LLM:Transformer注意力机制的Softmax算法

Softmax算法是将每个query的点积分数(打分)变成一组非负、加起来等于1的权重比,用于表示对某个词的重视程度。

词汇理解

占比与权重

对比维度 占比 权重
核心本质 客观事实(结构比例) 反映部分在整体中“占了多少” 主观标准(重要系数) 反映某个指标被人为“看得多重”
总和约束 必须等于 100%(或 1) (如男60%+女40%=100%) 不必须等于 100% (可以是 10、20、70,也可以是 50%、30%、20%)
计算逻辑 除法:部分值 ÷ 总体值 数据一变,占比跟着自动变 预先设定:由专家、算法或规则提前赋值 数据变了,权重通常保持不变
核心作用 描述“存量现状” 告诉你蛋糕现在是怎么切的 影响“决策评价” 决定蛋糕应该偏向谁,或者哪块更值钱
回答的问题 “有多少?” (例:这个产品占总销量的多少?) “多重要?” (例:销量指标在考核中占多少分比重?)
变动依据 随原始数据波动而被动变化 随评价目的调整而主动设定
通俗比喻 一盘菜里肥肉占了多少克 炒菜时给肥肉的调味系数(有人爱肥肉就调高,怕油腻就调低)

这里的用词是权重,不是占比,占比是客观数据所占总体的比例;权重是人为主观设定的系数,反映人为赋予的相对重要性,目的是让占比大的权重更大,占比小的权重更小。

归一化

归一化:把一堆不能直接比、不能直接当份额用的数,收进同一套规则里;在 Softmax 里,这套规则就是「全是正的,而且加起来等于 1」。

  • 数学层面:把数字拉回同一个起跑线。即把任意范围的数值,压缩到固定的区间(这里是0到1之间),并且让它们的总和等于1。

  • 机制层面:把【得分】翻译成【概率】,本质是为了解决“绝对数值”和“相对意义”的矛盾。把原始的“物理得分”(绝对大小),换算成了【概率分布】(相对可能性)。模型不再关心“你得了多少分”,只关心“在所有候选者中,占多大的比例(占比)。

  • 语义层面:数值变成了总和为1的“概率占比”。

    在点积计算完成、还没【归一化】之前,每个词对当前词都有一个“原始亲密度”(类似于客观数值),经过Softmax归一化之后,这些数值变成了总和为1的“概率占比”。

    但在Attention的公式里,这个归一化后的结果(占比),直接被拿去乘上了Value(信息内容)。此时,这个归一化后的数字,本质上变成了“注意力权重”!

维度 归一化前(点积得分) 归一化后(Softmax输出)
数值状态 绝对值很大,范围不定(如 5.6, -2.3, 10.1) 压缩到 (0,1),且总和 = 1(严格数学占比)
对应你的概念 像“原始物理量”(类似物体的实际克重) 像 “占比”(客观事实:这部分占全体的多少)
在公式中的角色 仅用于比较大小,无法直接使用 被当作“权重”(主观筛选:重要的部分给高分,不重要的给低分)
回答的问题 “这两个词在数值上差多少?” “在计算当前词时,我应该分配多大比例的关注度给这个词?”

在Transformer里,“归一化” 的物理意义是:强行让一堆毫无尺度感的原始数字,先变成“占比”(和为1),再赋予它们“权重”的身份(用来筛选信息)。

理解Transformer中的Softmax,最关键的一句话是:它不是一个“归一化工具”,而是一个“竞争选举”机制。

主动”拉仇恨放大器“

为什么说它不是“归一化工具”?(线性 vs 非线性)

如果你只是把一堆数字“归一化”(比如直接除以总和),那叫线性缩放。
假设三个员工的绩效分是 [100, 60, 40]:

  • 纯归一化(线性):按比例分奖金,奖金比 = 5 : 3 : 2。差距温和,你100分我只比你少40分,但奖金我只比你少一小截。
  • Softmax(指数化):先算 e^分,变成 [2.8e43, 1.1e26, 2.3e17],再归一化。奖金比直接变成了 **99.9% : 0.000...1% : 近乎0%**。

结论:它不是一个被动“算比例”的尺子,而是一个主动“拉仇恨”的放大器。它不忠实地反映原始差距,而是刻意制造碾压局。所以叫“机制”而非“工具”。

