Python 如何对SciPy稀疏矩阵进行最佳行缩放?

Python 如何对SciPy稀疏矩阵进行最佳行缩放?,python,scipy,sparse-matrix,Python,Scipy,Sparse Matrix,我得到了一个SciPy稀疏矩阵a,假设是CSR格式,还有一个匹配长度的向量v 使用v行缩放A的最佳方式是什么,即执行 diag(v)*A?简单的方法是让scipy处理血淋淋的细节,只需执行以下操作: scipy.sparse.spdiags(v, 0, len(v), len(v)) * A 编辑如果(且仅当)矩阵以CSC格式存储,则您可以按如下方式就地执行操作: A_csc.data = A_csc.data * v[A_csc.indices] 我已经做了一些计时,它很大程度上取决于矩阵

我得到了一个SciPy稀疏矩阵
a
,假设是CSR格式,还有一个匹配长度的向量
v

使用
v
行缩放
A
的最佳方式是什么,即执行
diag(v)*A

简单的方法是让scipy处理血淋淋的细节,只需执行以下操作:

scipy.sparse.spdiags(v, 0, len(v), len(v)) * A
编辑如果(且仅当)矩阵以CSC格式存储,则您可以按如下方式就地执行操作:

A_csc.data = A_csc.data * v[A_csc.indices]
我已经做了一些计时,它很大程度上取决于矩阵的稀疏性及其大小,请随意使用以下代码:

from __future__ import division
import numpy as np
import scipy.sparse as sps
import timeit

A_csr = None
A_csc = None
v = None

def time_row_scaling(n, dens) :
    global A_csr, A_csc, v
    v = np.random.rand(n)
    A_csr = sps.rand(n, n, density=dens, format='csr')
    A_csc = A_csr.tocsc()
    def row_scale(A_csc, v) :
        A_csc.data = A_csc.data * v[A_csc.indices]
    row_scaled_1 = sps.spdiags(v, 0, n , n) * A_csr
    row_scaled_2 = sps.spdiags(v, 0, n , n) * A_csc
    row_scale(A_csc, v)
    if n < 1000 :
        np.testing.assert_almost_equal(row_scaled_1.toarray(),
                                       row_scaled_2.toarray())
        np.testing.assert_almost_equal(row_scaled_1.toarray(),
                                       A_csc.toarray())
    A_csc = A_csr.tocsc()
    t1 = timeit.timeit('sps.spdiags(v, 0, len(v) , len(v)) * A_csr',
                       'from __main__ import sps, v, A_csr',
                       number=1)
    t2 = timeit.timeit('sps.spdiags(v, 0, len(v), len(v)) * A_csc',
                       'from __main__ import sps, v, A_csc',
                       number=1)
    t3 = timeit.timeit('A_csc.data = A_csc.data * v[A_csc.indices]',
                       'from __main__ import A_csc, v',
                       number=1)
    print t1, t2, t3

>>> time_row_scaling(1000, 0.01)
0.00100659830939 0.00102425072673 0.000231944553347
>>> time_row_scaling(1000, 0.1)
0.0017328105481 0.00311339379218 0.00239826562947
>>> time_row_scaling(10000, 0.01)
0.0162369397769 0.0359325217874 0.0216837368279
>>> time_row_scaling(10000, 0.1)
0.167978350747 0.492032396702 0.209231639536
来自未来进口部的

将numpy作为np导入
将scipy.sparse导入为SP
导入时间信息
A_csr=无
A_csc=无
v=无
def时间行刻度(n,密度):
全球A_csr,A_csc,v
v=np.rand.rand(n)
A_csr=sps.rand(n,n,密度=dens,format='csr')
A_csc=A_csr.tocsc()
def行刻度(A\U csc,v):
A_csc.data=A_csc.data*v[A_csc.index]
第1行=sps.spdiags(v,0,n,n)*A\u csr
第2行=sps.spdiags(v,0,n,n)*A\u csc
行标度(A\U csc,v)
如果n<1000:
np.testing.assert_几乎等于(row_scaled_1.toarray(),
行\u缩放\u 2.toarray())
np.testing.assert_几乎等于(row_scaled_1.toarray(),
A_csc.toarray())
A_csc=A_csr.tocsc()
t1=timeit.timeit('sps.spdiags(v,0,len(v),len(v))*A_csr',
“从主导入sps,v,A_csr”,
数字=1)
t2=timeit.timeit('sps.spdiags(v,0,len(v),len(v))*A_csc',
“从主导入sps,v,A_csc”,
数字=1)
t3=timeit.timeit('A_csc.data=A_csc.data*v[A_csc.index]”,
'从主导入一个csc,v',
数字=1)
打印t1、t2、t3
>>>时间-行-缩放(1000,0.01)
0.00100659830939 0.00102425072673 0.000231944553347
>>>时间行缩放(1000,0.1)
0.0017328105481 0.00311339379218 0.00239826562947
>>>时间行缩放(10000,0.01)
0.0162369397769 0.0359325217874 0.0216837368279
>>>时间行缩放(10000,0.1)
0.167978350747 0.492032396702 0.209231639536

总结似乎是,如果它是CSR,或者真的很大,那么使用简单的第一种方法。如果它是一个小的、非常稀疏的矩阵,那么就地方法会更快,尽管所有时间都很小。

sklearn在
sklearn.utils.sparsefuncs.inplace\csr\u row\u scale
中提供了执行此操作的实用程序。在我的实验中,这比Jaime建议的方法和
csr\u矩阵.multiply
方法稍微好一些。请注意,我的实验是在非常大的矩阵上进行的,形状大约为10^7 x 10^4。对于这种大小的矩阵,sklearn大约需要2秒的时间;其他方法的范围为2.5-5秒

然而,我发现到目前为止实现这一点最有效的方法是使用提供的方法和对角矩阵连接到MKL

没有提供这样做的代码,因为我的包装器到目前为止还存在太多的错误,但这将在大约0.3秒内对上面使用的相同大小的矩阵执行重缩放

也许有一天numpy/scipy会像对稠密数学一样,为稀疏数学连接到MKL