使用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本质是同一个数组。
代码执行的实际逻辑:
- 初始化
cov后,oldcov = cov让两者指向同一数组。 covT = cov.T创建视图,和cov共享内存。cov += covT是原地修改:执行时,cov的元素被更新,而covT作为视图也会实时变化——比如cov[0,1]和covT[1,0]是同一个元素,加法过程中会读取已经被修改后的值,导致最终结果不是原数组加原转置,而是原数组加已经被修改后的转置视图。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
相关产品推荐
相关产品推荐