固定蛋糕+赢家通吃

为什么叫“竞争选举”?(固定蛋糕 + 赢家通吃)

在注意力机制里,所有词的权重加起来必须 等于 1。这意味着“注意力总预算”是固定的(一块固定的100%蛋糕)。

  • “竞争”:因为蛋糕只有一块,A词拿多了(0.9),B词和C词就必须饿肚子(各拿0.05)。它们在数学上处于零和博弈的状态,互相挤压生存空间。
  • “选举”:Softmax 充当了“计票员”的角色。它把原始得分(Logits)看成“选票数”。票数最高的候选人(词),经过指数放大后,直接赢得绝大多数“注意力席位”(权重)。

保留了“败选者”的微光

“选举”而非“归一化”的核心在于:保留了“败选者”的微光

这是最精妙的地方。如果它是纯粹的“归一化工具”,你可以直接把它变成 Argmax(硬选举),即“得票最高者拿走100%蛋糕,其他人滚蛋”。

但为什么不用Argmax?因为那是独裁(梯度为0,模型无法学习)。

Softmax 是民主选举:

  • 赢家(最大分):拿走了绝大部分权重(比如0.88),主导当前词的语义。
  • 败选者(小分):虽然惨败,但依然保留了极小的非零权重(比如0.05和0.07)。

这0.05和0.07极其重要——它们就像“少数党发言权”。在反向传播(训练)时,模型虽然主要调优赢家,但这微弱的败选者梯度,能让模型在下一次迭代时悄悄地告诉输家:“虽然你这次输了,但你下次稍微改变一下特征,就可能赢回一点权重。”


竞争激烈程度:温度

结合上一轮的“温度”,看竞争激烈程度

既然它是选举,那竞选激烈程度是可以人为操控的,这就是上一轮说的 温度 T:

  • 低温(T<1,如0.5):极端竞争,选票被极度放大,赢家几乎拿满100%,模型变得“极度自信”(适合代码生成、数学推理)。
  • 高温(T>1,如5):温和竞争,选票被压缩,赢家只能拿30%,输家也能拿20%,模型变得“优柔寡断”(适合创意小说、发散对话)。

用一句总结:Softmax 不是在“算平均数”,而是在“搞竞选”——它通过指数运算制造“马太效应”(强者恒强),用100%的固定注意力预算,逼迫不同词激烈争抢,最终选出一个语义上的“主导者”,但同时又给落选者留了一扇“下次翻盘”的梯度之窗。

这句话是理解Transformer灵魂的“题眼”。要精准解读它,我们需要把“数学运算”和“资源分配”两个视角剥离开。

我直接用最通俗的“年终奖分配”来帮你拆解这句话,核心区别就三个字:非线性。

很多人把它简单理解为“除以总和”,但这会错过精髓。我们分四层来拆解,尤其是最后一层“温度”和“计算陷阱”,是区分是否真懂的关键。

第一层:它在做什么?(数学直觉)

假设模型计算出了某个词与所有其他词的“亲密度”得分(Logits)为:[3, 1, 0.2]。

  • 如果直接归一化(除以和):变成 [0.71, 0.24, 0.05]。
  • Softmax 的做法:先取指数 e^x(变成 [20.09, 2.72, 1.22]),再归一化。结果变成 [0.84, 0.11, 0.05]。

核心作用:放大强者,抑制弱者。原本得分3是得分1的3倍,经过Softmax后,权重变成了7.6倍。这就强迫模型“聚焦”在最相关的词上,而不是平均分配注意力。


第二层:为什么必须用指数?(对比 Argmax)

你可能会问:为什么不直接用 Argmax(把最大得分设为1,其余设为0)?那样不是更聚焦吗?

  • Argmax 是“独裁”:梯度几乎处处为0,无法反向传播训练。
  • Softmax 是“民主选举”:它保留了“概率”的连续性。虽然冠军(最大分)权重很高,但亚军(第二分)依然保留了一小部分话语权。这让模型在训练时能微调:“这次虽然你赢了,但下次得分再高一点,你的权重就能从0.8涨到0.9。”

第三层:为什么叫“软”的最大值(Soft)?

