Python MeanShift 内存错误
Posted
技术标签:
【中文标题】Python MeanShift 内存错误【英文标题】:Python MeanShift Memory Error 【发布时间】:2013-12-04 23:31:43 【问题描述】:我正在 sklearn.cluster
模块 (here are the docs) 中运行名为 MeanShift()
的聚类算法。我正在处理的对象有 310,057 个点分布在 3 维空间中。我正在运行它的计算机总共有 128Gb 的内存,所以当我收到以下错误时,我很难相信我实际上正在使用所有这些内存。
[user@host ~]$ python meanshifttest.py
Traceback (most recent call last):
File "meanshifttest.py", line 13, in <module>
ms = MeanShift().fit(X)
File "/home/user/anaconda/lib/python2.7/site-packages/sklearn/cluster/mean_shift_.py", line 280, in fit
cluster_all=self.cluster_all)
File "/home/user/anaconda/lib/python2.7/site-packages/sklearn/cluster/mean_shift_.py", line 99, in mean_shift
bandwidth = estimate_bandwidth(X)
File "/home/user/anaconda/lib/python2.7/site-packages/sklearn/cluster/mean_shift_.py", line 45, in estimate_bandwidth
d, _ = nbrs.kneighbors(X, return_distance=True)
File "/home/user/anaconda/lib/python2.7/site-packages/sklearn/neighbors/base.py", line 313, in kneighbors
return_distance=return_distance)
File "binary_tree.pxi", line 1313, in sklearn.neighbors.kd_tree.BinaryTree.query (sklearn/neighbors/kd_tree.c:10007)
File "binary_tree.pxi", line 595, in sklearn.neighbors.kd_tree.NeighborsHeap.__init__ (sklearn/neighbors/kd_tree.c:4709)
MemoryError
我正在运行的代码如下所示:
from sklearn.cluster import MeanShift
import asciitable
import numpy as np
import time
data = asciitable.read('./multidark_MDR1_FOFID85000000000_ParticlePos.csv',delimiter=',')
x = [data[i][2] for i in range(len(data))]
y = [data[i][3] for i in range(len(data))]
z = [data[i][4] for i in range(len(data))]
X = np.array(zip(x,y,z))
t0 = time.time()
ms = MeanShift().fit(X)
t1 = time.time()
print str(t1-t0) + " seconds."
labels = ms.labels_
print set(labels)
有人对正在发生的事情有任何想法吗?不幸的是,我无法切换聚类算法,因为这是我发现的唯一一个除了不接受链接长度/k 个聚类/先验信息之外做得很好的算法。
提前致谢!
**更新: 我又看了看文档,上面写着:
可扩展性:
因为这个实现使用了一个平面内核并且 一个球树来查找每个内核的成员,复杂度将是 在较低维度上为 O(T*n*log(n)),其中 n 为样本数 和 T 点数。在更高维度上,复杂性将 趋向于 O(T*n^2)。
可以通过使用更少的种子来提高可扩展性,例如使用 get_bin_seeds 函数中的 min_bin_freq 值较高。
请注意,estimate_bandwidth 函数的可扩展性远低于 均值偏移算法,如果使用它将成为瓶颈。
这似乎有些道理,因为如果您详细查看错误,它会抱怨估计带宽。这是否表明我只是在算法中使用了太多粒子?
【问题讨论】:
内存监视器(例如top
或free
)向您显示什么? (在top
中,按常驻内存排序:按 S 然后按 Q。)
是的,我已经这样做了,而且我只使用了总内存的 0.2%(即 128Gb)。它也几乎瞬间失败 - 这表明它是别的东西。我不明白它怎么能这么快使用这么多内存。
您是否尝试过以某种方式减小问题的大小?是否有已知的情况下一切正常,并且您可以测量使用的内存量?
【参考方案1】:
从错误消息来看,我怀疑它正在尝试计算点之间的所有成对距离,这意味着它需要 310057² 浮点数或 716GB 的 RAM。
您可以通过为 MeanShift
构造函数提供显式的 bandwidth
参数来禁用此行为。
这可以说是一个错误;考虑为其提交错误报告。 (包括我自己在内的 scikit-learn 团队最近一直在努力摆脱在各个地方这些过于昂贵的距离计算,但显然没有人关注 meanshift。)
编辑:上面的计算偏离了 3 倍,但内存使用量确实是二次方。我刚刚在 scikit-learn 的开发版中修复了这个问题。
【讨论】:
非常感谢您的帖子。我运行这个算法真的需要这么多内存吗?我已经用大约 30,000 个粒子完成了这项工作,我可以发誓它可以在具有 4GB RAM 的不同工作计算机上工作。我将使用 sklearn 提交错误。 @astromax:这个计算,按照目前的实现,创建一个 n² 64 位浮点数的数组。 30k² = 9e8,乘以 8 得到 6.7GB,所以这可能是可行的,但二次空间增长快速。 明白了。是否有非 n-squared 方法可以进入代码? @astromax:scikit-learn 是一个“doocracy”,即如果用户提交补丁,错误会得到最快的修复。顺便说一句,我只是看了一下代码,它似乎不完全是 n²,但肯定不止是线性的。 如何获取新代码?我必须要有开发者版本吗?以上是关于Python MeanShift 内存错误的主要内容,如果未能解决你的问题,请参考以下文章