【问题标题】:Multiplying elements in a sparse array with rows in matrix将稀疏数组中的元素与矩阵中的行相乘
【发布时间】:2012-08-27 14:32:53
【问题描述】:

如果你有一个稀疏矩阵 X:

>> X = csr_matrix([[0,2,0,2],[0,2,0,1]])
>> print type(X)    
>> print X.todense()    
<class 'scipy.sparse.csr.csr_matrix'>
[[0 2 0 2]
 [0 2 0 1]]

还有一个矩阵Y:

>> print type(Y)
>> print text_scores
<class 'numpy.matrixlib.defmatrix.matrix'>
[[8]
 [5]]

...如何将 X 的每个元素乘以 Y 的行数。例如:

[[0*8 2*8 0*8 2*8]
 [0*5 2*5 0*5 1*5]]

或:

[[0 16 0 16]
 [0 10 0 5]]

我已经厌倦了这个,但显然它不起作用,因为尺寸不匹配: Z = X.data * Y

【问题讨论】:

    标签: python matrix numpy scipy sparse-matrix


    【解决方案1】:

    不幸的是,如果另一个矩阵是密集的,CSR 矩阵的.multiply 方法似乎会使矩阵密集。所以这是避免这种情况的一种方法:

    # Assuming that Y is 1D, might need to do Y = Y.A.ravel() or such...
    
    # just to make the point that this works only with CSR:
    if not isinstance(X, scipy.sparse.csr_matrix):
        raise ValueError('Matrix must be CSR.')
    
    Z = X.copy()
    # simply repeat each value in Y by the number of nnz elements in each row: 
    Z.data *= Y.repeat(np.diff(Z.indptr))
    

    这确实会创建一些临时变量,但至少是完全矢量化的,并且不会使稀疏矩阵变密。


    对于 COO 矩阵,等价于:

    Z.data *= Y[Z.row] # you can use np.take which is faster then indexing.
    

    对于 CSC 矩阵,等价于:

    Z.data *= Y[Z.indices]
    

    【讨论】:

    • 不,对于首席运营官,我认为您需要使用Z.data *= Y[Z.row],或者如果您关心速度,则需要使用 np.take 而不是索引。
    • 那行得通。它可以在不致密矩阵的情况下做到这一点吗?
    • 我想我会把它添加到答案中。和另一个一样,它只使 Y 与 Z 的非零元素一样大,它不会使 Z 变密。
    【解决方案2】:

    我有同样的问题。就个人而言,我没有发现scipy.sparse 的文档很有帮助,也没有找到直接处理它的函数。所以我试着自己写,这为我解决了:

    Z = X.copy()
    for row_y_idx in range(Y.shape[0]):
        Z.data[Z.indptr[row_y_idx]:Z.indptr[row_y_idx+1]] *= Y[row_y_idx, 0]
    

    想法是:对于Y 位置row_y_idx-th 的每个元素,与Xrow_y_idx-th 行执行标量乘法。有关访问 CSR 矩阵 here 中的元素的更多信息(其中 dataAIAindptr)。

    给定 XY,如您所定义:

    import numpy as np
    import scipy.sparse as sps
    
    X = sps.csr_matrix([[0,2,0,2],[0,2,0,1]])
    Y = np.matrix([[8], [5]])
    
    Z = X.copy()
    for row_y_idx in range(Y.shape[0]):
        Z.data[Z.indptr[row_y_idx]:Z.indptr[row_y_idx+1]] *= Y[row_y_idx, 0]
    
    print(type(Z))
    print(Z.todense())
    

    输出和你的一样:

    <class 'scipy.sparse.csr.csr_matrix'>
     [[ 0 16  0 16]
      [ 0 10  0  5]]
    

    【讨论】:

      【解决方案3】:

      我用来执行逐行(或逐列)乘法的方法是使用矩阵乘法与左侧的对角矩阵(分别位于右侧):

      import numpy as np
      import scipy.sparse as sp
      
      X = sp.csr_matrix([[0,2,0,2],
                         [0,2,0,1]])
      Y = np.array([8, 5])
      
      D = sp.diags(Y) # produces a diagonal matrix which entries are the values of Y
      Z = D.dot(X) # performs D @ X, multiplication on the left for row-wise action
      

      保留稀疏性(以 CSR 格式):

      print(type(Z))
      >>> <class 'scipy.sparse.csr.csr_matrix'>
      

      而且输出也是正确的:

      print(Z.toarray()) # Z is still sparse and gives the right output
      >>> print(Z.toarray()) # Z is still sparse and gives the right output
      [[ 0. 16.  0. 16.]
       [ 0. 10.  0.  5.]]
      

      【讨论】:

        猜你喜欢
        • 2017-04-16
        • 1970-01-01
        • 2012-10-21
        • 2020-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多