【发布时间】:2019-05-24 12:22:49
【问题描述】:
我正在学习稀疏矩阵运算的 scipy 代码。但是,我对在进行加法运算时如何计算 csr_matrix 索引感到困惑。我的代码很简单:
B = A + A.T
A.toarray()
array([[1., 1., 1., 1., 0., 1., 1., 0., 1., 1., 1., 1.],
[0., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1.],
[0., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1.],
[0., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1.],
[0., 1., 0., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[0., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1.],
[0., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1.],
[0., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1.],
[0., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1.],
[0., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1.],
[0., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1.],
[0., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1.]])
A.indices:
array([ 0, 2, 1, 5, 10, 3, 6, 11, 9, 8,
1, 2, 9, 10, 5, 8, 6, 11, 3, 7,
2, 10, 1, 5, 9, 6, 11, 7, 8, 3,
3, 8, 6, 7, 5, 11, 9, 10, 2, 1,
4, 9, 1, 7, 8, 11, 3, 6, 10, 5,
5, 6, 11, 10, 8, 9, 3, 2, 7, 1,
6, 5, 8, 11, 9, 10, 3, 7, 2, 1,
7, 9, 3, 6, 8, 5, 11, 10, 2, 1,
8, 6, 11, 9, 5, 3, 10, 7, 1, 2,
9, 11, 10, 8, 6, 5, 7, 3, 2, 1,
10, 11, 5, 9, 6, 8, 2, 3, 1, 7,
11, 10, 5, 6, 8, 9, 3, 7, 2, 1], dtype=int32)
我调试了深入 scipy 的代码以获取更多详细信息,发现 .T 操作使矩阵 A 变为 CSC 格式矩阵。然后,除了重载操作,A.T 将再次转换为 CSR 格式矩阵,但其索引更改如下:
A.T.toarray():
array([[1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 0., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],
[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[0., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]])
A.T.indices:
array([ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3,
5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1,
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5,
6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11], dtype=int32)
我无法理解的是 B.indices,如下所示:
B.toarray()
array([[2., 1., 1., 1., 0., 1., 1., 0., 1., 1., 1., 1.],
[1., 2., 2., 2., 1., 2., 2., 2., 2., 2., 2., 2.],
[1., 2., 2., 2., 0., 2., 2., 2., 2., 2., 2., 2.],
[1., 2., 2., 2., 1., 2., 2., 2., 2., 2., 2., 2.],
[0., 1., 0., 1., 2., 1., 1., 1., 1., 1., 1., 1.],
[1., 2., 2., 2., 1., 2., 2., 2., 2., 2., 2., 2.],
[1., 2., 2., 2., 1., 2., 2., 2., 2., 2., 2., 2.],
[0., 2., 2., 2., 1., 2., 2., 2., 2., 2., 2., 2.],
[1., 2., 2., 2., 1., 2., 2., 2., 2., 2., 2., 2.],
[1., 2., 2., 2., 1., 2., 2., 2., 2., 2., 2., 2.],
[1., 2., 2., 2., 1., 2., 2., 2., 2., 2., 2., 2.],
[1., 2., 2., 2., 1., 2., 2., 2., 2., 2., 2., 2.]])
B.indices
array([ 8, 9, 11, 6, 3, 10, 5, 1, 2, 0,
4, 0, 7, 3, 11, 6, 8, 5, 10, 9, 2, 1,
0, 3, 8, 7, 11, 6, 9, 5, 1, 10, 2,
4, 0, 1, 2, 10, 9, 11, 5, 7, 6, 8, 3,
5, 10, 6, 3, 11, 8, 7, 1, 9, 4,
4, 0, 1, 7, 2, 3, 9, 8, 10, 11, 6, 5,
4, 0, 1, 2, 7, 3, 10, 9, 11, 8, 5, 6,
4, 1, 2, 10, 11, 5, 8, 6, 3, 9, 7,
4, 0, 2, 1, 7, 10, 3, 5, 9, 11, 6, 8,
4, 0, 1, 2, 3, 7, 5, 6, 8, 10, 11, 9,
4, 0, 7, 1, 3, 2, 8, 6, 9, 5, 11, 10,
4, 0, 1, 2, 7, 3, 9, 8, 6, 5, 10, 11], dtype=int32)
结果 B 是通过 C++ 计算的,所以库 _sparsetools.cpython-35m-x86_64-linux-gnu.so 在 scipy 中,因此我无法获取它的代码。
这个问题几乎把我逼疯了。希望你们中的一些人可以帮助我。
【问题讨论】:
-
我认为你把事情弄得太复杂了。您的
A比测试所需的更大更密集。A+A.T的加法与两个不相关矩阵的加法(只要它们在形状上匹配)B = A1 + A2没有任何不同。一个逻辑方法,假设两者都是csr,是逐行迭代的。B行的索引将是A1和A2的并集。现在可以删除等于 0 的总和,并在最后的B.eliminate_zeros()调用中删除。 -
您的
A.T.indices实际上是A.T.tocsr().indices,不是吗?使csr副本对索引进行排序。
标签: python numpy scipy sparse-matrix