Python 计算scipy csr矩阵中的欧氏距离
我需要计算存储在csr稀疏矩阵和一些点列表中的所有点之间的欧氏距离。对我来说,将csr转换为稠密的csr会更容易,但由于内存不足,我无法将其转换为稠密的csr,因此我需要将其保留为csr 例如,我有一个数据\u csr稀疏矩阵(csr和稠密视图): 这个中心列出了一些点:Python 计算scipy csr矩阵中的欧氏距离,python,sparse-matrix,euclidean-distance,Python,Sparse Matrix,Euclidean Distance,我需要计算存储在csr稀疏矩阵和一些点列表中的所有点之间的欧氏距离。对我来说,将csr转换为稠密的csr会更容易,但由于内存不足,我无法将其转换为稠密的csr,因此我需要将其保留为csr 例如,我有一个数据\u csr稀疏矩阵(csr和稠密视图): 这个中心列出了一些点: center array([[0, 1, 2, 2, 4, 1], [3, 4, 1, 2, 4, 0]]) 使用scipy.spatial包,data_csr和center之间的欧几里德距离数组如下所示。因此,
center
array([[0, 1, 2, 2, 4, 1],
[3, 4, 1, 2, 4, 0]])
使用scipy.spatial
包,data_csr和center之间的欧几里德距离数组如下所示。因此,根据数据中的所有行计算中心每行总共6个点中的每个点。结果数组(2,5)的第一行是数据_csr中第一行中心和所有行之间的ED
到目前为止,我所学到的是,我可以通过以下方式获得非零值和索引:
data_csr.data
array([4, 1, 2, 2, 1, 1, 4, 3, 2])
data_csr.indices
array([2, 0, 4, 0, 3, 5, 0, 2, 3])
但我仍然不知道如何计算这两个对象之间的ED。因此,让我们创建您的矩阵(很遗憾,您没有提供我可以复制粘贴的输入)
csr
在数据
、索引
和indptr
数组中存储相同的信息。但是你必须做一些数学运算,才能得出最后2个变量的i,j
值csr
乘法例程充分利用了这些数组
一般来说,使用csr
矩阵进行乘法比加法/减法更好
我等待进一步澄清
我们需要做的是研究这个函数,了解它的输入。我们可能不得不超越它的文档,看看代码 但看看这段代码,我看到了确保
xB
是2d数组的步骤,列数与xA
相同。然后它调用
_distance_wrap.cdist_euclidean_wrap(_convert_to_double(XA),
_convert_to_double(XB), dm)
它看起来像一些C代码的包装器。我无法想象有什么办法可以给它提供稀疏矩阵
您可以迭代行;使用M[[0],:]调用dist
。A
与M.A[[0],:]相同,只是速度不同。迭代稀疏矩阵的行有点慢,因为每次迭代都必须构造一个新的稀疏矩阵csr
和lil
是行迭代中最快的两个
下面是一些可能更快的方法-直接迭代lil
格式的属性:
def foo(a,b,n):
# make a dense array from data,row
res = np.zeros((1,n))
res[0,b]=a
return res
In [190]: Ml=M.tolil()
In [191]: Ml.data
Out[191]: array([[4], [1, 2], [2, 1], [1], [4, 3, 2]], dtype=object)
In [192]: Ml.rows
Out[192]: array([[2], [0, 4], [0, 3], [5], [0, 2, 3]], dtype=object)
In [193]: rowgen=(foo(a,b,6) for a,b in zip(Ml.data,Ml.rows))
In [194]: np.concatenate([spatial.distance.cdist(center,row, 'euclidean') for row in rowgen],axis=1)
Out[194]:
array([[ 5.09901951, 3.87298335, 5.19615242, 5. , 5.91607978],
[ 7.34846923, 5.38516481, 5.91607978, 6.8556546 , 6.08276253]])
现在我将跳过时间测试。稀疏矩阵上的成对欧几里德距离在sklearn中实现(正如hpaulj所指出的,scipy实现在稀疏矩阵上不起作用)
hpaulj示例示例:
import scipy.sparse
import sklearn.metrics.pairwise
data = [4,1,2,2,1,1,4,3,2]
col = [0,1,1,2,2,3,4,4,4]
row = [2,0,4,0,3,5,0,2,3]
M = scipy.sparse.csr_matrix((data,(col,row)))
distances = sklearn.metrics.pairwise.pairwise_distances(M,M)
文档:如何计算数据与中心之间的ED(假设密集)?@Alexander我已经编辑了它,我使用了scipy.spatial.distance.cdist(中心,数据与中心,欧几里德),
我仍然无法复制您的结果来计算上述距离。关于如何从矩阵中提取数据,请参阅本文,这是我所掌握的。我已经编辑了这个案例,并解释了我是如何计算的,希望它足够清晰易懂。使用scipy.spatial.distance.cdist(中心,数据_csr,'euclidean')
只是为了理解稀疏矩阵上下文。我正在读这篇文章,似乎sklearn``成对距离
非常“低效”,但另一方面,这里似乎是一个不错的选择,你认为哪一个最快?
In [131]: M.tocoo().data
Out[131]: array([4, 1, 2, 2, 1, 1, 4, 3, 2])
In [132]: M.tocoo().col
Out[132]: array([2, 0, 4, 0, 3, 5, 0, 2, 3])
In [133]: M.tocoo().row
Out[133]: array([0, 1, 1, 2, 2, 3, 4, 4, 4])
spatial.distance.cdist(center,M.A, 'euclidean')
Out[156]:
array([[ 5.09901951, 3.87298335, 5.19615242, 5. , 5.91607978],
[ 7.34846923, 5.38516481, 5.91607978, 6.8556546 , 6.08276253]])
_distance_wrap.cdist_euclidean_wrap(_convert_to_double(XA),
_convert_to_double(XB), dm)
def foo(a,b,n):
# make a dense array from data,row
res = np.zeros((1,n))
res[0,b]=a
return res
In [190]: Ml=M.tolil()
In [191]: Ml.data
Out[191]: array([[4], [1, 2], [2, 1], [1], [4, 3, 2]], dtype=object)
In [192]: Ml.rows
Out[192]: array([[2], [0, 4], [0, 3], [5], [0, 2, 3]], dtype=object)
In [193]: rowgen=(foo(a,b,6) for a,b in zip(Ml.data,Ml.rows))
In [194]: np.concatenate([spatial.distance.cdist(center,row, 'euclidean') for row in rowgen],axis=1)
Out[194]:
array([[ 5.09901951, 3.87298335, 5.19615242, 5. , 5.91607978],
[ 7.34846923, 5.38516481, 5.91607978, 6.8556546 , 6.08276253]])
import scipy.sparse
import sklearn.metrics.pairwise
data = [4,1,2,2,1,1,4,3,2]
col = [0,1,1,2,2,3,4,4,4]
row = [2,0,4,0,3,5,0,2,3]
M = scipy.sparse.csr_matrix((data,(col,row)))
distances = sklearn.metrics.pairwise.pairwise_distances(M,M)