0

0

理解NumPy中np.linalg.norm的数值精度差异及其浮点数比较策略

心靈之曲

心靈之曲

发布时间:2025-10-03 10:28:08

|

337人浏览过

|

来源于php中文网

原创

理解NumPy中np.linalg.norm的数值精度差异及其浮点数比较策略

本文探讨了在NumPy中使用np.linalg.norm计算L2范数平方时,相较于手动展开计算可能引入微小的数值不精确性。这种不精确性源于np.linalg.norm内部的浮点数平方根运算。尽管打印输出可能显示相同结果,但底层数值存在差异,这是因为NumPy的默认打印精度会截断显示。文章提供了详细示例,并建议在比较浮点数时使用np.allclose,同时指出在计算L2范数平方时,直接使用np.sum(np.square(...))可避免此问题。

1. 问题现象:np.linalg.norm与手动计算的差异

在使用numpy进行数值计算时,我们有时会遇到看似相同但实际存在微小差异的结果。以下面的例子为例,我们尝试计算两个数组a和b之间l2范数平方的负一半。

首先,定义两个NumPy数组:

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]])

接下来,我们使用两种方法计算所需的结果:

方法一:使用 np.linalg.norm

这种方法利用 np.linalg.norm 函数来计算L2范数,然后进行平方。

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

方法二:手动展开 L2 范数平方

这种方法直接根据L2范数平方的定义,通过求差、平方和再求和的方式计算。

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

当我们打印这两个结果时,它们在视觉上是相同的:

print(m1)
# 输出: [[-116.5 -346.  -73.5]]

print(m2)
# 输出: [[-116.5 -346.  -73.5]]

然而,当我们使用 np.array_equal 进行精确比较时,结果却出乎意料:

print(np.array_equal(m1, m2))
# 输出: False

这表明 m1 和 m2 尽管看起来一样,但底层数值并不完全相等。更有趣的是,如果我们创建一个字面量数组来检查相等性:

sanity_check = np.array([[-116.5, -346. ,  -73.5]])
print(np.array_equal(sanity_check, m1))
# 输出: False

print(np.array_equal(sanity_check, m2))
# 输出: True

这进一步确认了 m1 是“异常”的那个。

2. 数值差异的根源:浮点数精度与中间计算

np.linalg.norm 方法与手动计算方法之间的微小差异,主要源于浮点数运算的本质以及 np.linalg.norm 函数的内部实现。

L2 范数的定义与 np.linalg.norm 的实现

L2 范数(欧几里得范数)的定义是向量各元素平方和的平方根。即 ||x||_2 = sqrt(sum(x_i^2))。 当我们需要计算L2范数的平方时,理论上 ||x||_2^2 = sum(x_i^2)。 np.linalg.norm(..., ord=2) 在内部会执行 sqrt(sum(x_i^2)) 的操作。因此,np.linalg.norm(..., ord=2) ** 2 实际上是 (sqrt(sum(x_i^2))) ** 2。

浮点数运算的精度问题

计算机中,浮点数(如Python中的float,NumPy中的np.float64)的表示是有限精度的。这意味着某些实数无法被精确表示,只能近似。当进行数学运算,尤其是涉及平方根等操作时,这种近似性可能导致微小的误差累积。

考虑一个简单的例子:

print(np.sqrt(8**2 + 13**2)**2)
# 输出: 232.99999999999997

print(8**2 + 13**2)
# 输出: 233

在这个例子中,8**2 + 13**2 结果是精确的整数 233。然而,np.sqrt(233) 会产生一个浮点数近似值,即使这个近似值再被平方,也可能无法完全恢复到原始的整数 233,而是产生一个非常接近但略有偏差的浮点数,例如 232.99999999999997。

PPT.AI
PPT.AI

AI PPT制作工具

下载

回到我们的 m1 和 m2,m1 的计算路径是: m1 = - (np.sqrt(np.sum(np.square(diff)))) ** 2 / 2 而 m2 的计算路径是: m2 = - np.sum(np.square(diff)) / 2

m1 在中间多了一步 sqrt 操作,正是这一步引入了浮点数精度误差。为了验证这一点,我们可以查看 m1 和 m2 的原始数值:

print(m1.tolist())
# 输出: [[-116.49999999999999, -346.0, -73.5]]

print(m2.tolist())
# 输出: [[-116.5, -346.0, -73.5]]

可以看到,m1 的第一个元素 -116.49999999999999 与 m2 的 -116.5 存在微小的差异。

3. 打印输出的假象:NumPy的显示精度

