【问题标题】:Numpy array subtraction: inconsistent values for large arraysNumpy数组减法:大数组的值不一致
【发布时间】:2016-12-05 06:31:59
【问题描述】:

这是我今天遇到的一个问题:我试图从(大)整个矩阵中减去矩阵的第一行。作为测试,我使所有行都相等。这是一个 MWE:

import numpy as np
first = np.random.normal(size=10)
reference = np.repeat((first,), 10000, axis=0)
copy_a = np.copy(reference)
copy_a -= copy_a[0]
print np.all(copy_a == 0) # prints False

哇哦 - False!所以我尝试了另一件事:

copy_b = np.copy(reference)
copy_b -= reference[0]
np.all(copy_b == 0) # prints True

检查新的copy_a数组,我发现copy_a[0:818]全为零,copy_a[820:]是原始值,而copy_a[819]被部分操作。

In [115]: copy_a[819]
Out[115]: 
array([ 0.        ,  0.        ,  0.57704706, -0.22270692, -1.83793342,
        0.58976187, -0.71014837,  1.80517635, -0.98758385, -0.65062774])

看起来在操作过程中,numpy 回去查看copy_a[0],发现它全为零,因此从数组的其余部分中减去零。我觉得这很奇怪。这是一个错误,还是预期的numpy 结果?

【问题讨论】:

  • 在您的示例中,-= 正确工作的元素数量是 8192,正好是 2^13!

标签: python arrays numpy multidimensional-array


【解决方案1】:

这个问题实际上已经多次报告给 numpy 存储库(见下文)。 It is considered a bug,但在不牺牲性能(复制输入数组)的情况下很难修复,因为很难正确检测两个数组是否共享内存。

因此,现在,您最好按照@Torben's answer 中的说明复制copy_a[0]

问题的本质是您在迭代时正在修改数组。它恰好在copy_a[819] 之前有效,因为8192 (819×10+2) 是size of numpy's assign buffer


  1. https://github.com/numpy/numpy/issues/6119
  2. https://github.com/numpy/numpy/issues/5241
  3. https://github.com/numpy/numpy/issues/4802
  4. https://github.com/numpy/numpy/issues/2705
  5. https://github.com/numpy/numpy/issues/1683

【讨论】:

    【解决方案2】:

    中缀运算符-= 就地修改数组,这意味着您正在将地毯拉到自己的脚下。您看到的效果可能与结果的内部缓存有关(即第一次“提交”发生在 818 行之后)。

    解决方法是将减数换成另一个数组:

    copy_a -= copy_a[0].copy()
    

    【讨论】:

    • 不错。似乎与上面@DYZ 指出的 2^13 相匹配。但这似乎不是一个坏主意吗?困扰我的是这种不一致。我希望这要么全为零,要么在第一行之后立即放弃(严格就地)。在当前的实现中,最终的答案似乎取决于缓存大小。
    • @VBB:我认为这个想法只是自引用就地操作具有未定义的行为。
    • 是的,完全正确。通常,当您使用大型数组时,您需要清楚地了解底层内存分配,否则您的 RAM 将很快消失。 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 2021-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多