Python 为什么使用scipy';s稀疏csr_矩阵比numpy';什么是密集阵列?

Python 为什么使用scipy';s稀疏csr_矩阵比numpy';什么是密集阵列?,python,numpy,scipy,sparse-matrix,Python,Numpy,Scipy,Sparse Matrix,在这种情况下,我需要从稀疏矩阵中提取一行,并将其点积与密集行进行比较。使用scipy的csr_矩阵,这似乎比使用numpy的密集数组乘法要慢得多。这让我感到惊讶,因为我预计稀疏点积将涉及更少的操作。以下是一个例子: import timeit as ti sparse_setup = 'import numpy as np; import scipy.sparse as si;' + \ 'u = si.eye(10000).tocsr()[10];' + \

在这种情况下,我需要从稀疏矩阵中提取一行,并将其点积与密集行进行比较。使用scipy的csr_矩阵,这似乎比使用numpy的密集数组乘法要慢得多。这让我感到惊讶,因为我预计稀疏点积将涉及更少的操作。以下是一个例子:

import timeit as ti

sparse_setup = 'import numpy as np; import scipy.sparse as si;' + \
               'u = si.eye(10000).tocsr()[10];' + \
               'v = np.random.randint(100, size=10000)'

dense_setup  = 'import numpy as np; u = np.eye(10000)[10];' + \
               'v = np.random.randint(100, size=10000)'

ti.timeit('u.dot(v)', setup=sparse_setup, number=100000)
2.788649031019304

ti.timeit('u.dot(v)', setup=dense_setup, number=100000)
2.179030169005273
对于矩阵-向量乘法,稀疏表示法可以轻而易举地获胜,但在这种情况下不行。我尝试使用csc_矩阵,但性能更差:

>>> sparse_setup = 'import numpy as np; import scipy.sparse as si;' + \
...                'u = si.eye(10000).tocsc()[10];' + \
...                'v = np.random.randint(100, size=10000)'
>>> ti.timeit('u.dot(v)', setup=sparse_setup, number=100000)
7.0045155879925005

在这种情况下,为什么numpy要打败scipy.稀疏?是否有一种矩阵格式可以更快地进行此类计算?

CSR/CSC向量积调用在每次调用中都会有几微秒的开销,从执行少量Python代码到处理编译代码中的参数(scipy.sparse.\u sparsetools.CSR\u matvec)

在现代处理器上,计算矢量点积的速度非常快,因此在这种情况下,开销控制着计算时间。矩阵向量积本身更昂贵,在这里类似的开销是不可见的


那么为什么Numpy的日常开支更小?这主要是由于更好地优化了代码;csr_矩阵的性能可能会在这里得到改进。

稀疏矩阵节省内存,而在计算时会增加复杂性。如何计算“运算”?只是乘法和加法?或者你正在考虑索引、迭代等。在现代处理器上,2个数字相乘并不是一个昂贵的操作。此外,
dot
也被限定为快速数字库。稀疏乘法也是编译的,但不是使用相同的优化库。为了清楚起见,您正在测试一个非常稀疏的向量(10000中的1个非零向量)乘以相同大小的密集向量。我认为,它最终使用了
sparse.\u sparsetools.csr\u matvec
,一个编译函数。我必须看一下ScipyGitHub才能进一步挖掘。@hpaulj,我认为稀疏矩阵是行-列值元组的集合。k元素稀疏行向量与n元素稠密向量的点积应该只需要O(k)运算(常数因子高于稠密),而稠密乘法应该取O(n)。我将采纳您的建议并阅读源代码。当我改变
u
中非零值的数量时(以及密集等效值),计时没有变化
(u.data*v[u.index])。sum()
更接近您所想象的情况。它稍微快一点,但它的时间仍然不是O(k)。