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

Numpy均值计算结果随行顺序不同略有差异

浮点运算顺序导致的均值计算差异

我们在测试中使用np.testing.assert_allclose验证两组数据的均值是否一致,但发现数据内容完全相同仅顺序不同时,计算出的均值存在微小差异。以下是最简复现代码:

import numpy as np

x = np.array(
    [[0.5224021, 0.8526993], [0.6045113, 0.7965965], [0.5053657, 0.86290526], [0.70609194, 0.7081201]],
    dtype=np.float32,
)
y = np.array(
    [[0.5224021, 0.8526993], [0.70609194, 0.7081201], [0.6045113, 0.7965965], [0.5053657, 0.86290526]],
    dtype=np.float32,
)
print("X mean", x.mean(0))
print("Y mean", y.mean(0))
z = x[[0, 3, 1, 2]]
print("Z", z)
print("Z mean", z.mean(0))

np.testing.assert_allclose(z.mean(0), y.mean(0))
np.testing.assert_allclose(x.mean(0), y.mean(0))

在Python 3.10.6 + NumPy 1.24.2环境下运行,输出如下:

X mean [0.58459276 0.8050803 ]
Y mean [0.5845928 0.8050803]
Z [[0.5224021  0.8526993 ]
 [0.70609194 0.7081201 ]
 [0.6045113  0.7965965 ]
 [0.5053657  0.86290526]]
Z mean [0.5845928 0.8050803]
Traceback (most recent call last):
  File "/home/nuric/semafind-db/scribble.py", line 19, in <module>
    np.testing.assert_allclose(x.mean(0), y.mean(0))
  File "/home/nuric/semafind-db/.venv/lib/python3.10/site-packages/numpy/testing/_private/utils.py", line 1592, in assert_allclose
    assert_array_compare(compare, actual, desired, err_msg=str(err_msg),
  File "/usr/lib/python3.10/contextlib.py", line 79, in inner
    return func(*args, **kwds)
  File "/home/nuric/semafind-db/.venv/lib/python3.10/site-packages/numpy/testing/_private/utils.py", line 862, in assert_array_compare
    raise AssertionError(msg)
AssertionError: 
Not equal to tolerance rtol=1e-07, atol=0

Mismatched elements: 1 / 2 (50%)
Max absolute difference: 5.9604645e-08
Max relative difference: 1.0195925e-07
 x: array([0.584593, 0.80508 ], dtype=float32)
 y: array([0.584593, 0.80508 ], dtype=float32)

目前可以通过降低断言容差解决,但想了解该现象的原因是什么?


原因分析

这是浮点数精度限制和加法运算的顺序敏感性导致的:

  • 浮点数精度限制:你使用的float32(单精度浮点数)仅支持约7-8位十进制有效数字,无法精确表示所有实数,每次加法运算都会产生微小的舍入误差。
  • 加法的顺序影响误差累积:浮点数加法不满足结合律,即(a + b) + c与a + (b + c)在浮点数运算中结果可能不同。不同的累加顺序会导致舍入误差的累积方式不同,最终总和(进而均值)出现微小差异。你的示例中x和y元素相同但顺序不同,NumPy计算均值时的累加顺序不同,因此产生了约5.96e-08的差异。
  • NumPy实现细节:mean函数底层是先计算总和再除以元素个数,不同顺序的数组会因累加误差累积方式不同,导致最终均值出现细微差别;而z是x按y的顺序重排后的数组,累加顺序与y一致,所以均值完全相同。

解决建议

  • 调整断言容差:针对float32类型,将assert_allclose的rtol(相对容差)调整到1e-6左右,atol(绝对容差)调整到1e-7左右,即可兼容正常的浮点误差:
    np.testing.assert_allclose(x.mean(0), y.mean(0), rtol=1e-6, atol=1e-7)
    
  • 使用更高精度浮点数:改用float64(双精度浮点数),其有效数字可达15-17位,此类误差会显著缩小,甚至在多数场景下可忽略。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 07:52:54