假设我有一个稀疏矩阵:
>>> indptr = np.array([0, 2, 3, 6])
>>> indices = np.array([0, 2, 2, 0, 1, 2])
>>> data = np.array([1, 2, 3, 4, 5, 6])
>>> csr_matrix((data, indices, indptr), shape=(3, 3)).toarray()
array([[1, 0, 2],
[0, 0, 3],
[4, 5, 6]])
我想将第0列和第2列归零。下面是我想得到的结果:
array([[0, 0, 0],
[0, 0, 0],
[0, 5, 0]])
下面是我的尝试:
sp_mat = csr_matrix((data, indices, indptr), shape=(3, 3))
zero_cols = np.array([0, 2])
sp_mat[:, zero_cols] = 0
然而,我得到一个警告:
SparseEfficiencyWarning: Changing the sparsity structure of a csr_matrix is expensive. lil_matrix is more efficient.
由于我拥有的sp_mat很大,因此转换为lil_matrix的速度非常慢。
什么是有效的方法?
2条答案
按热度按时间dkqlctbz1#
看看
csr
赋值语句的结果:它不仅给予了警告,而且实际上增加了“稀疏”项的数量,尽管大多数项现在的值为0。只有当我们清理时,这些项才会被删除:
在索引赋值中,
csr
并不区分设置0和其他值,它对所有值都一视同仁。我应该注意到,给出效率警告主要是为了防止用户重复使用它(如在一个迭代中)。
对于索引赋值,
lil
更有效(或者至少它不会警告效率),但是转换成这种格式或从这种格式转换是非常耗时的。另一种选择是直接查找并设置新的0,后跟
eliminate_zeros
)。另一种方法是使用矩阵乘法,我认为对角稀疏矩阵的右列为0就可以了。
如果你在矩阵中进行乘法运算,你不会得到效率警告。它只是改变了现有的非零项的值,所以不会改变矩阵的稀疏性(至少在你消除零之前不会):
6ioyuze22#
矩阵乘法是要走的路。
对于我的大型CSR矩阵(大小为2M*2M),直接使用
sp_mat[:, zero_cols] = 0
赋值会导致内存不足错误。假设在布尔数组zero_mask
中,零列的索引标记为True,则乘以对角矩阵可以高效地完成这项工作(在3秒内)。这里,
(~node_mask).astype(int)
给出了一个0和1的一维数组,它指定了哪些列应该保留(1),哪些应该归零(0)。