Numpy scipy:将稀疏向量添加到稀疏矩阵的特定行
在python中,向CSR矩阵的特定行添加CSR向量的最佳方法是什么?我发现了,但不知道是否有更好/更有效的方法来做到这一点。非常感谢您的帮助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
给定一个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]))