You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用NumPy ndarray执行基础加法运算时出现结果错误的问题

NumPy数组转置与原数组相加的异常问题

我在学习NumPy ndarray用法时,写了如下代码:

import numpy as np

cov = np.random.uniform(.2, .4, (2, 2))
display('cov', cov)
oldcov = cov
covT = cov.T
cov += covT
cov2 = oldcov + covT
display('cov.T', covT)
display('cov += cov.T', cov)
display('cov = cov + cov.T', cov2)
display('cov - cov - cov.T', cov - oldcov - covT)
display('cov - cov - cov.T', cov2 - oldcov - covT)

运行后得到输出(附观察):

'cov'
array([[0.32258373, 0.33701686],
       [0.36291378, 0.24004231]])
'cov.T, 错误:预期是cov的转置,但结果不符'
array([[0.64516745, 0.69993064],
       [0.69993064, 0.48008463]])
'cov += cov.T, 错误:0.322 + 0.645 ≠ 0.645,似乎只执行了赋值操作'
array([[0.64516745, 0.69993064],
       [0.69993064, 0.48008463]])
'cov = cov + cov.T, 异常:与+=运算结果不同,且加法结果不正确'
array([[1.2903349 , 1.39986128],
       [1.39986128, 0.96016926]])
'cov - cov - cov.T, 对执行+=后的cov进行减法'
array([[-0.64516745, -0.69993064],
       [-0.69993064, -0.48008463]])
'cov - cov - cov.T, 对未执行+=的cov2进行减法,结果符合预期'
array([[0., 0.],
       [0., 0.]])

问题原因

  • NumPy中数组的.T转置返回的是原数组的视图,不是独立副本——covT和cov共享同一块内存空间,修改其中一个会同步影响另一个。
  • oldcov = cov只是复制了数组的引用,并没有创建新数组,oldcov和cov本质是同一个数组。

代码执行的实际逻辑:

  1. 初始化cov后,oldcov = cov让两者指向同一数组。
  2. covT = cov.T创建视图,和cov共享内存。
  3. cov += covT是原地修改:执行时,cov的元素被更新,而covT作为视图也会实时变化——比如cov[0,1]和covT[1,0]是同一个元素,加法过程中会读取已经被修改后的值,导致最终结果不是原数组加原转置,而是原数组加已经被修改后的转置视图。
  4. cov2 = oldcov + covT时,oldcov已经是被+=修改后的cov,covT也是修改后的视图,所以得到的是两倍的最终cov值。

正确实现方法

方法1:直接用普通加法(自动创建新数组)

普通加法cov + cov.T会生成新数组,不会修改原数组,也不会受视图影响:

import numpy as np

cov = np.random.uniform(.2, .4, (2, 2))
result = cov + cov.T
display('原数组', cov)
display('原数组+转置', result)

方法2:原地修改时,先将转置转为副本

如果需要原地修改原数组,先把转置转为独立副本,避免视图同步变化:

import numpy as np

cov = np.random.uniform(.2, .4, (2, 2))
cov += cov.T.copy()  # 用copy()创建转置的独立副本
display('原地修改后的数组', cov)

方法3:保存原数组副本时用copy()

如果需要保留原数组的初始值,必须用copy()创建独立副本,而不是直接赋值:

import numpy as np

cov = np.random.uniform(.2, .4, (2, 2))
oldcov = cov.copy()  # 创建原数组的独立副本
covT = cov.T.copy()  # 创建转置的独立副本
cov += covT
cov2 = oldcov + covT
display('原数组', oldcov)
display('转置', covT)
display('cov += cov.T', cov)
display('oldcov + covT', cov2)

内容的提问来源于stack exchange,提问作者zeticknight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 18:23:15