使用 Scipy 稀疏矩阵的高效矩阵更新和矩阵乘法
Efficient matrix update and matrix multiplication using Scipy sparse matrix
我有一个大矩阵 (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 点和 Scipy 稀疏点函数。
对于第一个问题:数学上,
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)
。)
要以内存高效的方式恢复结果,您只需存储 B.sum(axis=0)
和 scipy.sparse.identity(5) @ B
。
Scipy使用了稀疏矩阵,因为其中一个矩阵是稀疏矩阵,而稀疏矩阵中的叉积函数是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)
我有一个大矩阵 (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 点和 Scipy 稀疏点函数。
对于第一个问题:数学上,
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)
。)
要以内存高效的方式恢复结果,您只需存储 B.sum(axis=0)
和 scipy.sparse.identity(5) @ B
。
Scipy使用了稀疏矩阵,因为其中一个矩阵是稀疏矩阵,而稀疏矩阵中的叉积函数是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)