导读:本期聚焦于小伙伴创作的《Attention里的Softmax总算溢出怎么办?Softmax数值稳定性优化怎么做》,敬请观看详情。训练大模型时,Attention矩阵里的Softmax经常因为指数运算爆出无穷大,导致梯度变成NaN。直接拿原始分数做exp很容易在数值上失控。常用做法是先减去每行最大值再算指数,配合log_sum_exp技巧避免除零和溢出。本文从原理到实现讲清楚为什么减去最大值不影响结果,以及如何在自注意力里安全地完成归一化,让长序列训练不再频繁中断。

在Transformer的Attention计算中,Softmax函数负责对查询和键的点积分数做归一化。当序列长度变大或分数绝对值偏高时,指数运算会让数值迅速膨胀,最终超出浮点数表示范围,出现Inf或NaN,这就是典型的Attention计算溢出问题。解决它的核心思路是在不改动数学等价性的前提下,提升Softmax的数值稳定性。

Attention里的Softmax总算溢出怎么办?Softmax数值稳定性优化怎么做

为什么Softmax会发生数值溢出

标准Softmax的定义为对向量x的每个元素计算exp(x_i)再除以所有exp的和。假设x里有一个值是1000,那么exp(1000)在单精度浮点数下远远超过了约3.4e38的上限,直接变成Inf。一旦分子或分母出现Inf,后续除法和梯度回传都会失效,训练被迫停止。

在Attention里,分数矩阵由Q和K相乘并除以根号d得到。如果维度较大或没有合理缩放,某些分值可能非常极端。尤其是批量训练时,不同样本的最大值差异巨大,不加处理就会频繁触发溢出。理解这一点,才能明白稳定性优化并不是可选项,而是工程实现的必选项。

减去最大值:最简单有效的等价变换

数学上,给x的每个元素同时减去常数c,Softmax结果不变,因为分子分母的exp(c)可以约掉。通常取c为x里的最大值max(x),这样平移后的最大指数为exp(0)=1,其余均为负数指数,不会超过1,从根源上杜绝了上溢。

举例来说,若分数为[1000, 1001, 999],直接算会溢出;减去最大值1001后变成[-1, 0, -2],exp结果分别是[0.3679, 1, 0.1353],求和后再归一化,得到稳定概率。这种操作在PyTorch的softmax里已默认集成,但手写Attention时必须显式写上,否则自定义核函数仍会出错。

下溢与log_sum_exp的配合

减去最大值解决了上溢,但小数指数可能下溢成0,导致求和后为0进而除零。为此在算对数似然或交叉熵时,应使用log_sum_exp技巧:先取最大a,再算log(sum(exp(x-a)))+a,以对数域安全求和。

例如计算log_softmax,可写为x - (x.max() + log(sum(exp(x - x.max()))))。这样即使个别项下溢为0,求和项依然保留主要贡献,不会让分母为0,也方便后续与标签做稳定交叉熵。

Attention中的具体优化实现

在自注意力分数S上,应先沿最后一个维度求最大值,再广播减去。伪代码逻辑为:S = S - S.max(dim=-1, keepdim=True);然后e = exp(S);P = e / e.sum(dim=-1, keepdim=True)。这样无论序列多长,概率矩阵始终有限。

如果还做mask,要把padding位置设成负无穷,减去最大值后它们变成负无穷减有限值仍为负无穷,exp后为0,求和不受影响。但要注意某些框架负无穷减负无穷会得到NaN,因此mask应在减最大值前用大负数(如-1e9)替代,而不是真正inf。

缩放与混合精度下的额外注意

除以根号d是一种软性稳定,降低分值方差。在混合精度用float16时,最大正值仅约65504,所以减最大值更为关键。建议先在float32算Softmax再转回半精度,或确保减最大值后指数和不超过半精度上限。

另外,一些高效Attention库采用分块计算最大值再归一,逻辑相同但需注意跨块最大值同步。只要遵循先减最大、后指数、再归一的顺序,就能在绝大多数硬件上避免溢出。

常见错误与排查清单

不少实现漏写keepdim,导致广播形状错误,概率和不为1;还有人在mask时使用bool直接乘0,却忘了负无穷已污染最大值。下表列出典型问题和对策。

问题现象可能原因修复方式
Loss变成NaN未减最大值直接exp显式减去行最大值
概率和不为1keepdim缺失保持维度一致再除和
mask位置概率非0用inf后减inf得NaNmask用-1e9代替inf

只要按上述方式组织代码,Attention里的Softmax数值稳定性优化就能落地,长文本训练也不再被溢出中断。数值稳定不是理论细节,而是保障模型可训的底线。

Softmax数值稳定性Attention计算溢出log_sum_exp修改时间:2026-08-11 20:39:26

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。