核心要点
Transformer 用缩放点积注意力(scaled dot-product),不是加性注意力(additive)
点乘可直接复用高度优化的矩阵乘法(GEMM),更快、更省内存
加性注意力多一层前馈网络来打分,计算更慢、更占资源
维度不太高时两者效果相近,但点乘在效率上明显占优,故被选用
除以 √dk:dk 越大点积方差越大,过大的分数会把 softmax 推入饱和区、梯度趋近 0,缩放后方差回到 1 左右,训练稳定
标准回答
用的是缩放点积注意力
Transformer 采用的是 scaled dot-product attention(缩放点积注意力)。打分函数本质上是 Q 与 K 做点积,再除以 √dk,最后过 softmax 得到权重。这与早期 Seq2Seq 里常用的 加性注意力(additive / Bahdanau attention) 形成对比——后者是把 Q 和 K 拼接(或相加)后送进一个带 tanh 的小前馈网络来打分。
为什么选点乘而不是加法
核心原因是效率。点积注意力对所有 query 和 key 的打分,可以一次性写成两个大矩阵相乘 Q·Kᵀ,直接调用 GPU 上高度优化的矩阵乘法(GEMM)内核,并行度高、访存友好、几乎不引入额外参数。加性注意力则要为每一对 Q/K 过一遍前馈层,多出一组权重、多一次非线性运算,在大规模并行下又慢又占显存。
从效果看,论文里指出:当维度 dk 不大时,两者精度相近;dk 较大时,未缩放的点积反而会变差。但只要做了缩放,点积在「同等甚至更好的效果下拿到显著更快的速度」,这正是 Transformer 选它的理由。
为什么要除以 √dk
这是为了控制点积的方差。假设 Q、K 各维度是均值 0、方差 1 的独立随机变量,那么它们的点积是 dk 个乘积项之和,期望为 0,方差正比于 dk。也就是说 dk 越大,点积的数值波动范围越大,容易出现绝对值很大的分数。
softmax 对输入量级非常敏感:一旦某些 logit 远大于其余,softmax 输出就会逼近 one-hot(饱和),此时函数在这些点上的梯度几乎为 0,反向传播时梯度消失,训练难以推进。
除以 √dk 恰好把点积的方差从 dk 拉回到约 1(标准差从 √dk 拉回 1),让分数维持在一个温和的量级,softmax 工作在梯度健康的区间。这就是缩放因子选 √dk(而不是 dk 或别的值)的来历——它精确抵消了维度带来的方差膨胀。
常见误区
⚠️ 常见踩坑
别把「除以 √dk」说成是为了归一化概率或防止数值溢出——归一化是 softmax 干的,溢出另有 max 减法技巧处理。缩放的真正目的是抑制高维点积的方差、避免 softmax 饱和导致梯度消失。另外也别误以为加性注意力一定更弱,它在低维或某些任务上效果不差,Transformer 选点乘主要是为了大规模并行下的速度与显存。
追问
追问 1:为什么是除以 √dk 而不是除以 dk?
因为要校正的是标准差而非方差。点积方差正比于 dk,对应标准差正比于 √dk。我们希望把分数的尺度(标准差)拉回到 1 左右,所以除以标准差量级 √dk 即可让方差回到约 1。若除以 dk,会把方差压成 1/dk,分数过小、softmax 又趋于均匀,区分度反而下降。
追问 2:softmax 饱和导致梯度消失,能从公式上说清楚吗?
softmax 对输入的 Jacobian 含 s_i(δ_ij − s_j) 这类项。当某个 s_i 接近 1、其余接近 0 时,s_i(1−s_i) 和 s_i·s_j 都趋近 0,整个梯度矩阵接近零矩阵。于是上游传来的梯度被几乎清零,注意力打分对应的 Q、K 参数得不到有效更新,训练停滞。缩放让 logit 不至于极端,从而避开这个区域。
追问 3:如果不缩放,但改用更小初始化或 LayerNorm,能替代 √dk 吗?
部分能缓解但不等价。更小的初始化或对 Q、K 做归一化可以压低点积量级,确实能减轻饱和,一些变体(如 QK-Norm)正是这思路。但 √dk 是与维度精确匹配、零额外开销的解析解,无需调参也不引入新模块;而依赖初始化在训练过程中参数尺度漂移后又会失效。所以 √dk 仍是默认且最稳妥的做法,归一化更多是补充而非替代。
🔗 相似问题
同一考点的不同问法,面试官可能换着问,一起刷更稳
没找到想看的面试题?把你想看的告诉我们 →
延伸学习
按主题分类的相关资源,便于系统复习