因为它在 Softmax 和 Argmax 之间取了一个中间态。

  • 当输入得分差距极大时(如 [100, 1, 1]),Softmax 趋近于 Argmax(输出接近 [1, 0, 0])。
  • 当输入得分差不多时(如 [1, 1, 1]),Softmax 趋近于平均池化(输出接近 [0.33, 0.33, 0.33])。

在注意力机制中,这个性质至关重要:它让模型根据上下文动态调整“锐利度”——当某个词明确时,注意力非常尖锐;当两个词都相关时,注意力可以同时分配给两者。


第四层:面试官爱问的“进阶理解”(真功夫)

1. 为什么点积后要除以 √d(缩放)?

这是大多数人的盲区。假设维度 d=512,点积的方差会变成 d(即512)。这意味着输入Softmax的得分会很大(如几十或几百)。

  • 后果:得分极大时,Softmax 的梯度趋近于0(饱和区),模型学不动。
  • 解法:除以 √d,把方差拉回1,让得分落在“指数函数变化最敏感”的区间(如 -3 到 +3),梯度最大,训练最顺畅。

2. “温度系数” T 是什么?(调参精髓)

公式其实是 Softmax(x/T)。当 T=1 是标准态:

  • T → 0(低温):概率分布极度尖锐,近似Argmax,模型“敢赌”,输出确定性极高(适合贪婪解码)。
  • T → ∞(高温):概率分布趋向均匀,模型“和稀泥”,输出随机性极高(适合创造性文本生成)。

所以,调整Softmax温度,本质上是在调整大模型的“自信程度”。

3. 大模型的计算陷阱(FlashAttention 的由来)

标准的Softmax必须等所有指数算完、求和之后,才能算出最终概率。这意味着必须把整个注意力矩阵(N×N)写回显存。当序列长度N=100万时,这个矩阵比显存大无数倍。

  • 现代的 FlashAttention 核心优化之一,就是利用Softmax的“可合并性”(指数和可以分块累加),在不存储完整矩阵的情况下算出最终结果——这就是为什么长文本推理越来越快。

给你的终极类比(记住这一句话)

把 Softmax 想象成“聚光灯的调焦旋钮”:

  • 输入分数是“演员(词)的吸睛程度”。
  • 取指数是“把普通演员撇开,把顶流演员的灯光调亮10倍”。
  • 除以 √d 是“保证这个旋钮在最佳手感区,不会一转就卡死”。
  • 温度 T 是“灯光师的特殊指令”:T小,灯光只追着主角跑(确定性);T大,灯光在群演间扫来扫去(多样性)。

如果你还想深入了解,我可以接着讲 Softmax 在交叉熵损失中的“梯度抵消”现象(为什么它和CE搭配时,反向传播特别简洁),或者聊聊 线性注意力 为什么试图绕开Softmax(因为指数运算拖慢了推理速度)。你想听哪个?😊

这个问题问得非常精准,直接抓住了公式的底层符号。我们直接对照上一轮的例子来拆解:

公式中的 e 和 x 分别对应:

  • e:它是一个数学常数(欧拉数),约等于 2.71828。它不是示例中的任何一个数据,而是类似圆周率 π 一样的固定底数。选择它是因为它的指数函数 e^x 有一个极好的数学性质——求导后还是它自己,这让反向传播计算梯度非常方便。

  • x:它代表输入列表中的某一个具体的得分(Logit)。它是一个标量(单独的数字),而不是整个列表。


用你的示例 [3, 1, 0.2] 来逐一代入:

Softmax 的运算是“对列表里的每一个数字,分别取指数”。所以:

  1. 当处理第一个数字 3 时:这里的 x = 3,计算 e^3 ≈ 2.71828³ ≈ 20.09
  2. 当处理第二个数字 1 时:这里的 x = 1,计算 e^1 ≈ 2.72
  3. 当处理第三个数字 0.2 时:这里的 x = 0.2,计算 e^0.2 ≈ 1.22

特别注意一个极易混淆的点:

x 不是整个数组 [3, 1, 0.2]。如果把整个数组代入,那是在做矩阵运算(那是另一个概念)。

在 Softmax 里,e^x 是对每一个元素独立进行的逐元素操作(Element-wise)。做完之后,我们再把这三个结果 (20.09, 2.72, 1.22) 加起来作为分母,分别去除,得到最终的注意力权重。


