如何从大型(scipy.sparse)矩阵计算对角度矩阵?

3 投票
1 回答
3796 浏览
提问于 2025-04-17 10:30

给定一个一百万维的方阵,我想计算它的对角度矩阵。

对角度矩阵是一个对角矩阵,它的每个元素表示每一行中非零值的数量。

这个矩阵我们称为 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))

我有两个问题:

  1. 有没有更有效的方法,我可能忽略了?
  2. 虽然 scipy sparse 的文档 说:

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

为什么在从 CSR 转换到 CSC 时我会得到一个

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

1 个回答

4

如果你只需要计算非零元素的数量,可以使用一个叫做 nonzero 的方法,这个方法会很有用。

具体的代码示例是这样的(感谢 Joe Kingtonmatehat 的帮助):

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)

撰写回答