我在机器学习和聚类分析方面不是很有经验,但我有以下问题:
我有~100kk-1000kk的数据,我无法一次性加载到内存中,我需要将它分成多个类(如1-10k甚至100k类)以便进一步分析。为此,我选择了在OpenIMAJ库(FloatKMeans类)中实现的K-Means算法。 据我所知,K-Means算法可分为两个阶段:
我打算使用Hadoop reduce阶段构建集群模型,我将逐个接收数据(这就是为什么我不能同时将数据传递给算法)
我的问题是:
感谢您的帮助
答案 0 :(得分:2)
K-Means聚类是一种迭代算法,可以对数据进行多次传递。在每次传递中,将点指定给聚类质心,然后在指定所有点之后,将聚类质心重新计算为指定点的平均值。你不能"流"传统意义上的算法数据,因为您需要在后续迭代过程中回到它。
关于OpenIMAJ FloatKMeans
实施:是的,这可以处理大数据"从某种意义上说,它并不介意从哪里获取数据 - 它所需的DataSource
实例可以在必要时从磁盘读取数据。唯一的要求是您可以在算法运行期间将所有质心保存在内存中。实现是多线程的,因此在计算过程中可以使用所有cpu内核。这里有示例代码:https://github.com/openimaj/openimaj/blob/master/demos/examples/src/main/java/org/openimaj/examples/ml/clustering/kmeans/BigDataClusterExample.java。
OpenIMAJ IOUtils.writeBinary(...)
方法可用于在FloatCentroidsResult
对象中保存结果集群质心。
K-Means中最大的成本之一是计算每个数据点与每个聚类质心之间的距离,以便找到最接近的数据点。其成本与数据的维数和质心的数量有关。如果你有大量的质心和高维数据,那么使用近似的K-Means实现可以获得很大的速度效益,但代价是精度略有下降(例如,参见FloatKMeans.createKDTreeEnsemble()
- 这使用了一组KD-Trees来加速邻居计算)。
关于与Hadoop的集成,可以将K-Means实现为一系列Map-Reduce任务(每对对应于算法的迭代)。请参阅此文章以进行讨论:http://eprints.soton.ac.uk/344243/1/paper.pdf。如果你想沿着这条路走下去,OpenIMAJ在这里有一个非常粗略的实现,你可以建立起来:https://github.com/openimaj/openimaj/tree/master/hadoop/tools/HadoopFastKMeans。如链接文章中所述,Apache Mahout还包含一个实现:https://mahout.apache.org。这两种实现的一个问题是它们需要在映射器和reducer之间传输相当多的数据(每个映射器发出当前数据点及其分配的簇ID)。这可能意味着使用算法的非Hadoop实现可能会更快,但这取决于您可用的处理资源和数据集的性质。可以通过聪明的Hadoop Combiner
来减少map和reduce之间的数据传输问题,并从数据的子集计算加权质心,然后将这些质心传递给(修改的)reducer以计算实际的质心。