Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么在求解稀疏线性方程组时会出现内存错误?_Python_Matlab_Numpy_Scipy_Sparse Matrix - Fatal编程技术网

Python 为什么在求解稀疏线性方程组时会出现内存错误?

Python 为什么在求解稀疏线性方程组时会出现内存错误?,python,matlab,numpy,scipy,sparse-matrix,Python,Matlab,Numpy,Scipy,Sparse Matrix,当我试图从下面解大型稀疏线性方程组时,我只得到一个内存错误:。我如何解决这个问题 此外,该代码基于Matlab中的一个实现,该实现应该运行良好。在原始版本中,M是一个三维矩阵,我不知道是否会因为我将M转换为二维scipy.sparse.lil_矩阵(而不是coo)s.t而出现内存问题。我可以迭代填充M def dectrans(features, faces, template): """ Decode transformation matrix. features :

当我试图从下面解大型稀疏线性方程组时,我只得到一个
内存错误:
。我如何解决这个问题

此外,该代码基于Matlab中的一个实现,该实现应该运行良好。在原始版本中,
M
是一个三维矩阵,我不知道是否会因为我将
M
转换为二维
scipy.sparse.lil_矩阵
(而不是
coo
)s.t而出现内存问题。我可以迭代填充
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

这是我得到的错误的回溯:

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: 
MemoryError回溯(最近一次调用)
在里面
20 rr=encrelrot(v_位置、面、r_v_位置、f_邻居)
21
--->22模型输出=dectrans(decrelrot(rr,f_邻居),面,r_v_位置)
在dectrans中(特征、面、模板)
616打印(“尺寸dx”,dx.nnz)
617#M=M.tocsr()
-->618 model=scipy.sparse.linalg.spsolve(Mt@M,Mt.dot(dx))
619
620返回模式
~/anaconda3/lib/python3.6/site-packages/scipy/sparse/base.py in_uuuuumatmul_uuuu(self,other)
560 raise VALUERROR(“不允许使用标量操作数,”
561“使用“*”代替”)
-->562返回自我(其他)
563
564定义(自身、其他):
~/anaconda3/lib/python3.6/site-packages/scipy/sparse/base.py in\uuuuu mul\uuuu(self,other)
480如果自我塑造[1]!=其他。形状[0]:
481提升值错误(“维度不匹配”)
-->482返回自多稀疏矩阵(其他)
483
484#如果它是一个列表或任何东西,请将其视为矩阵
矩阵中的~/anaconda3/lib/python3.6/site-packages/scipy/sparse/compressed.py(self,other)
494其他指数和其他指数),
495最大值=M*N)
-->496 indptr=np.empty(长轴+1,数据类型=idx\U数据类型)
497
498 fn=getattr(_sparsetools,self.format+'_matmatmat_pass1')
记忆错误:

回溯应该显示问题是在
spsolve中,还是在创建一个或两个参数时,
Mt@M
Mt.dot(dx)

带有
M
dx
形状
((6891474721000)
(6891,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>
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>
[268]中的
M1=M.tocsr()
In[269]:M1。T@M1                                                            
出[269]:
===

你提到了MATLAB中的3d稀疏矩阵。你必须使用某种第三方扩展或解决方法,因为MATLAB稀疏仅限于2d(至少在几年前用于FEM工作时是这样)

scipy.sparse
csc
格式类似于MATLAB的内部sparse。事实上,如果通过
save
scipy.io.loadmat
csr
传输矩阵,就会得到类似的结果,但具有行方向

当我在MATLAB中创建FEM刚度矩阵时,我使用了相当于
scipy
coo
输入的方法。也就是说,创建3个
数据数组
,和
。当
coo
转换为
csr
时,添加重复元素,巧妙地处理FEM e的子矩阵重叠元素。(此行为在
scipy
和MATLAB中相同)


重复添加
lil
矩阵(如果索引正确的话)应该可以工作,但我希望它会慢很多。

您能打印
Mt
M
dx
的大小,并将它们与RAM大小关联起来吗?您可以尝试处理
Mt@M
Mt.dot(dx)
在生成错误的行之前。另外,可以帮助您跟踪错误谢谢,这是一个很好的建议。
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)
查看是否有其他错误。回溯告诉我是
@
导致了此问题。我如何查看非零条目的数量?奇怪的是,
M.nnz
返回1。我认为
M[v][:,v]=
失败,原因我在另一个问题中解释过。因此,您只设置了
fixvertex
元素。因此
M.nnz
为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>
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>