self-attention至最终概率输出
在前文《深入了解self-attention》中我们了解了自注意力模式的工作原理,它主要关注每个token和上下文之间的关系,self-attention后输出每个token和上下文加权后的向量,那么怎么用这个加权后的向量得到下一个词的概率分布呢?本文主要关注这个过程。
先用一张图画出整个transformer架构的过程:

接上前文,“它”经过一层 的self-attention 后得到一个混淆了上下文相关表示的向量[0.031,0.111],对比原始”它“的embedding向量[0.19, -0.37, 0.28, 0.06]少了两个维度,这里是因为,还需要靠Multi-head补齐剩下的维度,比如两个head可以输出两个向量,两个向量拼接成一个和原始向量相同维度的向量。
| head1 | head2 | mix上下文的向量 |
| [0.031,0.111] | [-0.08, 1.231] | [0.031,0.111,-0.08, 1.231 ] |
得到mix上下文的向量后,进入残差连接+LayerNorm。
残差连接+LayerNorm
目的:把向量的数值稳定在一个合理范围内,防止深层网络训练时梯度爆炸或消失。它对同一个 token 内部的所有维度做归一化。
残差连接
将mix上下文的向量加回原始向量,[0.19, -0.37, 0.28, 0.06]+[0.031,0.111,-0.08, 1.231 ],这就像说”我在原来’它’这个词的基础上,叠加一点从上下文学到的新信息”,而不是完全替换掉原来的向量。
LayerNorm具体公式:
z:向量,例子如上文的[0.031,0.111,-0.08, 1.231 ](这里示例省略了残差连接的计算),实际再过一层矩阵做信息融合。
μ:z 向量所有维度的均值。
σ²:z 向量所有维度的方差(各个维度的离散程度)。
ε:一个很小的常数(比如 1e-5),防止除以 0报错。
γ、β:两个可训练的参数向量,分别叫”缩放”和”平移”,让模型有能力把归一化后的分布重新调整成最适合的样子。
手算体验一下(可展开)
z=[0.031,0.111,-0.08, 1.231 ]
μ=(0.031+0.111+(-0.08)+1.231) / 4 = 0.32325
σ²=[(0.031-0.32325)2+(0.111-0.32325)2+(-0.08-0.32325)2+(1.231-0.32325)2] / 4 = [0.0854+0.045+0.1626+0.824] / 4 = 0.27925
假设训练好的 γ=[1,1,1,1],β=[0,0,0,0]
LayerNorm(z)=[(0.031-0.32325)+(0.111-0.32325)+(-0.08-0.32325)+(1.231-0.32325)]/0.5284411=[-0.55, -0.402, -0.763, 1.718]
前馈神经网络 Feed-Forward Network
目的:对每个 token 单独做非线性加工——它不看其他 token,只对当前这一个向量做变换,相当于给模型增加”思考深度”。
W₁:形状 [d_model, d_ff],把向量从d_model维放大到d_ff维(通常 d_ff = 4×d_model)。
Activation:激活函数,早期用 ReLU,现代模型(GPT、Claude 这类)更常用 GELU 或 SwiGLU。
W₂:形状[d_ff, d_model],再把向量压缩回原始维度。
b₁、b₂:偏置项。(给了模型一个”基准线”、一个”默认偏好”,不需要完全依赖输入的具体数值,才能产生某种输出。相当于给每个”特征探测器”设置了一个独立的激活阈值,让不同神经元可以对不同强度的信号做出反应,而不是所有神经元共享同一个”零点”标准)
注:真实模型里,一层 FFN 里的 W₁+W₂,就有约 1.34 亿个参数。W₁ 的每一列(或者说每个”中间神经元”),往往对应某种特定的、可被人类识别的”特征检测器”。而 W₂ 则负责把这些被激活的特征检测器的意见,重新组合、投票,汇总成一个更新后的语义表示。
Activation激活函数,以以 ReLU 为例,负数变 0。如放大为d_ff维的矩阵为[0.31, -0.85, 0.42, -1.20, 0.55, 0.08, -0.63, 0.97],过激活函数后得到:[0.31, 0, 0.42, 0, 0.55, 0.08, 0, 0.97],负数置为了0。
整个前馈神经网络,可以做这样一个类比:像把一张小图片的信息,同时喂给 8 个不同的、各自关注不同特征组合的”滤镜”(比如一个专门检测”是不是偏暖色调”、一个专门检测”是不是有强对比边缘”……),每个滤镜产出一个响应值;响应为负的滤镜,说明”这个特征在这张图里根本没检测到”,直接归零、不参与后续;剩下响应为正的滤镜结果,再重新按权重组合、投票汇总,压缩回原来的通道数,得到一张”被这8个滤镜重新解读过”的新图。
线性投影到词表大小
直接看个示例:
假设经过残差连接+layerNorm+FFN后得到最后一个token的向量为:[0.15, -0.32, 0.48, 0.21]。我们需要预测输出它的下一个词,我们需要将它映射到词表中。
假设词表里有5 个候选词,真实模型词表通常几万到十几万。
词表 = [“。”, “,”, “但是”, “所以”, “呢”]
词表矩阵 = [
[0.9, -0.2, 0.1, 0.3, -0.5],
[0.4, 0.7, -0.3, 0.1, 0.2],
[-0.1, 0.5, 0.8, -0.4, 0.3],
[0.2, -0.6, 0.2, 0.9, 0.1]
]
每一列代表一个词
1.算出的 logits(每个词一个原始分数):
| 词 | 计算logits | 得分 |
| 。 | 0.15×0.9 + (-0.32)×0.4 + 0.48×(-0.1) + 0.21×0.2 | -0.006 |
| , | 0.15×(-0.2)+ (-0.32)×0.7 + 0.48×0.5 + 0.21×(-0.6) | -0.156 |
| 但是 | 略 | 0.549 |
| 所以 | 略 | 0.086 |
| 呢 | 略 | 0.024 |
2.Softmax将得到分数,归一为概率分布
elogits ≈ [0.994, 0.856, 1.732, 1.090, 1.024]
sum≈5.696
P(“。”) ≈ 0.994 / 5.696 ≈ 17.4%
P(“,”) ≈ 0.856 / 5.696 ≈ 15.0%
P(“但是”) ≈ 1.732 / 5.696 ≈ 30.4%
P(“所以”) ≈ 1.090 / 5.696 ≈ 19.1%
P(“呢”) ≈ 1.024 / 5.696 ≈ 18.0%
至此示例中,按最大概率取,模型预测得到下一词为“但是”。
实际拿到概率分布后,不一定取概率最高的词,会有几种不同的采样策略。
| 策略 | 做法 | 特点 |
|---|---|---|
| 贪心解码(Greedy) | 直接选概率最高的词 | 确定性强,但容易生硬、重复 |
| Top-k 采样 | 只在概率最高的 k 个词里按概率随机抽 | 平衡随机性和质量 |
| Top-p (nucleus) 采样 | 只在累计概率达到 p(如90%)的最小词集合里抽 | 目前最常用,更自然 |
| 温度(Temperature)调节 | 在 softmax 前把 logits 除以一个温度值 T | T越低越保守(接近贪心),T越高越随机、越”有创意” |
一句话总结整个流程
输入词 → embedding → N层Transformer(attention+FFN反复处理)
→ 最终向量 → × W_U 得到logits → softmax得到概率 → 采样得到下一个词
这也是为什么大语言模型本质上是在做”预测下一个词的概率分布“这一件事——但因为这个过程会在生成完一个词后,把新词加回输入序列、再走一遍整个流程(自回归生成),所以最终能连续生成一整段连贯的文本。