Csr_matrix.dot与Numpy.dot

时间:2015-07-28 11:56:56

标签: python numpy scipy sparse-matrix

我有一个大的( n = 50000 )块对角csr_matrix M ,表示一组图的邻接矩阵。我必须多次使用密集numpy.array v 乘以 M 。因此我使用M.dot(v)

令人惊讶的是,我发现首先将 M 转换为numpy.array然后使用numpy.dot要快得多。

为什么会这样呢?

1 个答案:

答案 0 :(得分:4)

我没有足够的内存来在内存中保存50000x50000密集矩阵并将其乘以50000向量。但是在这里找到一些维度较低的测试。

设定:

import numpy as np
from scipy.sparse import csr_matrix

def make_csr(n, N):
    rows = np.random.choice(N, n)
    cols = np.random.choice(N, n)
    data = np.ones(n)
    return csr_matrix((data, (rows, cols)), shape=(N,N), dtype=np.float32)

上面的代码在n矩阵中生成具有NxN非零元素的稀疏矩阵。

矩阵

N = 5000

# Sparse matrices
A = make_csr(10*10, N)     # ~100 non-zero
B = make_csr(100*100, N)   # ~10000 non-zero
C = make_csr(1000*1000, N) # ~1000000 non-zero
D = make_csr(5000*5000, N) # ~25000000 non-zero
E = csr_matrix(np.random.randn(N,N), dtype=np.float32) # non-sparse

# Numpy dense arrays
An = A.todense()
Bn = B.todense()
Cn = C.todense()
Dn = D.todense()
En = E.todense()

b = np.random.randn(N)

时序:

>>> %timeit A.dot(b)       # 9.63 µs per loop
>>> %timeit An.dot(b)      # 41.6 ms per loop

>>> %timeit B.dot(b)       # 41.3 µs per loop
>>> %timeit Bn.dot(b)      # 41.2 ms per loop

>>> %timeit C.dot(b)       # 3.2 ms per loop
>>> %timeit Cn.dot(b)      # 41.2 ms per loop

>>> %timeit D.dot(b)       # 35.4 ms per loop
>>> %timeit Dn.dot(b)      # 43.2 ms per loop

>>> %timeit E.dot(b)       # 55.5 ms per loop
>>> %timeit En.dot(b)      # 43.4 ms per loop
  • 对于高度稀疏的矩阵(AB),它的速度提高了1000x倍。
  • 对于不是非常稀疏的矩阵(C),它仍然会获得10x加速。
  • 对于几乎不稀疏的矩阵(D由于索引中的重复会有一些0,但概率上说不是很多),它仍然更快,而不是很多,但更快。
  • 对于真正的非稀疏矩阵(E),操作速度较慢,但​​速度不会太慢。

结论:您获得的加速取决于矩阵的稀疏性,但使用N = 5000稀疏矩阵总是更快(只要他们有一些条目)。

由于内存问题,我无法为N = 50000尝试。您可以尝试使用上面的代码,并使用N查看您的内容。