首页 文章

使用Scipy稀疏矩阵进行高效的矩阵更新和矩阵乘法

提问于
浏览
-1

我有一个大矩阵(236680 * 236680),我的电脑没有足够的内存来读取完整的矩阵,所以我正在考虑Scipy稀疏矩阵 . 我的目标是将生成的矩阵(非稀疏)乘以np.eye(观察次数)-np.ones(观察次数)/用稀疏矩阵观察的次数 .

在Scipy中,我使用以下代码,但计算仍然很大 . 我的问题包括:

  • 生成第一个矩阵,有没有其他方法来加速这个过程?

  • 用于矩阵乘法,有没有办法减少内存使用量,因为第一个矩阵不稀疏?

from scipy.sparse import lil_matrix
fline=5
nn=1/fline
M=lil_matrix((fline,fline))
M.setdiag(values=1-nn,k=0)
for i in range(fline)[1:]:
    M.setdiag(values=0-nn,k=i)
    M.setdiag(values=0-nn,k=-i)

#the first matrix is:
array([[ 0.8, -0.2, -0.2, -0.2, -0.2],
       [-0.2,  0.8, -0.2, -0.2, -0.2],
       [-0.2, -0.2,  0.8, -0.2, -0.2],
       [-0.2, -0.2, -0.2,  0.8, -0.2],
       [-0.2, -0.2, -0.2, -0.2,  0.8]])
#the second matrix is:
array([[0., 0., 0., 1., 0.],
      [0., 0., 0., 0., 0.],
      [0., 0., 0., 1., 0.],
      [0., 0., 0., 0., 0.],
      [1., 0., 1., 0., 0.]])
a2=M.dot(B)
#the final expected results
array([[-0.2,  0. , -0.2,  0.6,  0. ],
       [-0.2,  0. , -0.2, -0.4,  0. ],
       [-0.2,  0. , -0.2,  0.6,  0. ],
       [-0.2,  0. , -0.2, -0.4,  0. ],
       [ 0.8,  0. ,  0.8, -0.4,  0. ]])

更新:有没有办法提高跨产品的速度?测试Numpy dot和Scipy稀疏点函数 .

2 回答

  • 0

    对于第一个问题:数学上,

    arr1 = array([[ 0.8, -0.2, -0.2, -0.2, -0.2],
           [-0.2,  0.8, -0.2, -0.2, -0.2],
           [-0.2, -0.2,  0.8, -0.2, -0.2],
           [-0.2, -0.2, -0.2,  0.8, -0.2],
           [-0.2, -0.2, -0.2, -0.2,  0.8]])
    

    相当于

    arr1 = -0.2 * [[1,1,1,1,1,], + 1
                   [1,1,1,1,1,],     1
                   [1,1,1,1,1,],       1
                   [1,1,1,1,1,],         1
                   [1,1,1,1,1,]]           1
    
        = [1] [1, 1, 1, 1, 1] * 0.2 + 1
          [1]                           1
          [1]                             1
          [1]                               1
          [1]                                 1
    

    因此,它可以使用生成

    -0.2 * np.outer([1,1,1,1,1], [1,1,1,1,1]) + scipy.sparse.identity(5)
    

    对于第二个问题,让我滥用符号

    -0.2* [1] [1, 1, 1, 1, 1] @ B + scipy.sparse.identity(5) @ B 
          [1]
          [1]
          [1]
          [1]
    

    可以减少到

    np.outer([1, 1, 1, 1, 1], B.sum(axis=0)) * -0.2 + scipy.sparse.identity(5) @ B
    

    人们不需要真正计算 np.outer([1, 1, 1, 1, 1], B.sum(axis=0)) ,因为这将是一个内存可能不适合的密集方阵 . (请注意,外部产品基本上在其包含的每一行中重复 B.sum(axis=0) . )

    To recover the results in a memory efficient way ,您只需要存储 B.sum(axis=0)scipy.sparse.identity(5) @ B .

  • 1

    使用Scipy稀疏矩阵,因为其中一个matrics是稀疏矩阵,稀疏矩阵中的叉积函数是Numpy和Scipy之间最快的 .

    对于第一个问题,@ Tai的答案是基础,但我使用numpy.full函数(稍快一点) .

    对于第二个问题,使用划分整个矩阵并将较小的计算矩阵保存在文件中 .

    from scipy import sparse
    from scipy.sparse import vstack
    import h5sparse
    import numpy as num
    
    fline=236680
    nn=1/fline; dd=1-nn; off=0-nn
    div=int(fline/(61*10))
    
    for i in range(61*10):
        divM= num.full((fline, div), off) + sparse.identity(fline,format='csc')[:,0+div*i:div+div*i]
    
        vs=[]
        for j in range(divM.shape[1]):
            divMB=csr_matrix(divM.T[j]).dot(weights)
            vs.append(divMB)
        divapp=vstack(vs)
    
        if i ==0:
            h5f = h5sparse.File("F:/dissertation/dallastest/temp/tt1.h5")
            h5f.create_dataset('sparse/matrix', data=divapp, chunks=(389,),maxshape=(None,))        
        else:
            h5f['sparse/matrix'].append(divapp)
    

相关问题