更新:最后,我选择用于对我的大型数据集进行聚类的解决方案是 Anony-Mousse 下面建议的解决方案。也就是说,使用 ELKI 的 DBSCAN 实现我的聚类而不是 scikit-learn 的。它可以从命令行运行,并通过适当的索引,在几个小时内执行此任务。使用 GUI 和小样本数据集来制定您想要使用的选项,然后前往城镇。值得研究。任何人,请继续阅读我最初的问题的描述和一些有趣的讨论。
我有一个包含约 250 万个样本的数据集,每个样本包含 35 个我正在尝试聚类的特征(浮点值)。我一直在尝试使用 scikit-learn 的 DBSCAN 实现来做到这一点,使用曼哈顿距离度量和从数据中抽取的一些小随机样本估计的 epsilon 值。到目前为止,一切都很好。 (这里是片段,供引用)
db = DBSCAN(eps=40, min_samples=10, metric='cityblock').fit(mydata)
我目前的问题是我很容易耗尽内存。 (我目前正在使用 16 GB RAM 的机器)
我的问题是,DBSCAN 是否会在运行时即时计算成对距离矩阵,这就是吞噬我内存的原因? (250 万 ^ 2) * 8 字节显然大到愚蠢,我会理解的。我不应该使用 fit()
方法吗?更一般地说,有没有办法解决这个问题,或者我通常在这里吠叫错误的树?
如果答案很明显,我们深表歉意。这几天我一直在纠结这个问题。谢谢!
附录:另外,如果有人能更明确地向我解释 fit(X)
和 fit_predict(X)
之间的区别,我也将不胜感激——我'恐怕我只是不太明白。
附录 #2:可以肯定的是,我只是在一台内存约为 550 GB 的机器上尝试过,但它仍然崩溃,所以我觉得 DBSCAN 可能会尝试制作成对距离矩阵或我显然不知道的东西'不想让它这样做。我想现在最大的问题是如何阻止这种行为,或者找到其他可能更适合我需要的方法。谢谢你在这里陪我。
附录#3(!):我忘了附上回溯,在这里,
Traceback (most recent call last):
File "tDBSCAN.py", line 34, in <module>
db = DBSCAN(eps=float(sys.argv[2]), min_samples=10, metric='cityblock').fit(mydata)
File "/home/jtownsend/.local/lib/python2.6/site-packages/sklearn/base.py", line 329, in fit_predict
self.fit(X)
File "/home/jtownsend/.local/lib/python2.6/site-packages/sklearn/cluster/dbscan_.py", line 186, in fit
**self.get_params())
File "/home/jtownsend/.local/lib/python2.6/site-packages/sklearn/cluster/dbscan_.py", line 69, in dbscan
D = pairwise_distances(X, metric=metric)
File "/home/jtownsend/.local/lib/python2.6/site-packages/sklearn/metrics/pairwise.py", line 651, in pairwise_distances
return func(X, Y, **kwds)
File "/home/jtownsend/.local/lib/python2.6/site-packages/sklearn/metrics/pairwise.py", line 237, in manhattan_distances
D = np.abs(X[:, np.newaxis, :] - Y[np.newaxis, :, :])
MemoryError
最佳答案
问题显然是 scikit-learn
中的非标准 DBSCAN 实现。
DBSCAN 不需要距离矩阵。该算法是围绕使用可以加速regionQuery
函数的数据库设计的,并有效地返回查询半径内的邻居(空间索引应该支持O(log n)中的此类查询
)。
然而,scikit
中的实现显然计算了完整的 O(n^2)
距离矩阵,这需要在内存方面和运行时方面都付出代价.
所以我看到了两个选择:
您可能想尝试 ELKI 中的 DBSCAN 实现。相反,当与 R*-tree 索引一起使用时,它通常比简单的实现要快得多。
否则,您可能需要重新实现 DBSCAN,因为在
scikit
中的实现显然不太好。不要害怕:DBSCAN 自己实现起来非常简单。一个好的 DBSCAN 实现中最棘手的部分实际上是regionQuery
函数。如果你能快速得到这个查询,DBSCAN 就会很快。您实际上也可以将此函数重用于其他算法。
更新:到目前为止,sklearn 不再计算距离矩阵,并且可以使用 kd-tree 索引等。但是,由于“矢量化”,它仍然会预先计算每个点的邻居,因此 sklearn 用于大 epsilon 的内存使用量为 O(n²),而据我了解,ELKI 中的版本只会使用O(n) 内存。因此,如果内存不足,选择较小的 epsilon 和/或尝试 ELKI .
关于python - scikit-learn DBSCAN 内存使用情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16381577/