- 作者
-
-
- 姓名
- Amit Shekhar
- 发布于
-
我们将点积注意力除以 √dₖ 进行缩放,因为随着维度 dₖ 的增大,点积也会变大。这么大的数值会把 softmax 推向极端值,而除以 √dₖ 可以把它们拉回健康的范围。
在这篇博客中,我们将通过一个循序渐进的数值示例,学习在 Transformer 架构中为什么要对点积注意力除以 √dₖ 进行缩放。
如果你已经读过我们关于 Attention 背后的数学 - Q、K 和 V 的博客,你应该已经了解注意力公式和计算步骤。在那篇博客中,我们将注意力分数除以
sqrt(d_k)
然后就继续往下讲了。现在,是时候理解
why我们为什么要这样做了。为什么偏偏是
sqrt(d_k)
?为什么不除以 2 或 10 或其他任何数字呢?
本文的目标是让你理解为什么要用 √dₖ 进行缩放,这意味着在写作过程中做了一些简化。如果你理解了缩放背后的原理,那我的使命就完成了。如果你完整读完这篇文章,我相信我的使命一定会完成。
我们将涵盖以下内容:
- 注意力公式(快速回顾)
- 不缩放会发生什么?
- 为什么点积会随 dₖ 增大?
- 理解点积的方差
- 逐步证明:点积的方差是 dₖ
- 大的点积对 softmax 的影响
- 为什么 √dₖ 是正确的缩放因子
- 用真实数字验证
- 总结
我是 Amit Shekhar,Outcome School 的创始人,我教导和指导过许多开发者,他们的努力为他们赢得了高薪的技术工作,帮助许多科技公司解决了他们的独特问题,并创建了许多被顶级公司使用的开源库。我热衷于通过开源、博客和视频分享知识。
我在 Outcome School 教授 AI 和机器学习。
让我们开始吧。
注意力公式(快速回顾)
这个缩放步骤位于更大的 Transformer 架构之中。缩放点积注意力的公式是:
Attention(Q, K, V) = softmax(Q x K^T / sqrt(d_k)) x V
其中:
- Q 是 Query 矩阵
- K 是 Key 矩阵
- V 是 Value 矩阵
- d_k 是 Key 向量的维度
- sqrt(d_k) 是 d_k 的平方根
我们今天关注的部分是
/ sqrt(d_k)
。这就是
scaling factor。我们在将点积分数传入
softmax.
现在,问题是:为什么需要这个缩放?答案在于理解不缩放会发生什么。
不缩放会发生什么?
假设我们跳过缩放步骤,直接按如下方式计算注意力:
Attention = softmax(Q x K^T) x V
在真实的 Transformer 模型中,
d_k
是 64、128 甚至更大。当
d_k
很大时,分数
Q x K^T
可能会变成非常大的数字(我们将在下一节解释原因)。而当我们把非常大的数值传入 softmax 时,就会出问题。
softmax 函数(用于将分数转换为概率)产生的输出会极其接近 0 和 1。 一个词几乎获得全部注意力(接近 1.0),而其他所有词几乎得不到任何注意力(接近 0.0)。模型不再把注意力分散到多个相关词上,而是对某一个词变得过于自信。
这是一个大问题,因为:
- 模型无法同时从多个词中学习。
- 梯度(训练过程中用于更新模型的信号)变得极小,几乎为零。这就是所谓的 梯度消失问题。
- 当梯度过小时,模型就无法有效学习。
于是,缩放因子
sqrt(d_k)
应运而生,来解决这个问题。
Softmax 还有一个值得了解的后果。它的输出总和总是等于 1,因此一个 token 必须把全部注意力分配出去,即使句子里没有任何内容值得关注。我们有一篇关于 Attention Sinks 的详细博客,解释了这些多余的注意力最终去了哪里。
但在理解解决方案之前,我们必须先弄清楚当
d_k
增大时,点积为什么会变大。
为什么点积会随 dₖ 增大?
两个向量的点积是通过将每一对元素相乘,然后把它们全部相加来计算的。
假设我们有两个向量
q
和
k
,每个的维度都是
d_k
:
dot_product = q_1*k_1 + q_2*k_2 + q_3*k_3 + ... + q_{d_k}*k_{d_k}这里,我们把
d_k
个项加在一起。
现在,让我们简单地思考一下。每一项
q_i * k_i
都是一个数字,可以是正数或负数。当我们把这些数字越加越多时,它们并不总能完美地相互抵消。有些相加,有些抵消,但总体上总和的绝对值往往会增大。维度越多,相加的项就越多,点积就可能变得越大。
例如,如果
d_k = 4
,我们只相加 4 个项,所以点积保持较小。但如果
d_k = 512
,我们就要相加 512 个项。尽管一些正负值会相互抵消,但项数之多使得总和的绝对值大得多。
点积随
d_k
增长。这就是核心问题。维度越大,点积越大,softmax 的表现就越差。
现在,让我们用方差的概念来更精确地理解这一点。
理解点积的方差
别担心,我们会保持简单。
方差衡量一组数值相对于平均值的离散程度。方差大意味着数值远离平均值;方差小意味着数值接近平均值。
假设我们要测量一个班级学生的身高。如果所有学生的身高都在 5.0 到 5.5 英尺之间,那么方差就低。如果学生的身高范围从 3.0 到 7.0 英尺,那么方差就高。同样,当我们谈论点积的方差时,我们是在问:点积的值能有多分散?
现在,假设 Query 向量和 Key 向量中的每个元素都是一个随机数,且满足:
- 均值(平均值)= 0
- 方差 = 1
这是机器学习中的标准假设。输入值通常会被归一化,使其均值为零、方差为一。
那么,单个乘积的方差是多少
q_i * k_i
?
当我们把两个独立的随机数相乘,每个随机数的均值都是 0、方差都是 1 时,结果具有:
- 均值 = 0
- 方差 = 1 x 1 = 1(我们将在下一节解释原因)
所以,每个单独的乘积
q_i * k_i
的方差都是 1。
现在,点积是
d_k
个这样的乘积之和:
dot_product = q_1*k_1 + q_2*k_2 + ... + q_{d_k}*k_{d_k}当我们把
d_k
个独立项相加,每项的方差都是 1 时,总方差为:
Variance(dot_product) = d_k x 1 = d_k
这就是关键洞察。点积的方差等于 dₖ。
d_k
越大,点积的值就越分散。而值越分散,就会给 softmax 带来问题。
正在规划进入 AI 领域?
无论你今天在哪个技术领域工作,只要付出努力,你都可以转型到以下这些角色:
- AI 工程师
- 前沿部署工程师
- AI Agent 工程师
- Harness 工程师
- 语音 AI 工程师
- AI 架构师
- LLM 工程师
- LLM 推理工程师
- 生成式 AI 工程师
- MLOps 工程师
- 机器学习工程师
- 深度学习工程师
Outcome School 的 AI 与机器学习课程 助你达成目标。
逐步证明:点积的方差是 dₖ
现在,为了便于理解,让我们一步一步地证明为什么方差等于
d_k
。别担心,我们会保持简单。
我们已经知道,点积的均值为零(因为每个
q_i
和
k_i
的平均值都是零)。
现在,一般来说,方差的计算方式如下:
Variance = Average of (value - mean)^2
但由于我们的均值为零,这就变成了:
Variance = Average of (value - 0)^2
= Average of value^2所以,当均值为零时,方差就简化为平方值的平均值。这意味着我们需要求点积平方的平均值。
现在,让我们看看对点积取平方会发生什么。我们举一个
d_k = 3
:
dot_product = q_1*k_1 + q_2*k_2 + q_3*k_3
对它取平方时,我们把和与自身相乘。这就像展开
(a + b + c)^2
:
(a + b + c)^2 = a*a + a*b + a*c
+ b*a + b*b + b*c
+ c*a + c*b + c*c其中:
a = q_1*k_1
,
b = q_2*k_2
,
c = q_3*k_3
。所以我们得到 9 项(3 x 3)。现在,关键问题是:这 9 项中每一项的平均值是多少?
这 9 项分为两类:
第一类:一项与自身相乘的项(如 a*a、b*b、c*c)
这些是同一对元素与自身相乘的项。例如,
(q_1*k_1) * (q_1*k_1) = q_1^2 * k_1^2
。共有 3 个这样的项。
每一项的平均值是多少?让我们用上面学到的方差公式。我们知道:
Variance = Average of value^2 (when mean is zero)
由于
q_1
的均值为 0,方差为 1:
1 = Average of q_1^2 Average of q_1^2 = 1
同理,由于
k_1
的均值为 0,方差为 1:
Average of k_1^2 = 1
由于
q_1
和
k_1
相互独立,它们乘积的平均值等于各自平均值的乘积:
Average of (q_1^2 * k_1^2) = Average of q_1^2 * Average of k_1^2 = 1 * 1 = 1
这些项中每一项的平均值都是 1。
第 2 组:不同配对相乘的项(如 a*b、a*c、b*c)
这些是两个不同配对混合在一起的项。例如,
(q_1*k_1) * (q_2*k_2) = q_1 * k_1 * q_2 * k_2
。共有 6 个这样的项。
每一项的平均值是多少?由于
q_1
,
k_1
,
q_2
,
k_2
都相互独立,它们乘积的平均值等于各自平均值的乘积:
Average of (q_1 * k_1 * q_2 * k_2) = Average of q_1 * Average of k_1 * Average of q_2 * Average of k_2
= 0 * 0 * 0 * 0
= 0这里,由于每一项的平均值(均值)都为零,整个乘积就变为零。
这些项中每一项的平均值都是 0。
综合起来:
在 9 个项中:
- 3 个项(第 1 组)每项平均贡献 1
- 6 个项(第 2 组)每项平均贡献 0
Variance = 3 * 1 + 6 * 0 = 3
和
d_k = 3
。所以方差等于
d_k
.
现在,同样的逻辑适用于任何
d_k
的取值。如果
d_k = 64
,我们得到
64 * 64 = 4096
个总项数。其中,64 个项(第 1 组)每项贡献 1,其余 4032 个项(第 2 组)每项贡献 0。所以方差是 64,正好等于
d_k
.
点积的方差总是恰好等于 dₖ。 这不是近似值,而是数学上精确的。
如果我们想从头深入了解 Q/K/V、自注意力机制以及 Transformer 架构背后的数学原理,我们有一个完整的课程——请查看 Outcome School 的 AI 与机器学习课程。
大的点积对 softmax 的影响
Softmax 函数将一组数字转换为概率。公式为:
softmax(x_i) = e^(x_i) / sum(e^(x_j) for all j)
其中:
e
是数学常数(约为 2.718)。
现在,需要理解的重要一点是:
e^x
会随着
extremely fast的增大而
x
增长。让我们用实际数字来看看它增长得有多快:
e^1 = 2.718 e^5 = 148.4 e^10 = 22,026 e^20 = 485,165,195 e^50 = 5,184,705,528,587,072,045
这里,我们可以看到
e^10
和
e^50
之间的差异是天文数字级别的。
现在,假设我们有三个注意力分数:
[50, 10, 5]
(只是为了理解 softmax 在大数字下的表现)。当我们应用 softmax 时:
e^50 = 5,184,705,528,587,072,045 e^10 = 22,026 e^5 = 148 softmax = [5,184,705,528,587,072,045 / total, 22,026 / total, 148 / total]
第一个值完全占主导地位。softmax 的输出将近似为
[1.0, 0.0, 0.0]
.
现在,将其与较小的分数进行比较:
[5, 1, 0.5]
。当我们应用 softmax 时:
e^5 = 148.4
e^1 = 2.718
e^0.5 = 1.649
Sum = 152.780
softmax = [148.4/152.780, 2.718/152.780, 1.649/152.780]
= [0.971, 0.018, 0.011]这里,我们可以看到即使分数较小,第一个值仍然获得最多的注意力。但其他值并非完全为零。模型仍然可以从所有位置学习。
这就是问题所在。当
d_k
很大且我们不进行缩放时,点积得分会变得非常大,以至于 softmax 的输出几乎变成 one-hot。One-hot 意味着一个值为 1.0,其余都是 0.0。模型表现得好像只有一个词重要,而忽略了其他所有内容。梯度消失,学习停止。
给你的一点提示
无论你在哪个技术领域工作,都要熟悉这些主题:
- LLM
- RAG
- MCP
- Agent
- 微调
- 量化
我们把它们全部整合在一个视频中:
AI 工程详解:LLM、RAG、MCP、Agent、微调与量化
不必停止阅读——先收藏起来,等有空时再看。未来的你会感谢现在的你。
现在,让我们回到正题。
为什么 √dₖ 是正确的缩放因子
现在我们理解了问题所在,解决方案也就清晰了。我们需要让点积值保持足够小,以便 softmax 能产生分布良好的注意力权重。
无论
d_k
有多大,我们都需要把点积的方差重新拉回到 1。
我们知道:
Variance(dot_product) = d_k
如果我们把点积除以某个常数
c
,方差就变为:
Variance(dot_product / c) = d_k / c^2
注意: 当我们把一个随机变量除以常数
c
时,方差会被除以
c^2
(而不是
c
)。这是统计学中的标准规则。让我们来理解为什么。
方差衡量的是数值相对于均值的离散程度。它是用与均值的平方差来计算的。所以,当我们把所有值除以
c
时,每个与均值的差也会被除以
c
。但由于方差对这些差进行平方运算,除以
c
就变成了除以
c^2
.
让我们用一个简单的例子来看。假设我们有三个值:
[2, 4, 6]
.
Mean = (2 + 4 + 6) / 3 = 4 Differences from mean: [2-4, 4-4, 6-4] = [-2, 0, 2] Squared differences: [4, 0, 4] Variance = (4 + 0 + 4) / 3 = 2.67
现在,把所有值除以
c = 2
。新值为
[1, 2, 3]
.
New Mean = (1 + 2 + 3) / 3 = 2 Differences from mean: [1-2, 2-2, 3-2] = [-1, 0, 1] Squared differences: [1, 0, 1] New Variance = (1 + 0 + 1) / 3 = 0.67
这里可以看到,原来的方差是
2.67
,新的方差是
0.67
和
2.67 / 4 = 0.67
。我们除以了
c = 2
,但方差被除以了
c^2 = 4
.
这是因为方差使用的是平方差。当每个值缩小
c
倍时,平方差会缩小
c^2
.
现在,回到我们的点积。我们有:
Variance(dot_product / c) = d_k / c^2
我们希望这个方差等于 1,以便点积值保持在可管理的范围内。所以,我们设:
d_k / c^2 = 1 c^2 = d_k c = sqrt(d_k)
这就是为什么我们要除以
sqrt(d_k)
。它正是能把方差拉回到 1 的那个值。
缩放之后:
Variance(dot_product / sqrt(d_k)) = d_k / d_k = 1
缩放后的点积值方差为 1,这意味着无论
d_k
有多大,它们都保持在可管理的范围内。softmax 函数接收到合理的输入,并产生分布良好的注意力权重。
这不是一个随意的选择。它在数学上正是正确的缩放因子。原始 《Attention Is All You Need》 论文(提出 Transformer 架构的论文)的作者正是出于这个原因选择了这个值。
要深入掌握《Attention Is All You Need》论文、缩放点积注意力以及 Transformer 内部机制,请查看 Outcome School 的 AI 与机器学习课程。
用真实数字验证
现在,让我们用两个不同的维度来看看缩放的效果。
示例 1:小维度(dₖ = 4)
假设我们有:
q = [1, 0, 1, 0] k = [0, 1, 1, 1]
dot_product = 1*0 + 0*1 + 1*1 + 0*1 = 1
sqrt(d_k) = sqrt(4) = 2
scaled_score = 1 / 2 = 0.5
原始分数是
1
,缩放后的分数是
0.5
。两个值都很小,所以无论哪种情况下 softmax 都表现良好。当
d_k
较小时,缩放并不重要。
示例 2:大维度(dₖ = 64)
假设我们有三个词,其点积分数为:
[14, 10, 12]
.
不缩放时:
e^14 = 1,202,604 e^10 = 22,026 e^12 = 162,755 Sum = 1,387,386 softmax = [0.867, 0.016, 0.117]
这里,第一个词获得了 86.7% 的注意力。第二个词只获得 1.6%。尽管原始分数(14、10、12)相差并不大,但分布却相当极端。
缩放后(除以 sqrt(64) = 8):
缩放后的分数:
[14/8, 10/8, 12/8]
=
[1.75, 1.25, 1.5]
e^1.75 = 5.755
e^1.25 = 3.490
e^1.5 = 4.482
Sum = 13.727
softmax = [5.755/13.727, 3.490/13.727, 4.482/13.727]
= [0.419, 0.254, 0.326]这里我们可以看到差别。缩放之后,注意力分布得更加均匀:41.9%、25.4% 和 32.6%。模型现在可以从所有三个词中学习,而不是几乎完全聚焦于一个词。
这就是除以
sqrt(d_k)
解决问题的方式。
保持更新: 订阅我们的 新闻通讯,将最新的 AI 与机器学习博客直接发送到您的邮箱。
总结
让我们总结一下所学到的内容:
问题所在: 查询(Query)和键(Key)向量的点积会随着维度
d_k
的增加而增大。点积的方差等于
d_k
。较大的点积值会把 softmax 推向极端区域,使其输出接近 0 或 1 的值。这会导致梯度消失问题,模型停止学习。
解决方案: 在应用 softmax 之前,我们将点积除以
sqrt(d_k)
。这样可以把方差拉回 1,无论维度大小如何,都能使分数保持在可管理的范围内。
为什么是 sqrt(d_k)? 因为当一个方差为
d_k
的值除以
sqrt(d_k)
后,新的方差变为
d_k / d_k = 1
。这在数学上正是完全正确的值。
带缩放的完整注意力公式:
Attention(Q, K, V) = softmax(Q x K^T / sqrt(d_k)) x V
这一行代码,
/ sqrt(d_k)
,看起来很简单。但没有它,Transformer 架构就难以有效学习,尤其是在维度较大时。这是一个虽小却非常重要的细节,正是它让整个注意力机制得以正常运作。
现在,我们应该已经理解了为什么要将点积注意力除以 √dₖ。
常见问题
当 d_k 较小时,除以 sqrt(d_k) 的缩放重要吗?
不太重要。当
d_k
较小时,点积保持较小,因此无论是否缩放,softmax 都表现良好。例如,当
d_k = 4
时,分数 1 缩放后变为 0.5,两个值都很小。随着
d_k
变大,缩放才变得重要起来。
为什么我们除以 sqrt(d_k) 而不是其他数字?
当我们用一个常数去除一个值时
c
,它的方差会除以
c^2
。点积的方差为
d_k
,因此我们需要
d_k / c^2 = 1
,即得到
c = sqrt(d_k)
。它正是能把方差拉回到 1 的那个值。
点积的方差只是近似等于 d_k 吗?
不是。点积的方差精确等于
d_k
,而不是近似值。这在 Query 和 Key 向量的每个元素均值为 0、方差为 1 且各元素相互独立的标准假设下成立。
是谁在注意力机制中引入了 sqrt(d_k) 缩放因子?
该缩放因子来自最初提出 Transformer 架构的论文《Attention Is All You Need》。作者选择
sqrt(d_k)
是因为从数学上讲,这是使分数方差保持为 1 的正确值。
今天就到这里。
谢谢
Amit Shekhar Outcome School 创始人
你可以通过以下方式与我联系:
关注 Outcome School: