scipy稀疏csr_matrix的索引

2 投票
1 回答
1652 浏览
提问于 2025-04-18 18:50

我有两个形状完全相同的稀疏矩阵,它们的数据值可能不同,非零元素的数量也可能不同。现在我想从其中一个矩阵中找出前10个元素,然后在另一个矩阵的相同位置上增加这些元素的值。我现在的做法是这样的:

idx = a.data.argpartition(-10)[-10:]
i, j = matrix.nonzero()

i_idx = i[idx]
j_idx = j[idx]

b[i_idx, j_idx] += 1

我之所以这么做,是因为这两个矩阵的数据部分(a.data 和 b.data)不一定有相同数量的元素,因此它们的索引会不同。

我现在的问题是,是否有办法改进这个过程。根据我的了解,获取非零元素的做法并不太优雅,因为我需要分配两个新的数组,而我现在的内存使用已经很紧张了。我可以通过 csr_matrix.indices 获取 j_indices,但 i_indices 怎么办呢?我能否用 indptr 来更好地处理这个问题?

欢迎任何建议。

1 个回答

0

我不太明白“前10个元素”是什么意思。我猜如果你有两个矩阵A和B,你想要在A的前10个非零元素的位置上,把B[i, j]加1,也就是说如果A[i, j]在这10个非零元素之内,就要加1。

我还假设B[i, j]可能是零,这在性能上是最糟糕的情况,因为这意味着你需要改变矩阵的稀疏结构。

CSR格式并不是改变稀疏结构的理想选择。因为每次插入或删除操作的复杂度都是O(nnzs)(假设CSR存储是用数组实现的,通常确实是这样)。

你可以使用DOK格式来处理你的第二个矩阵(就是你要修改的那个),这种格式可以让你以O(1)的速度访问元素。

我没有进行过基准测试,但我想你的选择在最坏情况下是10 * O(nnzs),也就是说当你添加10个新的非零值时,而DOK格式在构建矩阵时需要O(nnzs),然后每次插入只需要O(1),最后如果需要转换回CSR格式,则需要O(nnzs)。

撰写回答