Python中具有大稀疏矩阵的kNN

Python中具有大稀疏矩阵的kNN,python,scikit-learn,sparse-matrix,nearest-neighbor,Python,Scikit Learn,Sparse Matrix,Nearest Neighbor,我有两个大型稀疏矩阵: In [3]: trainX Out[3]: <6034195x755258 sparse matrix of type '<type 'numpy.float64'>' with 286674296 stored elements in Compressed Sparse Row format> In [4]: testX Out[4]: <2013337x755258 sparse matrix of type '&

我有两个大型稀疏矩阵:

In [3]: trainX
Out[3]: 
<6034195x755258 sparse matrix of type '<type 'numpy.float64'>'
        with 286674296 stored elements in Compressed Sparse Row format>

In [4]: testX
Out[4]: 
<2013337x755258 sparse matrix of type '<type 'numpy.float64'>'
        with 95423596 stored elements in Compressed Sparse Row format>
即使预测一个
testX
项目也需要一段时间(即大约30-60秒,但如果乘以200万,这几乎是不可能的)。我的16GB内存的笔记本电脑开始交换一些内存,但在
testX
中成功完成了1项

我的问题是,如何才能在合理的时间内完成?比如说在一个大型EC2实例上的一个晚上?仅仅是拥有更多的RAM并阻止交换就足够快了(我猜不是)。也许我可以利用稀疏性来加速计算


谢谢。

经典的kNN数据结构,如
sklearn
中使用的KD树,在数据维度增加时会变得非常缓慢。对于高维问题,建议切换算法类并使用近似最近邻(ANN)方法,不幸的是,
sklearn
似乎缺乏这种方法。有关算法和理论的论文,请参阅下面的链接,了解为什么在这些情况下,近似近邻速度会快得多

    <> L.> P>一个著名的在C++世界中的ANN库,广泛应用于计算机视觉中的特征描述符空间中的最近邻。主页上说它包含Python绑定(那时我从未使用过)

  • 另一个流行的替代方案是带有Python包装器的库,尽管较新的FLANN目前似乎更受欢迎

  • 另请参见(但有些链接已失效)

一个警告:您的数据似乎是非常高维的——我不知道这些库对您的性能如何。他们仍然应该击败sklearn

即使预测一项testX也需要一段时间(比如30-60秒,但是如果乘以200万,这几乎是不可能的)

这正是所有scikit学习估计器在其
predict
方法中批量采样的原因。如果您在一次调用中传递多个样本,那么输入验证和Python缓慢循环的成本就会降低,因此每个样本的时间会比一个样本的成本乘以样本数的时间少得多

>>> from sklearn.datasets import fetch_20newsgroups_vectorized
>>> from sklearn.decomposition import TruncatedSVD
>>> from sklearn.neighbors import KNeighborsClassifier
>>> data = fetch_20newsgroups_vectorized()
>>> X, y = data['data'], data['target']
>>> X = TruncatedSVD(n_components=100).fit_transform(X)
>>> clf = KNeighborsClassifier(n_neighbors=1).fit(X, y)
>>> %timeit clf.predict(X[0])
1000 loops, best of 3: 766 us per loop
>>> %timeit clf.predict(X[0:10])
100 loops, best of 3: 2.44 ms per loop
>>> %timeit clf.predict(X[0:100])
100 loops, best of 3: 14.2 ms per loop
>>> %timeit clf.predict(X[0:1000])
10 loops, best of 3: 117 ms per loop
也许我可以利用稀疏性来加速计算

您可以从训练集中取样,而不是全部使用。k-NN的性能取决于训练集的大小,这就是为什么普通k-NN算法不是文本分类的好选择


(文本处理领域最喜欢的技巧是使用磁盘索引构建k-NN分类器,例如Lucene:使用整个文档作为查询,检索前k个文档,从中确定标签。)

据我所知,FLANN和ANN都不能很好地处理稀疏数据。我刚刚发布了一个新的C++库,用于KNN搜索,用于通用数据类型和通用相似性度量在www. kgCop.Org。你所要做的就是插入你的函数,计算对象i和对象j之间的相似性,库将完成剩下的工作。缺点是,使用python可能无法获得很多好处。由于相似性计算代码将被极其频繁地调用,因此为用户提供的度量添加python API没有多大意义。

如果您正在寻找可伸缩的ANN算法,另一种途径是局部性敏感哈希(LSH)方法,如ITQ()。本文附带了一些MATLAB代码,但我之前已经将其翻译成python。请参阅OpenCV中的:

:谢谢您的帮助。我的数据是文本数据——我现在已经对其执行了LSA,以使其降到100维
sklearn
现在每个测试用例大约需要0.5秒,但对于2mil记录来说,这仍然太慢。我现在正在探索法兰,并将回到它的工作原理。100维应该是法兰的完美选择。vision中通常使用的描述符空间具有128个dim。如果我的答案解决了你的问题,请向上投票/接受(最近很多人似乎忘记了这一点)。@DCS没有忘记,仍在尝试。现在它工作得很好,谢谢。根据
算法
的文档,我认为批处理预测在这种情况下不会有多大帮助:使用蛮力拟合稀疏输入将覆盖此参数的设置。@Matt:因为它会对每个批而不是每个样本进行一次性能输入验证,而且它避免了Python的函数调用开销——这与稀疏和密集无关。另外,OP说他们已经对数据进行了LSA,LSA(
TruncatedSVD
)的输出总是一个密集数组。很抱歉,错过了那个数组。我只看了OP问题中的
trainX
。@larsmans感谢Lucene的提示,我以前从未听说过。如果你有很好的例子/文档可以在Python中使用它,我很想看看。@mchangun:有,还有我的。这表明在拟合稀疏矩阵时,实现使用“蛮力”,它计算所有对的距离。
>>> from sklearn.datasets import fetch_20newsgroups_vectorized
>>> from sklearn.decomposition import TruncatedSVD
>>> from sklearn.neighbors import KNeighborsClassifier
>>> data = fetch_20newsgroups_vectorized()
>>> X, y = data['data'], data['target']
>>> X = TruncatedSVD(n_components=100).fit_transform(X)
>>> clf = KNeighborsClassifier(n_neighbors=1).fit(X, y)
>>> %timeit clf.predict(X[0])
1000 loops, best of 3: 766 us per loop
>>> %timeit clf.predict(X[0:10])
100 loops, best of 3: 2.44 ms per loop
>>> %timeit clf.predict(X[0:100])
100 loops, best of 3: 14.2 ms per loop
>>> %timeit clf.predict(X[0:1000])
10 loops, best of 3: 117 ms per loop