使用花式索引修改稀疏矩阵
Modifying sparce matrix using fancy indexing
我正在尝试使用花式索引来修改大型稀疏矩阵。假设您有以下代码:
import numpy as np
import scipy.sparse as sp
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
b = sp.lil_matrix(a)
c = sp.lil_matrix((3,4))
c[[1,2], 0] = b[[1,2], 0]
然而,此代码给出以下错误:
ValueError: shape mismatch in assignment
我不明白为什么这不起作用。两个矩阵具有相同的形状,如果两个矩阵都是 numpy 数组,这通常有效。如果有任何帮助,我将不胜感激。
是的,这是稀疏 __setitem__
的错误。我之前已经 运行 进入了它(但我只是解决了它)。现在我真的调查了它;首先,你可以很容易地解决这个问题:
import numpy as np
import scipy.sparse as sp
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
b = sp.lil_matrix(a)
c = sp.lil_matrix((3,4))
c[[1,2], 0] = b[[1,2], 0]
这提高了您看到的 ValueError
。这不会并按预期工作:
c[[1,2], 0] = b[[1,2], [0]]
>>> c.A
array([[0., 0., 0., 0.],
[5., 0., 0., 0.],
[9., 0., 0., 0.]])
让我们看一下 the offending __setitem__
(我将省略很多不会被调用的代码):
row, col = self._validate_indices(key)
这很好 - row = [1, 2]
和 col = 0
col = np.atleast_1d(col)
i, j = _broadcast_arrays(row, col)
到目前为止一切顺利 - i = [1, 2]
和 j = [0, 0]
if i.ndim == 1:
# Inner indexing, so treat them like row vectors.
i = i[None]
j = j[None]
broadcast_row = x.shape[0] == 1 and i.shape[0] != 1
broadcast_col = x.shape[1] == 1 and i.shape[1] != 1
这是我们的问题 - i
和 j
都变成了形状为 (1, 2)
的行向量。 x
这是您要分配的内容 (b[[1,2], 0]
),其形状为 (2, 1)
;下一步引发 ValueError
原因 x
并且索引不对齐。
>>> c[[1,2], 0] = b[[1,2], 0].A
ValueError: cannot reshape array of size 4 into shape (2,)
这是同样的问题,但是 __setitem__
将 x
广播到 (2,2)
数组中,然后再次失败,因为它比您分配给它的数组大。
解决方法 (b[[1,2], [0]]
) 的形状 (1, 2)
不正确,但该错误最终抵消了索引 c
.
中的错误
我不确定这个索引代码背后的确切逻辑是什么,所以我不确定如何在不引入其他细微错误的情况下解决这个问题。
我正在尝试使用花式索引来修改大型稀疏矩阵。假设您有以下代码:
import numpy as np
import scipy.sparse as sp
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
b = sp.lil_matrix(a)
c = sp.lil_matrix((3,4))
c[[1,2], 0] = b[[1,2], 0]
然而,此代码给出以下错误:
ValueError: shape mismatch in assignment
我不明白为什么这不起作用。两个矩阵具有相同的形状,如果两个矩阵都是 numpy 数组,这通常有效。如果有任何帮助,我将不胜感激。
是的,这是稀疏 __setitem__
的错误。我之前已经 运行 进入了它(但我只是解决了它)。现在我真的调查了它;首先,你可以很容易地解决这个问题:
import numpy as np
import scipy.sparse as sp
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
b = sp.lil_matrix(a)
c = sp.lil_matrix((3,4))
c[[1,2], 0] = b[[1,2], 0]
这提高了您看到的 ValueError
。这不会并按预期工作:
c[[1,2], 0] = b[[1,2], [0]]
>>> c.A
array([[0., 0., 0., 0.],
[5., 0., 0., 0.],
[9., 0., 0., 0.]])
让我们看一下 the offending __setitem__
(我将省略很多不会被调用的代码):
row, col = self._validate_indices(key)
这很好 - row = [1, 2]
和 col = 0
col = np.atleast_1d(col)
i, j = _broadcast_arrays(row, col)
到目前为止一切顺利 - i = [1, 2]
和 j = [0, 0]
if i.ndim == 1:
# Inner indexing, so treat them like row vectors.
i = i[None]
j = j[None]
broadcast_row = x.shape[0] == 1 and i.shape[0] != 1
broadcast_col = x.shape[1] == 1 and i.shape[1] != 1
这是我们的问题 - i
和 j
都变成了形状为 (1, 2)
的行向量。 x
这是您要分配的内容 (b[[1,2], 0]
),其形状为 (2, 1)
;下一步引发 ValueError
原因 x
并且索引不对齐。
>>> c[[1,2], 0] = b[[1,2], 0].A
ValueError: cannot reshape array of size 4 into shape (2,)
这是同样的问题,但是 __setitem__
将 x
广播到 (2,2)
数组中,然后再次失败,因为它比您分配给它的数组大。
解决方法 (b[[1,2], [0]]
) 的形状 (1, 2)
不正确,但该错误最终抵消了索引 c
.
我不确定这个索引代码背后的确切逻辑是什么,所以我不确定如何在不引入其他细微错误的情况下解决这个问题。