【问题标题】:How to best row-scale a SciPy sparse matrix?如何最好地对 SciPy 稀疏矩阵进行行缩放?
【发布时间】:2016-12-14 08:48:37
【问题描述】:

我有一个 SciPy 稀疏矩阵 A,假设是 CSR 格式,以及一个匹配长度的向量 v

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

【问题讨论】:

    标签: python scipy sparse-matrix


    【解决方案1】:

    简单的方法是让 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
    

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

    【讨论】:

      【解决方案2】:

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

      但是,我发现到目前为止实现这一点的最高效方法是使用提供的mkl_?csrmultcsr 方法和对角矩阵连接到 MKL。

      不提供这样做的代码,因为我的包装器仍然存在太多错误,但是对于与上面使用的相同大小的矩阵,这会在大约 0.3 秒内执行重新缩放。

      也许有一天 numpy/scipy 会像处理密集数学一样连接到 MKL 进行稀疏数学...

      【讨论】:

        猜你喜欢
        • 2019-03-12
        • 2015-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-07
        • 2013-10-11
        • 2013-05-24
        • 2015-12-05
        相关资源
        最近更新 更多