【发布时间】:2019-10-06 20:07:52
【问题描述】:
当试图从下面求解大型、稀疏的线性方程组时,我只得到一个MemoryError:。我该如何解决这个问题?
此外,此代码基于 Matlab 中的实现,应该可以正常运行。在原始版本中,M 是一个三维矩阵,我不知道是否会因为我的修改将M 转换为二维scipy.sparse.lil_matrix(而不是coo)而出现内存问题。我可以反复填写M in。
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
这是我得到的错误的回溯:
MemoryError Traceback (most recent call last)
<ipython-input-10-9aa6e73eb179> in <module>
20 rr = encrelrot(v_positions, faces, r_v_positions, f_neighbors)
21
---> 22 modelout = dectrans(decrelrot(rr, f_neighbors), faces, r_v_positions)
<ipython-input-8-cdb51dd3cadf> in dectrans(features, faces, template)
616 print("Size dx", dx.nnz)
617 #M = M.tocsr()
--> 618 model = scipy.sparse.linalg.spsolve(Mt @ M, Mt.dot(dx))
619
620 return model
~/anaconda3/lib/python3.6/site-packages/scipy/sparse/base.py in __matmul__(self, other)
560 raise ValueError("Scalar operands are not allowed, "
561 "use '*' instead")
--> 562 return self.__mul__(other)
563
564 def __rmatmul__(self, other):
~/anaconda3/lib/python3.6/site-packages/scipy/sparse/base.py in __mul__(self, other)
480 if self.shape[1] != other.shape[0]:
481 raise ValueError('dimension mismatch')
--> 482 return self._mul_sparse_matrix(other)
483
484 # If it's a list or whatever, treat it like a matrix
~/anaconda3/lib/python3.6/site-packages/scipy/sparse/compressed.py in _mul_sparse_matrix(self, other)
494 other.indptr, other.indices),
495 maxval=M*N)
--> 496 indptr = np.empty(major_axis + 1, dtype=idx_dtype)
497
498 fn = getattr(_sparsetools, self.format + '_matmat_pass1')
MemoryError:
【问题讨论】:
-
您能打印出
Mt、M和dx的大小并将它们与您的RAM 大小相关联吗?您可以尝试在生成错误的行之前处理Mt @ M和Mt.dot(dx)。此外,memory-profiler 可以帮助您跟踪错误 -
谢谢,这是一个很好的建议。
sys.getsizeof(M)以及dx返回 56 个字节。我有 521MB 的可用 RAM。显然处理Mt @ M会导致此错误。 -
那么
Mt的大小呢? -
Mt具有相同的 56 字节大小。您认为在具有更多可用内存的另一台计算机上运行代码可能会解决此问题吗? -
不,这些是非常小的矩阵(抱歉,我没有注意到
Mt只是M转置...)。尝试在产生错误之前的那一行,计算MtM = Mt.matmul(M)和MtDx = Mt.dot(dx)并重写model = scipy.sparse.linalg.spsolve(MtM, MtDx)以查看是否有其他错误。
标签: python matlab numpy scipy sparse-matrix