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

为何使用np.linalg.norm会产生数值不等,手动实现却无此问题?

np.linalg.norm与平方求和的数值差异问题分析

前提代码

import numpy as np
a = np.array([[ 0,  1, 10,  2,  5]])

b = np.array([[ 0,  1, 18, 15,  5],
              [13,  9, 23,  3, 22],
              [ 2, 10, 17,  4,  8]])

两种计算方法

方法1(使用np.linalg.norm)

m1 = -np.linalg.norm(a[:, np.newaxis, :] - b[np.newaxis, :, :], axis=-1) ** 2 / 2

方法2(直接平方求和)

m2 = -np.sum(np.square(a[:, np.newaxis, :] - b[np.newaxis, :, :]), axis=-1) / 2

测试现象

  • 打印输出外观一致:
array([[-116.5, -346. ,  -73.5]])
  • 相等性检查结果:
>>> np.array_equal(m1, m2)
False
>>> sanity_check = np.array([[-116.5, -346. ,  -73.5]])
>>> np.array_equal(sanity_check, m1)
False
>>> np.array_equal(sanity_check, m2)
True

原因解释

1. np.linalg.norm的计算引入精度误差

np.linalg.norm计算L2范数时,会先对元素平方求和,再开平方根,之后我们又对结果做了平方操作。这个开根号再平方的额外步骤会引入浮点数精度损失:浮点数无法精确表示所有实数,开根号过程中产生的微小误差会在平方后被保留,导致最终结果和直接平方求和的m2存在微小差异。

而方法2直接对差值平方后求和,没有开根号的中间步骤,完全基于整数运算(差值的平方都是整数,求和后也是整数),除以2后得到的是精确的浮点数(如-116.5是精确可表示的),所以能和字面量sanity_check完全匹配。

2. 打印格式化掩盖了数值差异

numpy在打印数组时,会默认对浮点数进行格式化输出(通常显示1-2位小数),把微小的精度差异隐藏了。但实际上m1存储的是带有微小误差的浮点数,比如可能是-116.50000000000001或者-116.49999999999999,这些值在打印时会被四舍五入显示为-116.5,但和精确值的严格相等检查会失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 05:02:16