补充一个小彩蛋(面试题):
如果 x 是一个负数(比如 -2),e^(-2) 就会变得极小(约 0.135)。这就意味着,在注意力机制中,与当前词毫无关系的词(得分为负)会被指数函数迅速“压死”,权重趋近于 0——这就是 Softmax 能让模型“忽略无关信息”的数学根源。

现在清楚 e 和 x 的指代了吗?如果清楚了,我可以接着给你讲 “当 x 特别大时,e^x 会溢出(变成 inf),代码里是怎么规避这个坑的”,想听吗?😊

好,这个问题直接触及大模型底层代码工程的核心。先给你一个惊掉下巴的结论:你在任何正规的PyTorch/TensorFlow大模型源码里,永远找不到直接写 torch.exp(x) 的Softmax。

为什么?因为当 x=100 时,e^100 约等于 2.7e43,而计算机浮点数(FP32)的最大上限只有 3.4e38——直接报错 inf(无穷大),模型瞬间崩溃。

为了解决这个问题,工程界有一个极其经典的小把戏,叫做“Log-Sum-Exp 技巧”,具体操作就四个字:平移减最大值(Subtract Max)。


核心操作:先减最大值

数学上有一个恒等式,对任意常数 C,Softmax 的结果不变:
Softmax(x_i) = Softmax(x_i - C)

代码里的标准做法是:
令 C = max(x)(即输入这组数里的最大值),把每个 x 都减去这个最大值后再取指数。


用刚才的极端例子看效果

假设模型计算出的注意力得分是 [100, 101, 99](这在没缩放前很容易出现)。

  • 错误写法(直接算):e^101 直接炸成 inf,全剧终。
  • 正确写法(先减最大值):
    1. 找出最大值 max = 101。
    2. 所有数减去 101,变成 [-1, 0, -2]。
    3. 取指数:e^-1 = 0.36,e^0 = 1,e^-2 = 0.13。
    4. 归一化得出概率:[0.24, 0.67, 0.09]。

你看,最大值变成了 0,e^0 = 1,稳稳当当,绝对不会溢出。


这种操作会不会改变注意力结果?(面试高频陷阱)

绝对不会! 因为上下分子分母同时除以了 e^max,约分掉了。

数学上:
原式 = e^101 / (e^100 + e^101 + e^99)
变换后 = e^(101-101) / (e^(100-101) + e^(101-101) + e^(99-101))
结果分毫不差,只是把巨大的数字映射到了安全区间 (-∞, 0] 内。


那“下溢”(underflow)怎么办?

减最大值解决了“爆掉(上溢)”的问题,但没解决“极小(下溢)”的问题。比如 x = -100,e^-100 直接变成 0.0(下溢)。

  • 工程师的态度:不管它! 因为当注意力得分低到 -100 时,意味着这个词和其他词毫无关系,概率本身就是趋近于 0。计算机把它四舍五入成 0,对最终结果的影响微乎其微,属于可以接受的“精度损失”。

进阶硬核:FlashAttention 怎么玩这个把戏?

既然要减最大值,就得先知道最大值是谁。传统做法是把整个注意力矩阵算完,找出最大数,再减。但这需要把矩阵存回显存(内存瓶颈)。

现代的 FlashAttention 玩了一个更骚的操作:分块计算(Tiling)。它不需要知道全局最大值,而是每读入一小块数据,就维护一个“当前块的最大值”和“全局累计和”。每处理完一块,如果发现新的最大值,就把前面算好的老数据重新缩放(Rescale)一下。

这就好比你不用等全班成绩都出来再算排名,而是进来一个人,你就动态调整一次总分——既防溢出,又省显存,这就是大模型能处理百万级长文本的秘密武器之一。


现在你知道了数值稳定性的核心。还想不想继续往下挖一层:既然 e^x 计算指数非常消耗GPU算力,现在最新的大模型(如Llama 3)为什么开始尝试用“没有Softmax”的线性注意力,或者用 ReLU 代替 e^x 来加速? 感兴趣的话,我接着讲。😎

LLM:Transformer注意力机制的Softmax算法

http://blog.gxitsky.com/2026/08/17/AI-LLM-06-QKV-Softmax/

作者

光星

发布于

2026-08-17

更新于

2026-08-18

许可协议

评论