首页/新闻资讯/正文详情

Kornia 修复四元数奇点处 NaN/Inf 梯度:`quaternion_exp_to_log` 与 `euler_from_quaternion` 的边界防护实现解析

发布时间:2026/9/24 10:28:58 来源:云帆数科 栏目:资讯中心
Kornia 修复四元数奇点处 NaN/Inf 梯度:`quaternion_exp_to_log` 与 `euler_from_quaternion` 的边界防护实现解析
计算机视觉人工智能深度学习图像处理【免费下载链接】kornia Geometric Computer Vision Library for Spatial AI项目地址https://gitcode.com/gh_mirrors/ko/kornia点击查看免费下载导读位姿优化与刚体运动学中四元数对数和欧拉角提取是高频操作但在旋转奇点单位四元数、万向锁处其内部的反三角函数acos/asin导数无界导致反向传播出现0 * inf nan或inf梯度直接摧毁整个优化过程。本文基于 Kornia 仓库的迁移记录changelog.d/migration-089.fixed.md对应 issue #4007、PR #4228深入解析这一缺陷的数学根源、torch.wheredetach的防护实现模式、字节级一致的前向结果验证以及测试套件中如何跨 PyTorch 版本锁定该行为。读完本文你将理解旋转参数化在反向传播中的数值陷阱并能复现、验证这一修复。一、问题背景旋转奇点处的梯度灾难Kornia 的几何模块kornia/geometry/conversions.py提供了一批旋转表示之间的互转函数包括四元数对数/指数映射与欧拉角转换quaternion_exp_to_log源码将(w, x, y, z)顺序、形状为(*, 4)的四元数映射到形状为(*, 3)的对数向量是四元数指数映射quaternion_log_to_exp的逆操作euler_from_quaternion源码将四个分离张量w, x, y, z转换为(roll, pitch, yaw)三元组弧度制。这两个函数的数值核心都依赖反三角函数quaternion_exp_to_log计算acos(w)euler_from_quaternion计算asin(sinp)其中sinp 2 * (w * y - z * x)经clamp(-1, 1)后作为asin的参数。问题恰恰出在这些反三角函数的导数上d(acos)/dw -1 / sqrt(1 - w²) 在 w ±1 处无界 d(asin)/dx 1 / sqrt(1 - x²) 在 x ±1 处无界1.1 单位四元数0 * inf nanquaternion_exp_to_log在w 1处恰好命中acos的定义域边界——而w 1正是单位四元数(1, 0, 0, 0)这是位姿优化最标准的初始化起点。此时acos的导数在w 1处为-inf单位四元数的向量部分(0, 0, 0)恰好为零两者相乘得到0 * inf nan。从源码注释conversions.py可以看到torch在所有受支持的版本上于边界处返回-inf因此这一缺陷并非某个 torch 版本特有。测试用例test_convention_gradient_is_finite_at_the_acos_boundary_4007tests/geometry/test_conversions.py明确记录每个反向传播只要经过单位四元数这一最常见输入梯度就会变成nan。1.2 万向锁pitch梯度爆掉euler_from_quaternion的pitch由asin(sinp)求得当pitch ±π/2万向锁时sinp ±1同样命中asin的定义域边界asin的导数在该处为inf。源码注释conversions.py指出此前只要下游有任何东西对pitch求导所有四个四元数系数的梯度都会变成nan或inf——与被返回的三元组本身是否代表输入旋转无关。1.3 一个被版本掩盖的假修复修复前的代码用clamp限制的是值而非梯度。torch.clamp的反向传播行为随版本变化torch 2.14clamp的反向在闭边界处直接透传梯度-inf/inf原样到达乘法处产生nantorch 2.14clamp的反向在闭边界处返回0-inf在到达乘法之前被清零缺陷被掩盖而非消除。测试注释tests/geometry/test_conversions.py明确指出这是clamp行为的变化而非acos的变化因此修复绝不能依赖任何特定版本的clamp反向语义——这正是防护方案要独立于版本工作的原因。二、修复方案值取真实参数梯度走安全参数修复采用分离值路径与梯度路径的经典技巧前向值从真实可能位于边界上的参数的detach副本计算梯度则在一个替换过的安全参数上微分使 autograd 根本不会在边界点对acos/asin求导。2.1quaternion_exp_to_log的防护conversions.pyw_clamped torch.clamp(quaternion_scalar, min-1.0, max1.0) at_boundary w_clamped.abs() 1.0 safe_w torch.where(at_boundary, torch.zeros_like(w_clamped), w_clamped) acos_w torch.where(at_boundary, w_clamped.detach().acos(), safe_w.acos()) quaternion_log: torch.Tensor (quaternion_vector * acos_w / norm_q).to(orig_dtype)逐行拆解w_clamped把标量部分限制到[-1, 1]保证acos合法输入at_boundary标记|w| 1的边界元素safe_w把边界元素的参数替换为0acos(0) π/2导数有界非边界元素保持原值acos_w是一个torch.where混合张量边界元素取w_clamped.detach().acos()——真实值但已detach不参与求导非边界元素取safe_w.acos()——参与求导但参数远离边界导数有界。由于acos在±1处连续只是导数发散detach副本上算出的值与未防护调用逐位一致前向结果完全不变。2.2euler_from_quaternion的防护conversions.pyat_boundary sinp.abs() 1.0 safe_sinp torch.where(at_boundary, torch.zeros_like(sinp), sinp) pitch torch.where(at_boundary, sinp.detach().asin(), safe_sinp.asin())与 2.1 完全同构边界元素用sinp.detach().asin()取真实值asin(±1) ±π/2梯度走safe_sinp.asin()参数替换为0asin在0处导数恰为1有界。测试注释tests/geometry/test_conversions.py说明该防护是镜像了quaternion_exp_to_log的acos边界修复。2.3 为什么detach副本的前向值安全关键数学事实acos/asin在边界处值收敛acos(±1) 0/πasin(±1) ±π/2只有导数发散。因此从真实参数可能恰好是 ±1取detach值 → 前向结果与未防护实现完全相同从替换参数0求梯度 → 梯度路径上不存在无界导数torch.where的反向只会对被选中分支的输入回传梯度边界元素的safe_w/safe_sinp分支不会收到梯度。三、验证字节级一致与跨版本稳定修复的正确性由测试套件tests/geometry/test_conversions.py从两个维度锁定3.1 前向结果字节级不变test_convention_gradient_is_finite_at_the_acos_boundary_4007tests/geometry/test_conversions.py验证单位四元数的对数为全零[0, 0, 0]前向值不变对接近边界的输入w 1 - eps防护实现与未防护表达式直接clamp(...).acos()输出完全一致——这证明了torch.where的非边界分支在远离w ±1处完全惰性防护不会移动任何前向位变更记录还提到在 500 个随机输入含多个强制落在精确边界上的样本上前向结果与旧实现字节级相同。3.2 梯度在所有边界场景有限同一测试覆盖三类边界输入tests/geometry/test_conversions.pyidentity torch.tensor((1.0, 0.0, 0.0, 0.0), ...) # w 1单位四元数 antipode torch.tensor((-1.0, 0.0, 0.0, 0.0), ...) # w -1对跖点 non_unit torch.tensor((1.0, 0.1, 0.0, 0.0), ...) # 非单位、向量部分非零的边界输入三者梯度均断言torch.isfinite(...).all()。其中非单位输入尤其关键它说明即使0 * inf的抵消不再成立向量部分不为零梯度也必须保持有限——防护不依赖任何恰好相乘消掉的巧合。对euler_from_quaterniontest_convention_pitch_gradient_is_finite_at_gimbal_lock_4007tests/geometry/test_conversions.py构造w1, x0, y0.5, z0使sinp 2*(w*y - z*x) 1.0精确命中边界断言pitch等于π/2且对w/x/y/z四个系数的梯度全部有限。3.3 为什么 CI 矩阵里 torch 2.5.1 能区分修复测试注释tests/geometry/test_conversions.py指出由于clamp的反向在 torch 2.14 上已把-inf清零该缺陷只在 torch 2.5.1 等旧版本上暴露。因此这两个测试在 base 分支上2.5.1 失败、2.14 通过正是用来跨版本鉴别缺陷是否存在、防护是否真正生效的判别用例。四、已知边界对跖点的有限大梯度不在本次范围变更记录明确划定了本次修复的范围边界quaternion_exp_to_log的对跖点(-1, 0, 0, 0)仍会返回一个大但有限的梯度约π/eps其来源是既有实现中用clamp(mineps)夹取零范数后的除法与acos导数无界无关属预先存在且本次不处理的行为。从源码conversions.py可确认norm_q torch.norm(quaternion_vector, ...).clamp(mineps)对跖点的向量部分为零范数被夹到eps 1e-8acos(-1) π除以eps即产生约π × 10⁸的梯度。这是有限值不会破坏优化但数值量级很大使用时应知晓。五、使用注意事项与相关约定结合源码文档字符串与测试实际使用这两个函数时需留意以下约定5.1 输入不归一化的警告两者都不对输入四元数做归一化conversions.pyquaternion_exp_to_log([0.5, 0.5, 0, 0])返回[1.0471975511965976, 0, 0]比归一化后同一旋转的[0.7853981633974484, 0, 0]大 33%[2, 0, 0, 0]因w被clamp到 1 而返回原点euler_from_quaternion传入2q会使sinp饱和到 ±1被误报为万向锁。测试以kornia#3953为消息对这两个行为做了锁定tests/geometry/test_conversions.py。5.2 float16/bfloat16 的自动升档quaternion_exp_to_log会将float16/bfloat16输入升档为float32计算再转回conversions.py保证默认eps 1e-8可表示——否则在float16下默认eps下溢为 0单位四元数会返回[nan, nan, nan]issue #3966测试见 tests/geometry/test_conversions.py。5.3 欧拉角万向锁的值缺陷仍在本次修复只处理梯度。文档警告conversions.py明确在pitch ±π/2处返回的三元组通常不代表输入旋转且没有万向锁分支来声明这一点——roll/yaw由两个在此处相消为零的量做atan2得到结果由舍入决定随 dtype、torch 版本和输入的一个 ulp 变化而漂移issue #3950。值问题与梯度问题需分开对待。5.4eps参数建议quaternion_exp_to_log的eps默认1e-8。当输入为float64且希望精确落到边界时可像测试那样传torch.finfo(dtype).epstests/geometry/test_conversions.py——注意 docstring 示例中单位四元数使用epstorch.finfo(...).eps得到[0., 0., 0.]。六、总结一类可复用的梯度奇点防护模式本次变更changelog 条目见 changelog.d/migration-089.fixed.md解决的是一类普遍存在的数值问题任何在定义域边界求导的函数acos、asin、sqrt、log等都可能让梯度变为nan/inf而修复模式高度可复用用torch.where标记边界元素边界元素的前向值取自真实参数的detach副本值连续无损边界元素的梯度走替换后的安全参数导数有界无 nan配套测试同时断言前向值逐位不变、梯度在多个边界场景下有限并覆盖多个 torch 版本以抵御版本掩盖缺陷。Kornia 正是以这种方式让位姿优化最常用的初始化点——单位四元数——在反向传播中不再产生nan同时保证euler_from_quaternion在万向锁处的pitch梯度有限且前向数值结果与修复前逐字节一致实现了梯度修复值不动的稳健变更。赞分享计算机视觉人工智能深度学习图像处理【免费下载链接】kornia Geometric Computer Vision Library for Spatial AI项目地址https://gitcode.com/gh_mirrors/ko/kornia点击查看免费下载相关推荐Kornia 四元数梯度修复深度解析quaternion_to_axis_angle 在恒等旋转处的正确梯度4237Kornia 四元数梯度修复深度解析 quaternion_to_axis_angle 在恒等旋转处的正确梯度 4237 导读 本文以 changelo计算机视觉深度学习人工智能图像处理Kornia 3D 边界框非有限坐标校验修复解析validate_bbox3d 的 NaN/Inf 处理与错误信息改进Kornia 3D 边界框非有限坐标校验修复解析validate_bbox3d 的 NaN/Inf 处理与错误信息改进 导读 本文围绕 Kornia 几何模块计算机视觉人工智能深度学习图像处理Kornia solve_cubic 三实根分支的 acos 边界梯度修复从 nan 梯度到安全的替参求导约定Kornia solve_cubic 三实根分支的 acos 边界梯度修复从 nan 梯度到安全的替参求导约定 本文讲解 Kornia 多项式求解器在 sol计算机视觉深度学习人工智能图像处理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

