2014-01-13 177 views
4

我想从scikit-learn的DictVectorizer返回的Scipy稀疏矩阵上计算最近邻居群集。但是,当我尝试使用scikit-learn计算距离矩阵时,我通过pairwise.euclidean_distancespairwise.pairwise_distances两个参数使用'euclidean'距离得到一条错误消息。我的印象是,scikit-learn可以计算这些距离矩阵。Scipy稀疏 - 距离矩阵(Scikit或Scipy)

我的矩阵高度稀疏,形状为:<364402x223209 sparse matrix of type <class 'numpy.float64'> with 728804 stored elements in Compressed Sparse Row format>

我也尝试过在Scipy中使用的方法,例如pdistkdtree,但是收到了其他错误,无法处理结果。

任何人都可以请我指出一个解决方案,将有效地让我计算距离矩阵和/或最近的邻居结果?

一些示例代码:

import numpy as np 
from sklearn.feature_extraction import DictVectorizer 
from sklearn.neighbors import NearestNeighbors 
from sklearn.metrics import pairwise 
import scipy.spatial 

file = 'FileLocation' 
data = [] 
FILE = open(file,'r') 
for line in FILE: 
    templine = line.strip().split(',') 
    data.append({'user':str(int(templine[0])),str(int(templine[1])):int(templine[2])}) 
FILE.close() 

vec = DictVectorizer() 
X = vec.fit_transform(data) 

result = scipy.spatial.KDTree(X) 

错误:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/site-packages/scipy/spatial/kdtree.py", line 227, in __init__ 
    self.n, self.m = np.shape(self.data) 
ValueError: need more than 0 values to unpack 

同样,如果我跑:

scipy.spatial.distance.pdist(X,'euclidean') 

我得到如下:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/site-packages/scipy/spatial/distance.py", line 1169, in pdist 
    [X] = _copy_arrays_if_base_present([_convert_to_double(X)]) 
    File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/site-packages/scipy/spatial/distance.py", line 113, in _convert_to_double 
    X = X.astype(np.double) 
ValueError: setting an array element with a sequence. 

最后,在运行NearestNeighbor使用scikit学习在一个内存错误的结果:

nbrs = NearestNeighbors(n_neighbors=10, algorithm='brute') 
+2

你会得到什么样的错误?你在运行什么代码? – jorgeca

+0

请将该信息编辑到您的问题中:一个显示您正在做什么的最简单示例,以及您获得的实际错误。 – jorgeca

+1

谢谢!现在看起来好多了。 – jorgeca

回答

2

首先,你不能使用KDTreepdist与稀疏矩阵,你必须把它转换为密(你的选择无论是您的选择):

>>> X 
<2x3 sparse matrix of type '<type 'numpy.float64'>' 
     with 4 stored elements in Compressed Sparse Row format> 

>>> scipy.spatial.KDTree(X.todense()) 
<scipy.spatial.kdtree.KDTree object at 0x34d1e10> 
>>> scipy.spatial.distance.pdist(X.todense(),'euclidean') 
array([ 6.55743852]) 

其次,从the docs

Efficient brute-force neighbors searches can be very competitive for small data samples. However, as the number of samples N grows, the brute-force approach quickly becomes infeasible.

您可能想尝试'ball_tree'算法并查看它是否可以处理您的数据。

+0

我最初尝试过球树,但它给出了一个警告,它必须恢复到强力算法。你知道任何基于Python的方法,它们实际上可以在这些维度的矩阵上计算稀疏距离矩阵吗? – user2694306

+3

@ user2694306您的**欧几里得**距离矩阵必须是密集的(可能没有任何零值,我猜),所以它必须跨越超过74 Gb的内存。我怀疑这是可能的。 – alko

0

从您的评论:

Since it is a sparse matrix, I would expect there to be solutions to intelligently calculate the distances and store the result in a similarly sparse matrix.

基本的数学证明,这是唯一可能在您输入矩阵包含重复的数量庞大的情况下,由于欧氏距离是两个完全相等的点只有零(此实际上是axioms of distance之一)。所以如果你删除重复这可能工作。

否则,根据您的问题,您可能能够使用sklearn.metrics.pairwise_distances_argmin_min或余弦相似度,X * X.T,它与欧几里得距离相比具有相反的顺序。