求scipy.sparse.coo_matrix矩阵逆时触发RuntimeError:矩阵分解失败
解决scipy.sparse.coo_matrix求逆时的因式分解失败问题
可能原因及对应解决方案
1. 矩阵本身奇异(不可逆)
稀疏图邻接矩阵大概率是奇异的——比如无向图邻接矩阵通常非满秩,或存在全零行/列,直接求逆不存在。先验证矩阵可逆性:
import numpy as np import scipy.sparse # 转换为CSC格式方便行/列求和 adj_csc = adj.tocsc() # 检查零行 zero_rows = (adj_csc.sum(axis=1) == 0).ravel() print(f"零行数量: {zero_rows.sum()}") # 检查零列 zero_cols = (adj_csc.sum(axis=0) == 0).ravel() print(f"零列数量: {zero_cols.sum()}")
若存在零行/列,矩阵必然奇异。如果是图算法场景,你可能实际需要的是度矩阵的逆(对角矩阵,仅需对非零对角元取倒数),而非邻接矩阵的逆。
2. 矩阵格式与精度问题
scipy.sparse.linalg.inv依赖的SuperLU求解器对CSC/CSR格式兼容性更好,且float32精度可能引发数值不稳定问题,手动转换格式和精度:
from scipy.sparse.linalg import inv # 转换为CSC格式并提升精度到float64 adj_csc = adj.tocsc().astype(np.float64) try: Dinv = inv(adj_csc) except RuntimeError as e: print(f"报错: {e}")
3. 调整SuperLU求解器参数
若矩阵接近奇异但理论可逆,可调整求解器参数放宽阈值:
from scipy.sparse.linalg import splu import scipy.sparse adj_csc = adj.tocsc().astype(np.float64) # 配置参数:降低主元阈值,使用更优列置换策略 lu = splu(adj_csc, diag_pivot_thresh=1e-10, permc_spec='MMD_AT_PLUS_A') # 通过求解AX=I得到逆矩阵 I = scipy.sparse.eye(adj_csc.shape[0], format='csc') Dinv = lu.solve(I)
diag_pivot_thresh:值越小越易选择非对角主元,适配接近奇异的矩阵permc_spec='MMD_AT_PLUS_A':优化列置换,提升因式分解稳定性
4. 替代方案:使用伪逆
若矩阵确实奇异但需类似逆的矩阵,可使用Moore-Penrose伪逆(注意:大矩阵会占用极高内存):
from scipy.sparse.linalg import pinv Dinv_pinv = pinv(adj.tocsc().astype(np.float64))
内容的提问来源于stack exchange,提问作者AttaUllah
相关产品推荐
相关产品推荐

