为啥 Spark Mllib KMeans 算法非常慢?

Posted

技术标签:

【中文标题】为啥 Spark Mllib KMeans 算法非常慢?【英文标题】:Why is Spark Mllib KMeans algorithm extremely slow?为什么 Spark Mllib KMeans 算法非常慢? 【发布时间】:2016-06-01 10:18:37 【问题描述】:

我遇到了与post 相同的问题,但我没有足够的分数来添加评论。我的数据集有 100 万行,100 列。我也在使用 Mllib KMeans,它非常慢。事实上,这项工作永远不会完成,我必须杀死它。我在谷歌云(dataproc)上运行它。如果我要求较少数量的集群(k=1000),它就会运行,但仍然需要超过 35 分钟。我需要它运行 k~5000。我不知道为什么这么慢。考虑到工人/节点的数量和 100 万 x ~300,000 col 矩阵上的 SVD 需要约 3 分钟的时间,数据被正确划分,但是当涉及到 KMeans 时,它只是进入了一个黑洞。我现在尝试减少迭代次数(2 次而不是 100 次),但我觉得某处有问题。

KMeansModel Cs = KMeans.train(datamatrix, k, 100);//100 iteration, changed to 2 now. # of clusters k=1000 or 5000

【问题讨论】:

将 # 迭代更改为 2 没有任何区别。 凯,我有一个similar problem。然而,就我而言,这项工作只是挂起,不仅仅是因为它很慢。在运行你的工作时你会看到任何进展,它会很慢,或者什么都不做,就像我的情况一样? 【参考方案1】:

看起来原因比较简单。您使用了相当大的 k 并将其与昂贵的初始化算法相结合。

默认情况下,Spark 使用 K-means++ 的分布式变体,称为 K-means|| (见What exactly is the initializationSteps parameter in Kmeans++ in Spark MLLib?)。分布式版本大约是 O(k),因此如果 k 较大,您可以预期启动较慢。这应该可以解释为什么在减少迭代次数时看不到任何改进。

在训练模型时使用大 K 也很昂贵。 Spark 使用的是 Lloyds 的变体,大致为 O(nkdi)

如果您期望数据结构复杂,那么很可能有比 K-Means 更好的算法来处理这个问题,但如果您真的想坚持使用它,您可以从使用随机初始化开始。

【讨论】:

你是说大部分时间都被这个“初始化”消耗掉了? 我说这是一个代价高昂的步骤,并且要考虑您所看到的行为。但更重要的是,用数千个集群训练 K-means 并不能很好地发挥作用。 刚刚运行了 5000 个 custer 的 spark 作业,随机初始化,7 分钟内完成!!惊人的!!现在我会去阅读论文,看看对准确性的影响。谢谢,又是零。至于集群的数量,我认为问题的维度更为关键->在非常高的暗淡中,每个点都与其他点“相距甚远”。除了执行速度之外,点的数量并不重要。 维度会影响输出,但由于不同的原因(算法和可用优化)并不会影响运行时间。但我很高兴它有帮助。【参考方案2】:

请尝试其他的 k-means 实现。像ELKI 中的一些变体方式 比 Spark 好,即使仅在单个 CPU 上也是如此。您会惊讶于您可以从单个节点中获得多少性能,而无需使用集群!根据我的实验,不幸的是,您至少需要一个 100 个节点的集群才能击败优秀的本地实现。

我读到these C++ versions 是多核(但单节点)并且可能是您现在可以找到的最快的 K-means,但我自己还没有尝试过(对于我的所有需求,ELKI 版本速度快得惊人,在我最大的数据集上几秒钟就完成了)。

【讨论】:

以上是关于为啥 Spark Mllib KMeans 算法非常慢?的主要内容,如果未能解决你的问题,请参考以下文章

spark.mllib源码阅读-聚类算法1-KMeans

如何用mapreduce分布式实现kmeans算法

从数据帧中激发 MLLib Kmeans,然后再返回

使用 Spark MLlib KMeans 从数据中预测集群

3 分钟学会调用 Apache Spark MLlib KMeans

Spark Mllib kmeans 示例,使用数据框而不是 textFile