Scipy稀疏矩阵乘法比numpy数组慢得多

Scipy稀疏矩阵乘法比numpy数组慢得多,numpy,scipy,sparse-matrix,Numpy,Scipy,Sparse Matrix,我构建了以下案例来测试一维稀疏矩阵乘法与numpy数组 from scipy.sparse import csc_matrix sp = csc_matrix((1, 36710)) sp[0,4162] = 0.2335 sp[0,21274] = 0.1367 sp[0,27322] = 0.261 sp[0,27451] = 0.9266 %timeit sp.dot(sp.T) arr = sp.toarray()[0] %timeit arr.dot(arr) 结果如下: 267

我构建了以下案例来测试一维稀疏矩阵乘法与numpy数组

from scipy.sparse import csc_matrix
sp = csc_matrix((1, 36710))
sp[0,4162] = 0.2335
sp[0,21274] = 0.1367
sp[0,27322] = 0.261
sp[0,27451] = 0.9266

%timeit sp.dot(sp.T)
arr = sp.toarray()[0]
%timeit arr.dot(arr)
结果如下:

267 µs ± 6.58 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
9.9 µs ± 230 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
此外,它们都比存储条目的普通dict和乘法的for循环慢(~1µs)


在尝试不同类型的稀疏矩阵(包括csr/coo)后,结果是相同的。为什么稀疏矩阵乘法比numpy密集数组乘法慢30倍?是因为矩阵太稀疏吗?

您的“向量”计算使用随机稀疏矩阵,默认稀疏度为0.01

In [523]: M = sparse.random(1,50000,format='csr')
In [524]: timeit M*M.T
479 µs ± 289 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [525]: A = M.A
In [526]: timeit np.dot(A,A.T)
40.1 µs ± 21.4 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
所以稀疏的速度要慢10倍<代码>(A*A).sum()乘以130µs

In [531]: M
Out[531]: 
<1x50000 sparse matrix of type '<class 'numpy.float64'>'
    with 500 stored elements in Compressed Sparse Row format>
[531]中的
:M
出[531]:
但是制作一个平方矩阵(具有5x非零项):

[537]中的
:M=sparse.random(500500,format='csr')
In[538]:M
出[538]:
In[539]:A=M.A
In[540]:timeit M*M
每个回路416µs±4.29µs(7次运行的平均值±标准偏差,每个1000个回路)
在[541]中:timeitA@A
每个回路13.4 ms±81.1µs(7次运行的平均值±标准偏差,每个100个回路)
现在稀疏有着巨大的速度优势

计算方法是如此的不同,以至于很难找到任何一种方法来解释时间差


在hpaulj的回答中,M*M不是矩阵乘法——它只是元素乘法。这就是为什么M*M比矩阵乘法快得多。因此,在所有情况下,csr矩阵的矩阵乘法速度都要慢得多。

有一个更快的解决方案:
sp.data.dot(sp.data)
3.3ns/循环,在这种情况下,您的解决方案将给出错误的答案。我想使用稀疏向量不会获得太多结果。如果使用稀疏矩阵(nxm,n,m>1),情况确实会发生变化。请尝试使用稀疏度为1%和10%的矩阵。这种情况可能过于稀疏,稀疏矩阵设置在实际计算中占主导地位。
M=sparse.random(250500,format='csr')
M*M
给出了
ValueError:维度不匹配
<代码>*
对于numpy数组是元素式的,对于稀疏数组是点积式的
In [537]: M = sparse.random(500,500,format='csr')
In [538]: M
Out[538]: 
<500x500 sparse matrix of type '<class 'numpy.float64'>'
    with 2500 stored elements in Compressed Sparse Row format>
In [539]: A=M.A
In [540]: timeit M*M
416 µs ± 4.29 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [541]: timeit A@A
13.4 ms ± 81.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)