鸿蒙开发:ArrayList,可不会让UI更新哦
鸿蒙开发:ArrayList,可不会让UI更新哦

前言有同学遇到了一个问题&#xff0c;他是使用ArrayList来存储的数据&#xff0c;在动态给集合添加数据后&#xff0c;UI并未更新&#xff0c;代码如下&#xff1a;import { ArrayList } from kit.ArkTS;Entry Component struct Index {State numItems: ArrayList<string&g… · 2026/9/24 10:28:51

用NanoVNA调NFC天线匹配:从S11到读卡距离全面提升
用NanoVNA调NFC天线匹配:从S11到读卡距离全面提升

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 10:28:45

深度解读:Work Agent如何联动企业知识与协作系统完成长程业务任务
深度解读:Work Agent如何联动企业知识与协作系统完成长程业务任务

AI技术的落地轨迹&#xff0c;正在从即时对话向自主任务执行持续迁移。早期大模型只能完成单轮问答&#xff0c;用户提出问题&#xff0c;模型给出对应文本输出&#xff0c;上下文窗口限制了任务的延续性&#xff1b;随后多轮对话形态出现&#xff0c;模型可以记住一段对话内的… · 2026/9/24 10:28:33

swagger-codegen Eiffel 客户端 FORMAT_TEST 模型文档解读:OpenAPI 数据类型到 Eiffel 类型的映射规则
swagger-codegen Eiffel 客户端 FORMAT_TEST 模型文档解读:OpenAPI 数据类型到 Eiffel 类型的映射规则

