首页 文章

Python - scipy稀疏矩阵的高效函数

提问于
浏览
0

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

给定一个非常大的长稀疏向量列表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

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

非常感谢!

2 回答

  • 0

    我修改了你的功能并运行它

    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<YM . 看起来像稀疏没有像 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()的问题有重叠

  • 0

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

    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()
    

相关问题