【问题标题】:Efficient sparse matrix column change高效的稀疏矩阵列变化
【发布时间】:2020-05-22 05:09:42
【问题描述】:

我正在实施一种高效的 PageRank 算法,因此我使用的是稀疏矩阵。我很接近,但有一个问题。我有一个矩阵,我希望每列的总和为一。这很容易实现,但是当我得到一个零列的矩阵时就会出现问题。

在这种情况下,我想将列中的每个元素设置为 1/(n-1),其中 n 是矩阵的维度。我除以 n-1 而不是 n,因为我希望始终保持对角线为零。

我怎样才能有效地实现这一点?我天真的解决方案是只确定每列的总和,然后找到为零的列索引并用 1/(n-1) 值替换整个列,如下所示:

# naive approach (too slow!)
# M is my nxn sparse matrix where each column sums to one
col_sums = M.sum(axis=0)
for i in range(n):
   if col_sums[0,i] == 0:
      # set entire column to 1/(n-1)
      M[:, i] = 1/(n-1)
      # make sure diagonal is zeroed
      M[i,i] = 0

我的 M 矩阵非常非常非常大,这种方法根本无法扩展。我怎样才能有效地做到这一点?

【问题讨论】:

  • 使用csc 格式的矩阵可能比csr 更好。或进行转置(因此您正在处理行),并可能在设置行时转换为lil 格式。另一个想法是尝试一次设置所有0 列,至少设置1/n-1 值。添加非零值是最昂贵的步骤,因为它会改变稀疏性。简单地扩展现有的非零值相对便宜。
  • 尝试一次性设置值,比如用 cols = np.where(col_sums==0)[0] 计算零列,然后像 M[:,cols] = 1/ 那样进行赋值(n-1)。然后进行另一轮作业,将所有对角线都归零。您也许可以使用 M[np.arange(n),np.arange(n)] 或 np.diag_indices(n) 访问对角线。

标签: python-3.x algorithm numpy scipy sparse-matrix


【解决方案1】:

如果不重新分配和复制基础数据结构,就无法添加新的非零值。如果您希望这些零列非常常见(> 25% 的数据),您应该以其他方式处理它们,或者您最好使用密集数组。

否则试试这个:

import scipy.sparse

M = scipy.sparse.rand(1000, 1000, density=0.001, format='csr')

nz_col_weights = scipy.sparse.csr_matrix(M.shape, dtype=M.dtype)
nz_col_weights[:, M.getnnz(axis=0) == 0] = 1 / (M.shape[0] - 1)
nz_col_weights.setdiag(0)

M += nz_col_weights

这只有两个分配操作

【讨论】:

  • 谢谢。这很有帮助,但最终没有奏效,因为分配一个新的稀疏矩阵然后修改它的稀疏性太昂贵了。
  • 这使用与循环相同的内存量,并且是 Y 的解决方案。您应该做的是解决 X - 将十亿个相同数字的副本添加到稀疏矩阵是错误的。更改您的(回归?ml?)以在零列中假设统一权重。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-10
  • 2018-12-24
  • 1970-01-01
相关资源
最近更新 更多