简单来说,这个缩放的核心目的是为了维持数值稳定性,保持梯度稳定、防止数值爆炸或消失,从而提升训练稳定性。
这也是很多同学看《Attention is All You Need》论文时都会产生的一个疑惑。因为B站或视频号中都是重点讲解如何通过Q、K、V向量计算注意力权重,但对于Embedding层都是一带而过,没有展开。

实际上Embedding层乘以sqrt(d_model)进行缩放,与计算点积注意力时除以sqrt(d_model)是在实现同一个目标:稳定训练。
具体来说,在Transformer的Embedding层输出后乘以math.sqrt(d_model),这会让输出的Embedding向量中元素的方差放大为1,就像是给词向量"调音量旋钮",让它们在神经网络中保持清晰响亮的信号,既不淹没其他声音(位置编码),也不被噪声掩盖。本质上是控制输入特征的初始尺度,为神经网络构建一个数值稳定的"起跑线"。
在Transformer中,Embedding层的权重被乘以math.sqrt(d_model),主要是为了在共享Embedding和输出层权重的情况下,维持前向和反向传播过程中的数值稳定性。该操作通过调整嵌入向量的尺度,使其范数与模型维度匹配,从而避免因高维空间下嵌入向量范数过大而导致的梯度爆炸或消失问题。这并非削弱语义表达,而是增强训练动态的一致性。需要注意的是,这一缩放应与权重初始化策略配合使用:若初始化已包含适当的尺度控制(如 Xavier),则显式缩放可省略。这也是不同框架实现中是否包含该操作的原因之一。
是不是看懵了?
不要紧,刚开始都会懵的。这个时候,想想这个操作的目标:稳定训练,加速收敛。
先记住这句话:乘以math.sqrt(d_model)就像给词向量"调音量",让AI听得清楚又不刺耳。
想象一下你要教AI认字:
普通做法:给每个字分配一个小盒子(向量),AI自己学每个盒子里放什么;
Transformer的做法:给每个字分配一个盒子,但把盒子先放大一点,再交给AI学习。
# PyTorch中的嵌入层
import torch.nn as nn
# 假设我们有5000个词,每个词用512维向量表示 d_model=512
embedding = nn.Embedding(5000, 512)
# PyTorch默认初始化:从均匀分布或正态分布采样
# 比如:每个数字在-0.01到0.01之间,非常小问题来了:
# 放大信号! d_model=512
embedding_output = embedding(word_ids) * math.sqrt(512)
# 假设原来向量中数字是0.01,现在变成0.01×22.6=0.226
# 信号变强了,AI听得更清楚没有缩放的问题:
初始:词向量很小 [0.01, 0.02, -0.01, ...]
注意力计算:0.01 × 0.01 = 0.0001 (非常小)
Softmax:e^0.0001 ≈ 1.0001 (所有词的概率几乎一样)
→ AI无法区分哪个词更重要
→ 训练缓慢,效果差有缩放的改善:
缩放后:词向量合理 [0.226, 0.452, -0.226, ...]
注意力计算:0.226 × 0.226 = 0.051(合理大小)
Softmax:e^0.051 ≈ 1.052 (有明显的概率差异)
→ AI能清楚区分重要词和不重要词
→ 训练更快,效果更好平衡的艺术:
数学原理简化版:
假设每个维度平均值为0,标准差为1
512个维度加起来,总"能量" = 512
每个维度的平均"能量" = math.sqrt(512) ≈ 22.6
→ 用22.6缩放,让每个维度保持在合理范围一句话理解:
在输入端主动放大嵌入【乘以math.sqrt(d_model)】 可以提升整体信号幅度,使其在经过多层后仍保持良好动态范围。
打个比方,在Embedding层将嵌入矩阵的权重乘以sqrt(d_model)就像给词向量"调音量",让AI听得清楚又不刺耳。
《Attention is All You Need》3.4节译文:
与其他序列转换模型类似,我们使用学习到的嵌入向量将输入和输出词汇转换为维度为d_model的向量。我们还使用常规的学习线性变换和softmax函数,将解码器输出转换为预测下一个词汇的概率。在我们的模型中,两个嵌入层和softmax前的线性变换共享相同的权重矩阵。在嵌入层中,我们将这些权重乘以math.sqrt(d_model)。
觉得有点似懂非懂的同学可以再读一读译文,再理解理解找找感觉。