numpy,转置是视图,是否不会使矩阵对称?

4 投票
1 回答
1958 浏览
提问于 2025-04-18 09:08

在阅读scipy讲座的时候,发现了一个例子:

>>> a = np.triu(np.ones((3, 3)), 1)
>>> a
array([[ 0.,  1.,  1.],
       [ 0.,  0.,  1.],
       [ 0.,  0.,  0.]])
>>> a.T
array([[ 0.,  0.,  0.],
       [ 1.,  0.,  0.],
       [ 1.,  1.,  0.]])

然后它说:

在这里输入图片描述

我不明白为什么。我做了一个实验,确实让它变得对称。

在这里输入图片描述

编辑 1 :

对于随机矩阵,结果也是一样的:

在这里输入图片描述

1 个回答

5

我觉得我明白这个警告的目的是什么,虽然我对Numpy的内部工作原理了解得不够,不知道为什么这个问题没有发生。

重点是,你在就地加法操作右边的转置矩阵其实是对正在被修改的矩阵的一个浅表视图(并不是一个复制品)。如果Numpy通过逐个值来执行这个操作,有些结果可能会出错。

想象一下这样一个简单的实现,类似于二维矩阵的 += 操作符:

def matrix_iadd(lhs, rhs):
    for i in range(lhs.shape[0]):
        for j in range(lhs.shape[1]):
            lhs[i,j] += rhs[i,j]
    return lhs

如果 rhs 是一个和 lhs 有重叠的视图(比如转置),那么这个操作就不会按预期工作。这里有个例子:

>>> a = np.arange(9)
>>> a.shape=(3,3)
>>> a
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])
>>> a.T
array([[0, 3, 6],
       [1, 4, 7],
       [2, 5, 8]])
>>> matrix_iadd(a, a.T)
array([[ 0,  4,  8],
       [ 7,  8, 12],
       [14, 19, 16]])

结果不对称的原因是,在操作进行的过程中,右边的值在不断变化。当 lhs[0,1] 被更新时(把 rhs[0,1] 的3加到原来的1上),rhs[1,0] 也跟着改变了。所以,当轮到更新 lhs[1,0] 时,rhs[1,0] 已经是一个被修改过的值了。

我猜这个警告就是针对这个问题的,尽管在正常使用中,这个影响似乎并不适用于Numpy的内置操作符。也许这个指南和警告是为之前版本的Numpy写的,那时候的行为不太好,或者在当前版本的Numpy中,某些类型的数组仍然可能出现这种不好的行为。我不太确定。我觉得一般来说,避免使用视图进行就地修改是个好建议,尽管在某些情况下不一定会出错。

撰写回答