开发工具代码生成API设计 【免费下载链接】swagger-codegen swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition. 项目地址&#xff1a; http… · 2026/9/24 11:07:55

Arduino ESP32离线安装包:构建可复现、路径无关的嵌入式开发环境
Arduino ESP32离线安装包:构建可复现、路径无关的嵌入式开发环境

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 11:07:55

Linux服务器SCMP整改实践:禁用SSH Root远程登录(PermitRootLogin no)修复指南
Linux服务器SCMP整改实践:禁用SSH Root远程登录(PermitRootLogin no)修复指南

目录 一、背景二、现象分析三、根因定位四、整改前准备五、验证 Sudo 权限六、整改实施七、验证整改结果八、本次整改经验总结九、标准验证清单 一、背景 在企业 Linux 安全基线检查中&#xff0c;经常会遇到如下检查项&#xff1a; 检查项内容类别Configure SSH Server检查… · 2026/9/24 11:07:49

ESP32 SPI驱动W5500以太网实战:从时序到稳定运行
ESP32 SPI驱动W5500以太网实战:从时序到稳定运行

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 11:07:49

固态激光雷达如何让AGV装上“火眼金睛”:从选型到部署全解析
固态激光雷达如何让AGV装上“火眼金睛”:从选型到部署全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 11:07:49

