快速切片和乘法的scipy稀疏CSR矩阵



我有一个大小为 2M x 50k 的 scipy 稀疏CSR矩阵,具有 200M 的非零值(每行 100 个(。我需要用一个(随机分布的(索引(这是一个熊猫Series(对 120k 行进行切片,然后将该子矩阵乘以大小为 1x50k 的稀疏向量(也有 100 个非零值(。

我这样做:

slice = matrix[index.tolist(), :]
result = slice.dot(vector.T).T.toarray()[0]  # returns 1x120k array

切片需要0.7s(慢(,然后乘法需要0.05s

相反,我可以先将整个矩阵相乘,然后对结果进行切片:

result = matrix.dot(vector.T).T.toarray()[0]
result_sliced = result[index.tolist()]  # returns 1x120k array

在这种情况下,乘法需要0.65s,然后切片需要0.015s

问题:

  1. 为什么按行对 CSR 矩阵进行切片如此缓慢?即使整个矩阵的乘法花费的时间也比它少。

  2. 有没有办法更快地实现最终结果?

我在使用 list of int 的稀疏矩阵切片中解释说,这种行索引实际上是通过矩阵乘法执行的。 实际上,它为所需的行构造了一个带有 1 的稀疏向量,并执行适当的dot

所以我并不感到惊讶,操作的顺序并不重要。

通常,稀疏矩阵不是为高效索引而设计的。 例如,它们不返回视图。 csr矩阵乘法是其最有效的操作之一。 偶数行或列的总和通过矩阵乘法执行。

我遇到了同样的问题,我的解决方案是编写一个依赖于 numpy 数组索引而不是稀疏矩阵乘法的行提取器。在这里查看我的方法。

如果你有足够的 RAM 内存,你可以转换 tolil(( 和切片应该更快。

最新更新