使用scipy.sparse
基于行或列的格式:csc_matrix
和csr_matrix
.
这些在底层使用高效的 C 实现(包括乘法),并且转置是无操作的(特别是如果您调用transpose(copy=False)
),就像使用 numpy 数组一样。
编辑:通过ipython 的一些时间:
import numpy, scipy.sparse
n = 100000
x = (numpy.random.rand(n) * 2).astype(int).astype(float) # 50% sparse vector
x_csr = scipy.sparse.csr_matrix(x)
x_dok = scipy.sparse.dok_matrix(x.reshape(x_csr.shape))
现在x_csr
和x_dok
50% 稀疏:
print repr(x_csr)
<1x100000 sparse matrix of type '<type 'numpy.float64'>'
with 49757 stored elements in Compressed Sparse Row format>
和时间:
timeit numpy.dot(x, x)
10000 loops, best of 3: 123 us per loop
timeit x_dok * x_dok.T
1 loops, best of 3: 1.73 s per loop
timeit x_csr.multiply(x_csr).sum()
1000 loops, best of 3: 1.64 ms per loop
timeit x_csr * x_csr.T
100 loops, best of 3: 3.62 ms per loop
所以看起来我撒了谎。转置非常便宜,但没有 csr * csc 的高效 C 实现(在最新的 scipy 0.9.0 中)。每次调用都会构造一个新的 csr 对象:-(
作为一个 hack(虽然 scipy 现在相对稳定),你可以直接在稀疏数据上做点积:
timeit numpy.dot(x_csr.data, x_csr.data)
10000 loops, best of 3: 62.9 us per loop
请注意,最后一种方法再次执行 numpy 密集乘法。稀疏度为 50%,因此它实际上比dot(x, x)
2 倍快。