Spectrum 前端 GraphQL Fragments 最佳实践:从粒度拆分到性能约束的完整指南
Spectrum 前端 GraphQL Fragments 最佳实践:从粒度拆分到性能约束的完整指南

后端前端即时通讯社交 【免费下载链接】spectrum Simple, powerful online communities. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/sp/spectrum 点击查看 免费下载 导读 Fragments 是 Spectrum 开源社区项目中前端与 GraphQL API 交互的核心基础设施&#xff1a… · 2026/9/24 11:07:37

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介&#xff1a;这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源&#xff0c;围绕YOLOv8实现渔船作业监控系统&#xff0c;可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件&#xff0c;约24.21MB&#xff0c;以70个Python源码文件为… · 2026/9/24 0:00:13

1D-CNN时间序列建模实战:从Conv1d原理到工业落地
1D-CNN时间序列建模实战:从Conv1d原理到工业落地

简介&#xff1a;面向时间序列数据建模的一维卷积神经网络完整实现&#xff0c;适合深度学习入门者及需要快速验证时序模型的研究者&#xff0c;能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小&#xff0c;只有3KB&#xff0c;内含3个Python脚… · 2026/9/24 0:00:26

柔软的L:汉语语流中被忽视的舌肌张力控制
柔软的L:汉语语流中被忽视的舌肌张力控制

1. 这个“L”不是字母表里的L&#xff0c;而是舌尖上的L最近在几个方言群和语音教学社群里&#xff0c;反复看到有人发一句&#xff1a;“也说字母L&#xff1a;柔软的长舌”。初看以为是英语发音课笔记&#xff0c;点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码