python - scikit-learn DBSCAN 内存使用情况

标签 python scikit-learn cluster-analysis data-mining dbscan

更新:最后,我选择用于对我的大型数据集进行聚类的解决方案是 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) 距离矩阵,这需要在内存方面和运行时方面都付出代价.

所以我看到了两个选择:

  1. 您可能想尝试 ELKI 中的 DBSCAN 实现。相反,当与 R*-tree 索引一起使用时,它通常比简单的实现要快得多。

  2. 否则,您可能需要重新实现 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/

相关文章:

python - DBSCAN 中的预计算距离矩阵

python - 在 python 中将一个文本文件聚类为组和主题

python - 创建python 2.7 conda环境设置python 3.5

python - scikit-learn 决策树是否支持无序的 ('enum' ) 多类特征?

python - 分割字符串并用成分替换原始字符串

python - Pandas:将 DataFrame 转换为每个单元格的均值和标准差

dataset - 多维数据聚类

matlab - mat2gray对multithresh的影响

Python numpy 在 cmd 行中找到,但在脚本中没有

python - Heroku:使用 RQ 在 Python 中执行后台任务