当尝试从下面求解大型的稀疏线性方程组时,我只得到了MemoryError:
。我该如何解决这个问题?
此外,该代码基于Matlab的实现,应该可以正常运行。在原始版本中,M
是一个三维矩阵,我不知道是否由于修改将M
转换为二维scipy.sparse.lil_matrix
(而不是{ {1}})st我可以迭代地填写coo
。
M
这是我得到的错误的回溯:
def dectrans(features, faces, template):
"""
Decode transformation matrix.
features : shape (3*N) numpy.ndarray
faces : (Nx3) array
template : (Nx3) array
"""
ftrs = features
weight = 1
fixvertex = 1
fixto = np.zeros((3))
# M shape originally (len(template), len(template), 10 * len(template))
M = scipy.sparse.lil_matrix((len(template)+fixvertex, len(template) * 10 * len(template)))
dx = scipy.sparse.lil_matrix((len(template)+fixvertex,3))
# build laplacian system
for i in range(len(faces)):
v = faces[i,:]
...
M[v][:,v] = M[v][:,v] + WIJ # WIJ some 3x3 matrix
dx[v,:] = dx[v,:] + WIJ.dot(x.T)
weight = np.ones((fixvertex)) * weight
for i in range(fixvertex):
M[len(template)+i, fixvertex-1] = weight[i]
dx[len(template):len(template),:] = fixto.dot(np.tile(weight, (3)))
M = np.real(M)
dx = np.real(dx)
Mt = M.T
model = scipy.sparse.linalg.spsolve(Mt @ M, Mt.dot(dx)) # here I get the error
return model
答案 0 :(得分:2)
回溯应该显示问题是出在spsolve
上还是在创建一个或两个自变量Mt@M
或Mt.dot(dx)
时。
具有M
和dx
形状的((6891, 474721000)
,(6891, 3)
Mt@M
(474721000,6891) + (6891, 474721000) => (474721000, 474721000)
Mt.dot(dx) # why not Mt@dx?
(474721000,6891) + (6891, 3) => (474721000, 3)
取决于这些变量中的非零结构,@乘积可能比M
具有更多的非零,这可能会产生内存错误。一个或另一个的追溯可能有助于我们进行诊断。
更常见的是,内存错误是由于尝试从稀疏数组创建密集数组而引起的,但在这里似乎确实如此。但是再次,追溯可以帮助排除这种情况。
如果逐步填充矩阵值,建议使用 lil
格式。 csr
用于矩阵乘积,但是sparse
可以根据需要将lil
转换为csr
。所以这不应该是一个问题。
===
使用1个非零元素创建稀疏矩阵:
In [263]: M=sparse.lil_matrix((1000,100000))
In [264]: M
Out[264]:
<1000x100000 sparse matrix of type '<class 'numpy.float64'>'
with 0 stored elements in LInked List format>
In [265]: M[0,0]=1
In [266]: M
Out[266]:
<1000x100000 sparse matrix of type '<class 'numpy.float64'>'
with 1 stored elements in LInked List format>
此@
不会产生内存错误,并且如预期的那样,结果只有1个非零项。但是运行此程序存在明显的延迟,这表明它正在进行大量计算:
In [267]: M.T@M
Out[267]:
<100000x100000 sparse matrix of type '<class 'numpy.float64'>'
with 1 stored elements in Compressed Sparse Row format>
在等效的@
上执行相同的csr
不会造成时间延迟:
In [268]: M1=M.tocsr()
In [269]: M1.T@M1
Out[269]:
<100000x100000 sparse matrix of type '<class 'numpy.float64'>'
with 1 stored elements in Compressed Sparse Column format>
===
您提到了MATLAB中的3d稀疏矩阵。您必须使用某种第三方扩展或变通方法,因为MATLAB稀疏限制为2d(至少是我几年前在FEM工作中使用它的时候)。
scipy.sparse
csc
格式类似于MATLAB的内部稀疏格式。实际上,这就是通过save
和scipy.io.loadmat
传输矩阵所得到的。 csr
与之类似,但具有行方向。
当我在MATLAB中创建FEM刚度矩阵时,我使用了scipy
coo
输入的等效项。也就是说,创建data
,row
和col
的3个数组。将coo
转换为csr
时,将添加重复元素,从而巧妙地处理FEM元素的子矩阵重叠。 (此行为在scipy
和MATLAB中是相同的。
按照您的要求反复添加lil
矩阵(如果索引正确的话),但是我希望它会慢得多。