scipy 稀疏 CSR 矩阵的快速切片和乘法
Fast slicing and multiplication of scipy sparse CSR matrix
我有一个 scipy 稀疏 CSR
矩阵,大小为 2M x 50k,具有 200M 非零值(每行 100 个)。我需要通过(随机分布的)索引(pandas 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
。
问题:
为什么按行对 CSR 矩阵进行切片这么慢?整个矩阵的乘法甚至比它花费的时间更少。
有没有办法更快达到最终结果?
我在中解释过,这种行索引实际上是用矩阵乘法进行的。实际上,它为所需的行构造了一个带 1 的稀疏向量,并执行适当的 dot
.
所以我对操作顺序无关紧要并不感到惊讶。
一般来说,稀疏矩阵不是为高效索引而设计的。例如,他们没有 return 视图。 csr
矩阵乘法是其最有效的操作之一。甚至行或列的总和也是通过矩阵乘法执行的。
我 运行 遇到了同样的问题,我的解决方案是编写一个依赖于 numpy 数组索引而不是稀疏矩阵乘法的行提取器。 See my approach here.
如果您有足够的 RAM 内存,您可以转换 tolil() 并且切片应该更快。
我有一个 scipy 稀疏 CSR
矩阵,大小为 2M x 50k,具有 200M 非零值(每行 100 个)。我需要通过(随机分布的)索引(pandas 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
。
问题:
为什么按行对 CSR 矩阵进行切片这么慢?整个矩阵的乘法甚至比它花费的时间更少。
有没有办法更快达到最终结果?
我在dot
.
所以我对操作顺序无关紧要并不感到惊讶。
一般来说,稀疏矩阵不是为高效索引而设计的。例如,他们没有 return 视图。 csr
矩阵乘法是其最有效的操作之一。甚至行或列的总和也是通过矩阵乘法执行的。
我 运行 遇到了同样的问题,我的解决方案是编写一个依赖于 numpy 数组索引而不是稀疏矩阵乘法的行提取器。 See my approach here.
如果您有足够的 RAM 内存,您可以转换 tolil() 并且切片应该更快。