尽管 m1 和 m2 存在实际的数值差异,但 print() 函数默认情况下却显示它们是相同的。这是因为NumPy的打印选项(由 np.set_printoptions 控制)会根据设定的精度对浮点数进行四舍五入或截断显示。

我们可以通过 np.get_printoptions() 查看当前的打印设置:

print(np.get_printoptions())
# 典型输出示例: {'edgeitems': 3, 'threshold': 1000, 'floatmode': 'maxprec', 'precision': 3, 'suppress': False, 'linewidth': 75, 'nanstr': 'nan', 'infstr': 'inf', 'sign': '-', 'formatter': None, 'legacy': False}

其中,'precision': 3 表示默认显示小数点后3位。由于 m1 和 m2 的差异发生在更低的位数上,因此在默认的显示精度下,这些差异被隐藏了。

如果我们临时提高打印精度,就可以看到实际的差异:

with np.printoptions(precision=17): # 设置更高精度
    print(m1)
    # 输出: [[-116.49999999999998607 -346.00000000000000000  -73.50000000000000000]]
    print(m2)
    # 输出: [[-116.50000000000000000 -346.00000000000000000  -73.50000000000000000]]

通过将 precision 设置为更高的值(例如17),我们能够清晰地看到 m1 和 m2 之间微小的数值差异。

4. 最佳实践与建议

处理浮点数精度问题是数值计算中的常见挑战。以下是一些建议和最佳实践:

4.1 避免直接的浮点数相等性比较

由于浮点数精度问题,直接使用 == 运算符或 np.array_equal() 来比较浮点数通常是不可靠的。即使两个数在数学上应该相等,也可能因为微小的计算误差而导致它们不相等。

4.2 使用容忍度比较:np.allclose()

在比较浮点数时,应使用带有容忍度(tolerance)的比较方法。NumPy 提供了 np.allclose() 函数,它允许指定一个绝对容忍度(atol)和一个相对容忍度(rtol),只有当两个数组的对应元素之差在这些容忍度之内时,才认为它们相等。

# 检查 m1 和 m2 是否在默认容忍度下接近
print(np.allclose(m1, m2))
# 输出: True (通常默认容忍度足以覆盖这种微小差异)

# 可以手动指定容忍度
print(np.allclose(m1, m2, rtol=1e-05, atol=1e-08))
# 输出: True

np.allclose() 是处理浮点数比较的标准方法。

4.3 针对L2范数平方的优化

如果你的目标是计算L2范数的平方,而不是L2范数本身,那么直接使用 np.sum(np.square(...)) 是更优的选择。这种方法避免了中间的 np.sqrt() 操作,从而减少了引入浮点数精度误差的可能性。

# 推荐计算 L2 范数平方的方法
squared_l2_norm = np.sum(np.square(a[:, np.newaxis, :] - b[np.newaxis, :, :]), axis=-1) / 2

这种方法不仅在数值上更精确,而且在某些情况下也可能略微提高计算效率,因为它省去了一次平方根运算。

总结

本文深入探讨了在NumPy中计算L2范数平方时,np.linalg.norm 方法可能引入数值不精确性的问题。核心原因在于 np.linalg.norm 内部的平方根操作会产生浮点数误差,即使随后再进行平方也无法完全消除。同时,NumPy的默认打印精度会掩盖这些微小的差异。为了确保数值比较的准确性,我们应避免直接的浮点数相等性判断,转而使用 np.allclose() 进行容忍度比较。此外,对于L2范数的平方计算,直接使用 np.sum(np.square(...)) 是一种更精确且推荐的实践。理解这些浮点数计算的细微之处,对于编写健壮和高精度的数值代码至关重要。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
python中print函数的用法
python中print函数的用法

python中print函数的语法是“print(value1, value2, ..., sep=' ', end=' ', file=sys.stdout, flush=False)”。本专题为大家提供print相关的文章、下载、课程内容,供大家免费下载体验。

193

2023.09.27

python print用法与作用
python print用法与作用

本专题整合了python print的用法、作用、函数功能相关内容,阅读专题下面的文章了解更多详细教程。

19

2026.02.03

css中float用法
css中float用法

css中float属性允许元素脱离文档流并沿其父元素边缘排列,用于创建并排列、对齐文本图像、浮动菜单边栏和重叠元素。想了解更多float的相关内容,可以阅读本专题下面的文章。

595

2024.04.28

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

108

2025.10.23

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1567

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

241

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

150

2025.10.17

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

37

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

136

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 5万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号