gpt4 book ai didi

python - 避免在 numpy 操作中隐式转换为矩阵

转载 作者:太空宇宙 更新时间:2023-11-03 11:25:09 25 4
gpt4 key购买 nike

有没有办法全局避免 matrix 出现在 numpy 计算的任何结果中?例如,当前如果您将 x 作为 numpy.ndarray 并将 y 作为 scipy.sparse.csc_matrix,然后你说 x += yx 之后会变成一个 matrix。有没有一种方法可以防止这种情况发生,即保持 xndarray,更一般地说,在所有有 a 的地方继续使用 ndarray 矩阵产生了吗?

最佳答案

我添加了scipy标签,这是一个scipy.sparse问题,不是np.matrix问题。

In [250]: y=sparse.csr_matrix([[0,1],[1,0]])
In [251]: x=np.arange(2)
In [252]: y+x
Out[252]:
matrix([[0, 2],
[1, 1]])

稀疏 + 数组 => 矩阵

(作为旁注,np.matrixnp.ndarray 的子类。sparse.csr_matrix 不是子类。它有许多类似 numpy 的操作,但它在自己的代码中实现它们)。

In [255]: x += y
In [256]: x
Out[256]:
matrix([[0, 2],
[1, 1]])

从技术上讲,这不应该发生;实际上,它正在执行 x = x+yx 分配一个新值,而不仅仅是修改 x

如果我首先将 y 转换为规则的密集 matrix,我会得到一个错误。允许该操作会将一维数组更改为二维数组。

In [258]: x += y.todense()
...
ValueError: non-broadcastable output operand with shape (2,) doesn't match the broadcast shape (2,2)

x 更改为 2d 允许加法继续进行 - 无需将数组更改为矩阵:

In [259]: x=np.eye(2)
In [260]: x
Out[260]:
array([[ 1., 0.],
[ 0., 1.]])
In [261]: x += y.todense()
In [262]: x
Out[262]:
array([[ 1., 1.],
[ 1., 1.]])

一般来说,用稀疏矩阵执行加法/减法是很棘手的。它们是为矩阵乘法而设计的。乘法不像加法那样改变稀疏性。例如,y+1 使其变稠密。

如果不深入研究稀疏加法的编码方式,我会说 - 不要在未首先将 y 转换为之前尝试此 x+=... 操作一个密集的版本。

In [265]: x += y.A
In [266]: x
Out[266]:
array([[ 1., 2.],
[ 2., 1.]])

我想不出不这样做的好理由。

(我应该检查 scipy github 是否有关于此的错误问题)。


scipy/sparse/compressed.py 有 csr 添加代码。 x+y 使用 x.__add__(y) 但有时会翻转为 y.__add__(x)x+=y 使用 x.__iadd__(y)。所以我可能还需要为 ndarray 检查 __iadd__

但是稀疏矩阵的基本加法是:

def __add__(self,other):
# First check if argument is a scalar
if isscalarlike(other):
if other == 0:
return self.copy()
else: # Now we would add this scalar to every element.
raise NotImplementedError('adding a nonzero scalar to a '
'sparse matrix is not supported')
elif isspmatrix(other):
if (other.shape != self.shape):
raise ValueError("inconsistent shapes")

return self._binopt(other,'_plus_')
elif isdense(other):
# Convert this matrix to a dense matrix and add them
return self.todense() + other
else:
return NotImplemented

所以 y+x 变成了 y.todense() + xx+y 使用相同的东西。

不管 += 的细节如何,很明显,将稀疏添加到密集(数组或 np.matrix)涉及将稀疏转换为密集。没有代码遍历稀疏值并将这些值有选择地添加到密集数组。

只有当数组都是稀疏的时,它才会执行特殊的稀疏加法。 y+y 有效,返回稀疏。 y+=y 失败并出现来自 sparse.base.__iadd__NotImplmenentedError


这是我想出的最好的诊断序列,尝试了将 y 添加到 (2,2) 数组的各种方法。

In [348]: x=np.eye(2)
In [349]: x+y
Out[349]:
matrix([[ 1., 1.],
[ 1., 1.]])
In [350]: x+y.todense()
Out[350]:
matrix([[ 1., 1.],
[ 1., 1.]])

加法产生一个矩阵,但是可以在不改变x类(或形状)的情况下将值写入x

In [351]: x[:] = x+y
In [352]: x
Out[352]:
array([[ 1., 1.],
[ 1., 1.]])

+= 与密集矩阵做同样的事情:

In [353]: x += y.todense()
In [354]: x
Out[354]:
array([[ 1., 2.],
[ 2., 1.]])

但是 +=sparse 中的一些东西改变了 x

的类
In [355]: x += y
In [356]: x
Out[356]:
matrix([[ 1., 3.],
[ 3., 1.]])

进一步测试并查看 id(x)x.__array_interface__ 很明显 x += y 替换了 x 。即使 xnp.matrix 开头也是如此。所以稀疏 += 不是就地操作。 x += y.todense() 是一个就地操作。

关于python - 避免在 numpy 操作中隐式转换为矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35546740/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com