【问题标题】:Python - Efficient Function with scipy sparse MatricesPython - 具有 scipy 稀疏矩阵的高效函数
【发布时间】:2016-08-31 13:48:44
【问题描述】:

对于一个项目,我需要一个高效的 p​​ython 函数来解决以下任务:

给定一个非常大的长稀疏向量列表 X(=> 大稀疏矩阵)和另一个包含单个向量 y 的矩阵 Y,我想要一个“距离”列表,y 对 X 的每个元素都有。特此“距离”是这样定义的:

比较两个向量的每个元素,总是取较低的一个并将它们相加。

例子:

X = [[0,0,2],   
     [1,0,0],
     [3,1,0]]

Y = [[1,0,2]]

函数应该返回 dist = [2,1,1]

在我的项目中,X 和 Y 都包含很多零,并作为以下实例出现:

<class 'scipy.sparse.csr.csr_matrix'>

到目前为止一切顺利,我设法编写了一个解决此任务的函数,但速度非常慢且效率极低。我需要一些关于如何高效处理/迭代稀疏矩阵的技巧。 这是我的功能:

def get_distances(X, Y):
   Ret=[]
   rows, cols = X.shape  

   for i in range(0,rows):
       dist = 0                
       sample = X.getrow(i).todense()
       test = Y.getrow(0).todense()    
       rows_s, cols_s = sample.shape     
       rows_t, cols_t = test.shape 

       for s,t in zip(range(0, cols_s), range(0, cols_t)):
           dist += min(sample[0,s], test[0,t])

       X_ret.append([dist])    

   return ret

为了进行操作,我将稀疏矩阵转换为密集矩阵,这当然很糟糕,但我不知道如何做得更好。你知道如何改进我的代码并使功能更快吗?

非常感谢!

【问题讨论】:

  • 您不仅将稀疏矩阵转换为稠密矩阵,而且还在密集矩阵上进行迭代。你能退后一步,用密集数组解决这个问题,使用数组操作吗?一旦这样做了,将动作转换为稀疏矩阵应该会更容易。
  • 当我运行你的代码时,更正了ret,我得到[[2], [0], [0]];你的函数也根本不使用Y
  • 对不起,我在变量“test”的声明中打错了。我改正了

标签: python performance scipy sparse-matrix


【解决方案1】:

我修改了你的函数并运行它

import numpy as np
from scipy import sparse

def get_distances(X, Y):
   ret=[]
   for row in X:            
       sample = row.A
       test = Y.getrow(0).A   
       dist = np.minimum(sample[0,:], test[0,:]).sum()
       ret.append(dist)    
   return ret

X = [[0,0,2],   
     [1,0,0],
     [3,1,0]]

Y = [[1,0,2]]

XM = sparse.csr_matrix(X)
YM = sparse.csr_matrix(Y)

print( get_distances(XM,YM))

print (np.minimum(XM.A, YM.A).sum(axis=1))

生产

1255:~/mypy$ python3 stack37056258.py 
[2, 1, 1]
[2 1 1]

np.minimum 采用元素最小的两个数组(可能是 2d),所以我不需要对列进行迭代。我也不需要使用索引。

minimum 也适用于稀疏矩阵,但是当我尝试将其应用于您的 X(3 行)和 Y(1)时,会出现分段错误。如果它们的大小相同,则可行:

Ys = sparse.vstack((YM,YM,YM))
print(Ys.shape)
print (XM.minimum(Ys).sum(axis=1))

将单行矩阵转换为数组也可以避免错误 - 因为它最终使用密集版本,np.minimum(XM.todense(), YM.A)

print (XM.minimum(YM.A).sum(axis=1))

当我在这两个矩阵上尝试其他元素操作时,我得到ValueError: inconsistent shapes,例如XM+YM,或XM&lt;YM。看起来 sparse 不像 numpy 数组那样实现广播。

=========================

多次复制1行稀疏矩阵的方式比较

In [271]: A=sparse.csr_matrix([0,1,0,0,1])

In [272]: timeit sparse.vstack([A]*3000).A
10 loops, best of 3: 32.3 ms per loop

In [273]: timeit sparse.kron(A,np.ones((3000,1),int)).A
1000 loops, best of 3: 1.27 ms per loop

很多时候,kronvstack 好。

=========================

Scipy sparse matrix alternative for getrow() 的问题存在重叠

【讨论】:

  • 谢谢。这对我帮助很大。您认为堆叠向量并在稀疏矩阵上使用最小函数比您发布的第一个解决方案更有效吗?
  • 我不知道。它需要在实际尺寸矩阵上进行计时。你试过XM.minimum(YM) 计算吗?您是否像我一样遇到分段错误?我正在考虑提交错误报告。
【解决方案2】:

试试下面的稀疏矩阵代码:

from scipy.sparse import csr_matrix, vstack
X = csr_matrix([[0,0,2],[1,0,0],[3,1,0]])
Y = csr_matrix([[1,0,2]])
def matrix_dist(x,y):
    y=vstack([y]*x.shape[1])
    return (((x+y)-(x-y).multiply((x-y).sign())).sum(1)/2).A.ravel()

【讨论】:

  • vstack 来自 scipy.sparse 而不是 numpy
猜你喜欢
  • 2016-06-16
  • 2017-02-12
  • 2015-03-26
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 2020-12-07
  • 2015-05-08
  • 1970-01-01
相关资源
最近更新 更多