如何从一个巨大的(scipy.sparse)矩阵计算对角矩阵?

Posted

技术标签:

【中文标题】如何从一个巨大的(scipy.sparse)矩阵计算对角矩阵?【英文标题】:How to calculate diagonal degree matrix from a huge (scipy.sparse) matrix? 【发布时间】:2012-01-18 05:44:02 【问题描述】:

给定一个 100 万维的二次矩阵,我想计算对角度矩阵。

对角度矩阵被定义为一个对角矩阵,它以每行非零值的计数作为条目。

矩阵,我们称它为A,格式为scipy.sparse.csr_matrix

如果我的机器有足够的功率,我会这样做

diagonal_degrees = []
for row in A:
    diagonal_degrees.append(numpy.sum(row!=0))

我什至尝试过,但结果是

ValueError: array is too big.

所以我尝试利用 scipy 的稀疏结构。我是这样想的:

diagonal_degrees = []
CSC_format = A.tocsc() # A is in scipys CSR format.
for i in range(CSC_format.shape[0]):
    row = CSC_format.getrow(i)
    diagonal_degrees.append(numpy.sum(row!=0))

我有两个问题:

    有没有更有效的方法,我可能忽略了? 而docs of scipy sparse state:

CSR、CSC 和 COO 格式之间的所有转换都是高效的线性时间操作。

为什么我会得到一个

SparseEfficiencyWarning: changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient.

从 CSR 更改为 CSC 时?

【问题讨论】:

csr_matrix 中设置项目时出现错误。 “改变稀疏结构”与不同稀疏矩阵格式之间的转换无关。当您添加“密集”项目时。 如果您只需要计算非零元素,nonzero 方法看起来很有希望。 正如@avaris 已经指出的那样,你可以这样做diag_deg, _ = np.histogram(x.nonzero()[0], np.arange(x.shape[0]+1)) @Joe:请把这个变成答案,我可以投票和接受。 在我看来,这真的应该是@Avaris 的,因为他是指出nonzero 的人。 【参考方案1】:

如果您只需要计算非零元素,nonzero 方法可能会很有用。

确切的代码是(在Joe Kington 和matehat 的帮助下):

diag_deg, _ = np.histogram(x.nonzero()[0], np.arange(x.shape[0]+1))

# generating a diagonal matrix with diag_deg
dim = x.shape[0]
diag_mat = np.zeros((dim**2, ))
diag_mat[np.arange(0, dim**2, dim+1)] = diag_deg
diag_mat.reshape((dim, dim))

尽管对于大型数组 (dim ~ 1 million),如 Aufwind 所述,np.zeros((dim**2, )) 给出了例外:ValueError: Maximum allowed dimension exceeded。另一种解决方法是使用稀疏矩阵:

diag_mat = sparse.coo_matrix((dim, dim))
diag_mat.setdiag(diag_deg)

【讨论】:

只是为了增加一个很好的解决方案,如果想从diag_deg生成对角矩阵,他可以写diag_mat = np.zeros((x.shape[0]**2, ))然后diag_mat[np.arange(0, x.shape[0]**2, x.shape[0]+1)] = diag_deg最后diag_mat.reshape((x.shape[0], x.shape[0]))。抱歉代码稀疏……我不想为此创建新答案;) @matehat:感谢您完成解决方案。当dim 太高时,让dim = x.shape[0] 不幸的是np.zeros((dim**2,)) 导致ValueError: Maximum allowed dimension exceeded。就我而言,dim 大约是 一百万。所以在处理高维矩阵时应该选择另一种方式。例如:diag_mat = sparse.coo_matrix((dim,dim)),然后是diag_mat.setdiag(diag_deg) @Avaris:也许您想将这两个 cmets 合并到您的答案中。因此,对于面临类似问题的人来说,它变得更加完整和更好地阅读。 @Aufwind:会的。感谢您的通知。

以上是关于如何从一个巨大的(scipy.sparse)矩阵计算对角矩阵?的主要内容,如果未能解决你的问题,请参考以下文章

scipy.sparse 矩阵的元素功率

Scipy sparse的CSC矩阵总结

使用 scipy.sparse.bmat 从子块创建非常大的稀疏矩阵时出错

Python scipy.sparse矩阵使用方法

Python scipy.sparse矩阵使用方法

scipy.sparse.linalg.spsolve Linux 系统上大型稀疏矩阵的令人惊讶的行为