Numpy scipy:将稀疏向量添加到稀疏矩阵的特定行

Numpy scipy:将稀疏向量添加到稀疏矩阵的特定行,numpy,scipy,Numpy,Scipy,在python中,向CSR矩阵的特定行添加CSR向量的最佳方法是什么?我发现了,但不知道是否有更好/更有效的方法来做到这一点。非常感谢您的帮助 给定一个NxM CSR矩阵A和一个1xM CSR矩阵B,以及一个行索引i,目标是将B添加到A的第i行 明显的索引添加确实有效。它给出了一个效率警告,但这并不意味着它是最慢的方法,只是你不应该重复这样做。它建议使用lil格式,但是转换为该格式和返回格式可能比执行csr矩阵的加法需要更多的时间 In [1049]: B.A Out[1049]: array

在python中,向CSR矩阵的特定行添加CSR向量的最佳方法是什么?我发现了,但不知道是否有更好/更有效的方法来做到这一点。非常感谢您的帮助


给定一个NxM CSR矩阵A和一个1xM CSR矩阵B,以及一个行索引i,目标是将B添加到A的第i行

明显的索引添加确实有效。它给出了一个效率警告,但这并不意味着它是最慢的方法,只是你不应该重复这样做。它建议使用
lil
格式,但是转换为该格式和返回格式可能比执行
csr
矩阵的加法需要更多的时间

In [1049]: B.A
Out[1049]: 
array([[0, 9, 0, 0, 1, 0],
       [2, 0, 5, 0, 0, 9],
       [0, 2, 0, 0, 0, 0],
       [2, 0, 0, 0, 0, 0],
       [0, 9, 5, 3, 0, 7],
       [1, 0, 0, 8, 9, 0]], dtype=int32)
In [1051]: B[1,:] += np.array([1,0,1,0,0,0])
/usr/local/lib/python3.5/dist-packages/scipy/sparse/compressed.py:730: SparseEfficiencyWarning: Changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient.
  SparseEfficiencyWarning)
In [1052]: B
Out[1052]: 
<6x6 sparse matrix of type '<class 'numpy.int32'>'
    with 17 stored elements in Compressed Sparse Row format>
In [1053]: B.A
Out[1053]: 
array([[0, 9, 0, 0, 1, 0],
       [3, 0, 6, 0, 0, 9],
       [0, 2, 0, 0, 0, 0],
       [2, 0, 0, 0, 0, 0],
       [0, 9, 5, 3, 0, 7],
       [1, 0, 0, 8, 9, 0]])
是将要更改的
A.data
的切片。当然,您需要“vector”中相应的切片

从[1049]B中的
开始

In [1085]: B.indptr
Out[1085]: array([ 0,  2,  5,  6,  7, 11, 14], dtype=int32)
In [1086]: B.data
Out[1086]: array([9, 1, 2, 5, 9, 2, 2, 9, 5, 3, 7, 1, 8, 9], dtype=int32)
In [1087]: B.indptr[[1,2]]  # row 1
Out[1087]: array([2, 5], dtype=int32)
In [1088]: B.data[2:5]
Out[1088]: array([2, 5, 9], dtype=int32)
In [1089]: B.indices[2:5]   # row 1 column indices
Out[1089]: array([0, 2, 5], dtype=int32)
In [1090]: B.data[2:5] += np.array([1,2,3])
In [1091]: B.A
Out[1091]: 
array([[ 0,  9,  0,  0,  1,  0],
       [ 3,  0,  7,  0,  0, 12],
       [ 0,  2,  0,  0,  0,  0],
       [ 2,  0,  0,  0,  0,  0],
       [ 0,  9,  5,  3,  0,  7],
       [ 1,  0,  0,  8,  9,  0]], dtype=int32)
请注意,更改的值[3,7,12]采用
lil
格式:

In [1092]: B.tolil().data
Out[1092]: array([[9, 1], [3, 7, 12], [2], [2], [9, 5, 3, 7], [1, 8, 9]], dtype=object)

csr/csc矩阵对于包括加法(O(nnz))在内的大多数操作都是有效的。但是,影响稀疏结构的微小更改(例如您的示例)或甚至将单个位置从0切换到1都不是因为它们需要对表示进行O(nnz)重组。数值和指数被压缩;插入一个,以上所有需要移动

如果您只执行一个这样的操作,我的猜测是您无法轻松击败scipy的实现。但是,如果您要添加多行,例如,它可能是值得的。首先创建一个稀疏矩阵,然后一次性添加

比如说,手工从行中创建csr矩阵并不是那么困难。例如,如果您的行密集且有序:

row_numbers, indices = np.where(rows)
data = rows[row_numbers, indices]
indptr = np.searchsorted(np.r_[true_row_numbers[row_numbers], N], np.arange(N+1))
如果有一组稀疏行及其行号:

data = np.r_[tuple([r.data for r in rows])]
indices = np.r_[tuple(r.indices for r in rows])]
jumps = np.add.accumulate([0] + [len(r) for r in rows])
indptr = np.repeat(jumps, np.diff(np.r_[-1, true_row_numbers, N]))

请详细说明你的问题——那么复习一下你的意思是“到位”?到位。另一个问题是添加两个CSR矩阵(具有相同的维度)。这些都是基本操作,但我似乎找不到正确的方法来执行它们。那么您可能熟悉
sparseeficiencywarning
推荐
lil_matrix
?我只是稍微调整了一下时间。但不是很科学。无论如何,csr似乎比lil在适当位置添加一行和添加两个矩阵方面都要快;我甚至没有计算转换的成本,所以这不是解决方案。现有的行和要添加到其中的向量是否共享相同的稀疏结构?谢谢,我将对此进行实验。添加的行也是稀疏的,但不一定与添加到的行具有相同的非零。如果它没有稀疏性,则不能使用我的简单代码。您必须像链接答案一样更改
nnz
索引
indptr
。这是可以做到的,但我怀疑这是否值得努力。有没有更简单的解决方案仍然有效?如果你必须改变行的稀疏性,效率将受到影响。对于稀疏矩阵,像这样的更改从来不像使用
numpy
数组那样简单。
data = np.r_[tuple([r.data for r in rows])]
indices = np.r_[tuple(r.indices for r in rows])]
jumps = np.add.accumulate([0] + [len(r) for r in rows])
indptr = np.repeat(jumps, np.diff(np.r_[-1, true_row_numbers, N]))