我使用的格式是csr稀疏矩阵,建议它是add和dot opertor最快的稀疏结构。我将其性能与np.array的add和dot运算符进行了比较。然而,稀疏矩阵的计算比密集格式下的情况慢得多,这似乎很奇怪。为什么?有没有更有效的方法来实现稀疏计算?
import numpy as np
import scipy.sparse as sp
import random
#%% generate dense vector
vector_length = 10000
nonzero_term = 200
x = np.zeros((vector_length, ))
y = np.zeros((vector_length, ))
index = random.sample(range(vector_length), nonzero_term)
x[index] = np.random.rand(nonzero_term)
index = random.sample(range(vector_length), nonzero_term)
y[index] = np.random.rand(nonzero_term)
#%% transform to sparse vector
x_sp = sp.csr_matrix(x)
y_sp = sp.csr_matrix(y)
#%% test
# dense add
%timeit [x + y]
# sparse add
%timeit [x_sp + y_sp]
# dense dot
%timeit [x.dot(y)]
# sparse dot
%timeit [x_sp.dot(y_sp.T)]
,结果显示
100000 loops, best of 3: 6.06 µs per loop
10000 loops, best of 3: 97.8 µs per loop
100000 loops, best of 3: 3.45 µs per loop
1000 loops, best of 3: 225 µs per loop
答案 0 :(得分:1)
这两组操作都使用编译代码。但数据存储方式完全不同。
x.shape
是(10000,);同样y
。 x+y
只需要分配一个相同形状的数组,并在c
中有效地逐步通过3个数据缓冲区。
x_sp
有200个非零值,值在x_sp.data
中,其列索引在x_sp.indices
中。有第三个数组x_sp.indptr
,但只有2个值。同样适用于y_sp
。但要添加它们,它必须单步执行4个数组,并将值分配给两个数组。即使在c
中编码,也会有更多的工作。在我的测试用例x_sp+y_sp
中有397个非零值。
使用这些1d数组(1行矩阵),dot
涉及相同类型的单步执行值,只将它们全部加到一个最终值。
如果矩阵的密度足够低,稀疏计算可以更快。我认为,矩阵乘法的确比加法更真实。
总之,对于稀疏矩阵,每元素计算更复杂。因此,即使元素很少,总体时间也会更长。