大家好,这里是好评笔记,公主号:Goodnote,专栏文章私信限时Free。本文详细介绍面试过程中可能遇到的Transformer知识点,由于字数限制,分为上下篇发布。
热门专栏
机器学习
深度学习
初识Transformer
Transformer 是一种革命性的神经网络架构,最早由 Vaswani 等人在 2017 年提出,它彻底改变了自然语言处理(NLP)的领域。与传统的递归神经网络(RNN)和长短期记忆网络(LSTM)不同,Transformer不依赖于序列的时间步 ,而是通过注意力机制 并行处理整个输入序列。它在诸如机器翻译、文本生成和语言模型等任务中表现出色。下面详细介绍 Transformer 的原理、结构和应用。
1. 编码器-解码器架构
Transformer 的架构由两个部分组成:
- 编码器(Encoder):将输入序列 -> (映射) -> 连续的表示空间。
- 解码器(Decoder):根据编码器的输出 ->生成目标序列。
编码器和解码器均由多个相同的层堆叠而成。每层都有两个主要组件:
- 多头自注意力机制(Multi-Head Self-Attention Mechanism)
- 前馈神经网络(Feed-Forward Neural Network)。
解码器的额外结构
解码器除了与编码器相同的结构外,还多了一个编码器-解码器注意力机制,它在生成每个目标时依赖于编码器的输出。
2. 自注意力机制(Self-Attention Mechanism)
Transformer 的核心是自注意力机制,它能够捕捉输入序列中的全局依赖关系,并且不需要像 RNN 那样逐步计算。
自注意力的计算过程:
给定输入序列
X
=
(
x
1
,
x
2
,
…
,
x
n
)
X=(x_1,x_2,\ldots,x_n)
X=(x1,x2,…,xn),每个元素
x
i
x_i
xi 会生成三个向量:查询(Query)、键(Key)和值(Value)。这些向量通过三个不同的权重矩阵
W
Q
W_Q
WQ、
W
K
W_K
WK、
W
V
W_V
WV 得到:
Q
=
X
W
Q
,
K
=
X
W
K
,
V
=
X
W
V
Q = XW_Q,\quad K = XW_K,\quad V = XW_V
Q=XWQ,K=XWK,V=XWV
其中,
Q
Q
Q、
K
K
K 和
V
V
V 分别代表查询、键和值。
接下来,计算查询和键之间的相似性得出注意力分数。具体公式为:
Attention
(
Q
,
K
,
V
)
=
softmax
(
Q
K
T
d
k
)
V
\text{Attention}(Q,K,V)=\text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V
Attention(Q,K,V)=softmax(dkQKT)V
这里
d
k
d_k
dk 是键向量的维度,
d
k
\sqrt{d_k}
dk 是缩放因子,用于避免在点积中值过大而导致梯度爆炸。
多头注意力机制(Multi - Head Attention)
Transformer进一步引入了多头注意力机制,它不是一次计算一个查询 - 键值对的注意力,而是使用多个不同的权重矩阵并行计算多个“头”的注意力。每个头可以关注输入序列中的不同部分,最后将这些不同头的结果拼接起来并通过线性变换得到最终的输出:
MultiHead
(
Q
,
K
,
V
)
=
Concat
(
head
1
,
head
2
,
…
,
head
h
)
W
O
\text{MultiHead}(Q,K,V)=\text{Concat}(\text{head}_1,\text{head}_2,\ldots,\text{head}_h)W_O
MultiHead(Q,K,V)=Concat(head1,head2,…,headh)WO
其中
W
O
W_O
WO 是线性变换的权重矩阵。多头注意力机制的主要优势在于它能从不同的子空间中同时捕捉输入序列的不同特征,从而提高模型的表现。
解码器中的注意力机制的2点特殊
- 编码器-解码器注意力机制:解码器中,不仅包含自注意力机制,还包括一个与编码器输出交互的注意力机制,它允许解码器在生成每个词时参考编码器的上下文信息。
- 未来遮蔽:确保在生成第 t 个词时,只能看到之前生成的词,而看不到未来的词。
3. 位置编码(Positional Encoding)
因为 Transformer 不依赖输入序列的顺序信息,它需要显式地将位置信息引入模型中。为此,Transformer 使用位置编码(Positional Encoding)来为每个输入向量添加位置信息。
位置编码通过正弦和余弦函数生成,并按照序列的索引位置注入到每个词向量中:
P
E
(
p
o
s
,
2
i
)
=
sin
(
p
o
s
1000
0
2
i
d
)
PE_{(pos,2i)}=\sin\left(\frac{pos}{10000^{\frac{2i}{d}}}\right)
PE(pos,2i)=sin(10000d2ipos)
P
E
(
p
o
s
,
2
i
+
1
)
=
cos
(
p
o
s
1000
0
2
i
d
)
PE_{(pos,2i + 1)}=\cos\left(\frac{pos}{10000^{\frac{2i}{d}}}\right)
PE(pos,2i+1)=cos(10000d2ipos)
其中 ( p o s pos pos ) 是词在序列中的位置,( i i i ) 是词向量的维度索引,( d d d ) 是词向量的总维度。
4. 前馈神经网络(Feed-Forward Neural Network, FFN)
在每个编码器和解码器层中,除了自注意力机制外,还包括一个前馈神经网络。每个时间步上的前馈网络是独立应用的,它的公式如下:
F
F
N
(
x
)
=
max
(
0
,
x
W
1
+
b
1
)
W
2
+
b
2
FFN(x)=\max(0,xW_1 + b_1)W_2 + b_2
FFN(x)=max(0,xW1+b1)W2+b2
其中,
W
1
W_1
W1 和
W
2
W_2
W2 是权重矩阵,
b
1
b_1
b1 和
b
2
b_2
b2 是偏置项,
ReLU
\text{ReLU}
ReLU 是非线性激活函数。
5. 残差连接和层归一化(Residual Connections and Layer Normalization)
Transformer 的每个子层(如自注意力机制或前馈神经网络)后面都有一个残差连接(Residual Connection)和层归一化(Layer Normalization),确保在网络训练的过程中信息可以直接传递,缓解深层网络中的梯度消失问题。
残差连接的形式为:
Output
=
LayerNorm
(
x
+
SubLayer
(
x
)
)
\text{Output}=\text{LayerNorm}(x+\text{SubLayer}(x))
Output=LayerNorm(x+SubLayer(x))
这里
x
x
x 是输入,
SubLayer
(
x
)
\text{SubLayer}(x)
SubLayer(x) 是注意力机制或前馈神经网络的输出。
6. Transformer 的应用
Transformer 由于其并行计算的优势,以及在处理长距离依赖关系上的优越表现,在许多任务中取得了卓越的成果:
- 机器翻译:例如谷歌翻译。
- 文本生成:例如 OpenAI 的 GPT 系列模型。
- 文本摘要:自动生成文档摘要。
- 语言建模:如 BERT、GPT 及其变体,用于各种 NLP 任务。
- 图像处理&多模态:ViT、ViLT。
7. Transformer 的优势
- 并行处理:不依赖时间步顺序,可以并行处理整个序列,因此训练速度更快,特别适合大规模数据集。
- 长距离依赖处理能力强:注意力机制,能够轻松处理序列中远距离的依赖关系,而不像 RNN 或 LSTM 那样受限于序列的长度。
- 广泛的应用:Transformer 已成为 NLP 的标准架构,并被扩展到其他领域,如图像处理(Vision Transformer, ViT)和语音处理等。
编码解码的过程
编码过程(Encoder)
主要任务是将输入序列转换为一种捕捉全局上下文信息的表示。这一过程确保输入序列中的每个元素(如文本中的单词或句子中的其他单位)都能够有效地“理解”整个输入序列中的其他元素,从而为后续任务(如机器翻译、文本生成等)提供丰富的上下文信息。
输入数据的准备(输入数据向量化+位置编码)
x final = x embedding + P E position x_{\text{final}}=x_{\text{embedding}}+PE_{\text{position}} xfinal=xembedding+PEposition
其中 x e m b e d d i n g x_{embedding} xembedding是输入数据向量化; P E p o s i t i o n PE_{position} PEposition是位置编码,具体实现如下:
输入数据的准备
- 输入序列:假设我们要处理一个输入序列(例如,一个句子的单词序列),每个单词 x 1 , x 2 , … , x n x_1,x_2,\ldots,x_n x1,x2,…,xn 都被表示为向量(通常通过嵌入矩阵映射得到)。
- 输入嵌入(Input Embedding):首先,通过嵌入层将每个单词映射为一个固定维度的嵌入向量。嵌入可以理解为字典,用来将离散的单词或符号映射为连续向量空间中的表示。
Embedding ( x i ) = W embedding x i \text{Embedding}(x_i)=W_{\text{embedding}}x_i Embedding(xi)=Wembeddingxi
其中, W embedding W_{\text{embedding}} Wembedding 是嵌入矩阵。 - 位置编码(Positional Encoding)
由于Transformer结构本身不保留输入序列的顺序信息(不像RNN那样逐步处理输入),需要通过位置编码显式引入序列的顺序。位置编码是通过正弦和余弦函数生成的,加入到每个输入嵌入向量中:
P E ( p o s , 2 i ) = sin ( p o s 1000 0 2 i d ) , P E ( p o s , 2 i + 1 ) = cos ( p o s 1000 0 2 i d ) PE_{(pos,2i)}=\sin\left(\frac{pos}{10000^{\frac{2i}{d}}}\right),\quad PE_{(pos,2i + 1)}=\cos\left(\frac{pos}{10000^{\frac{2i}{d}}}\right) PE(pos,2i)=sin(10000d2ipos),PE(pos,2i+1)=cos(10000d2ipos)
其中 p o s pos pos 是输入序列中位置, d d d 是嵌入向量的维度。
自注意力机制(循环计算多次——多头)
自注意力机制(Self - Attention Mechanism)
接下来,输入序列被送入自注意力机制。自注意力机制允许输入序列中的每个单词可以“关注”到其他单词,从而捕捉全局上下文信息。
- 查询、键和值向量(Q,K,V):每个输入嵌入向量通过三个不同的权重矩阵变换为查询(Query)、键(Key)和值(Value)向量。
Q = X W Q , K = X W K , V = X W V Q = XW_Q,\quad K = XW_K,\quad V = XW_V Q=XWQ,K=XWK,V=XWV
其中, X X X 是输入嵌入, W Q W_Q WQ、 W K W_K WK、 W V W_V WV 是权重矩阵。 - 注意力得分计算:查询和键的点积表示单词之间的相似性。点积的结果经过缩放并通过softmax函数,生成每个单词对其他单词的注意力权重:
Attention ( Q , K , V ) = softmax ( Q K T d k ) V \text{Attention}(Q,K,V)=\text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V Attention(Q,K,V)=softmax(dkQKT)V
这里 d k d_k dk 是键向量的维度。注意力机制将这些权重用于加权求和,以生成每个单词的新的上下文表示。
多头自注意力机制(Multi - Head Attention)
为了让模型能从不同的子空间中关注不同部分,Transformer引入了多头注意力机制,它并行计算多个注意力头,每个头有独立的查询、键和矩阵。不同的头关注序列中的不同信息,最后将结果拼接并线性变换:
MultiHead
(
Q
,
K
,
V
)
=
Concat
(
head
1
,
head
2
,
…
,
head
h
)
W
O
\text{MultiHead}(Q,K,V)=\text{Concat}(\text{head}_1,\text{head}_2,\ldots,\text{head}_h)W_O
MultiHead(Q,K,V)=Concat(head1,head2,…,headh)WO
这里
W
O
W_O
WO 是线性变换矩阵,
h
h
h 是注意力头的数量。
前馈神经网络
在每个编码器层的注意力机制之后,接着使用一个前馈神经网络,它对每个位置上的向量独立进行非线性变换:
F
F
N
(
x
)
=
max
(
0
,
x
W
1
+
b
1
)
W
2
+
b
2
FFN(x)=\max(0,xW_1 + b_1)W_2 + b_2
FFN(x)=max(0,xW1+b1)W2+b2
这是一个两层的全连接网络,使用 ReLU 作为激活函数。
残差连接和归一化
每一层的注意力机制和前馈神经网络的输出都会经过残差连接 (Residual Connection) 与输入相加,并通过层归一化 (Layer Normalization):
Output = LayerNorm ( x + SubLayer ( x ) ) \text{Output} = \text{LayerNorm}(x+\text{SubLayer}(x)) Output=LayerNorm(x+SubLayer(x))
这样可以缓解梯度消失问题,加速训练。
编码器通常由多层(例如 6 层)堆叠组成。最终,编码器的输出是一个包含全局上下文信息的序列表示,作为解码器的输入。
解码过程(Decoder)
解码过程是自回归的,目的是根据编码器生成的上下文信息,以及已经生成的部分目标序列,逐步生成完整的输出序列(例如,翻译后的句子)。解码器的每一层与编码器类似,但有几个额外的步骤。
自回归模型:Transformer 的解码器是自回归的,这意味着解码器会根据已经生成的输出(即部分目标序列)来生成下一个时间步的输出。
输入嵌入和位置编码
解码器首先将已经生成的目标序列进行嵌入,并加入位置编码,确保模型感知目标序列的顺序。
计算自注意力时加入遮蔽机制(Masked Self-Attention Mechanism)
在解码过程中,使用遮蔽自注意力机制。通过对未来词进行掩蔽,确保在生成某个位置上的词时,解码器只能看到之前生成的词,而不能看到未来的词。
这个步骤确保生成过程是按顺序进行的。
增加编码器-解码器注意力机制(Encoder-Decoder Attention)
在每一层中,解码器还使用编码器-解码器注意力机制。这个机制使解码器在生成每个目标词时参考编码器提供的上下文信息,帮助生成更合适的输出。
编码器-解码器注意力与自注意力的区别在于:
- 作用不同:
- 自注意力机制(Self-Attention Mechanism):作用于单一序列(即源序列或目标序列),用于捕捉序列内部元素之间的上下文信息。
- 编码器-解码器注意力机制(Encoder-Decoder Attention Mechanism):作用于两个序列之间(源序列和目标序列),用于将编码器的输出信息传递到 解码器中。解码器的每个位置会基于编码器输出的特征来生成当前步的输出,从而实现对源序列和目标序列的关联建模。
- 输入不同:
- 自注意力(Self-Attention):
- 查询 ( Q )、键 ( K )、值 ( V ) 都来自同一个输入序列
- 编码器-解码器注意力(Encoder-Decoder Attention):
- 查询 ( Q ) 来自解码器;
- 键 ( K ) 和值 ( V ) 来自编码器的输出序列。
- 自注意力(Self-Attention):
前馈神经网络
类似于编码器的每一层,解码器每层的输出也会通过一个前馈神经网络进行非线性变换。
残差连接和层归一化
与编码器相同,解码器也使用残差连接和层归一化来稳定训练过程。
输出生成
最后一层解码器的输出经过一个线性层和 softmax 函数,用来生成目标词的概率分布。在每个时间步,解码器根据概率分布选择下一个词,逐步生成整个目标序列。
整体编码解码流程总结
- 编码过程:编码器通过多头自注意力机制和前馈神经网络,将输入序列中的每个位置的单词转化为一个上下文相关的表示。经过多层堆叠的编码器,生成输入序列的全局表示,供解码器使用。
- 解码过程:解码器首先通过遮蔽自注意力机制生成目标序列中的下一个词,然后使用编码器-解码器注意力机制获取编码器输出的信息,结合目标序列的已有部分,生成新的词。解码器通过循环逐步生成整个目标序列。
这个过程确保模型能够捕捉输入序列的全局信息,并在生成目标序列时做到合理且流畅的生成。
训练、推理过程的不同
步骤 | 训练流程 | 推理流程 |
---|---|---|
输入准备 | 有完整的源序列和目标序列作为输入 | 只有源序列作为输入 (目标序列是空) |
解码器输入 | 使用目标序列的前 ( m-1 ) 个词作为解码器输入(强制教学) | 自回归生成,每步使用解码器生成的词作为下一步输入 |
生成机制 | 每步根据目标序列计算输出,并与真实词对比计算损失 | 逐步生成输出,依赖之前生成的词作为输入 |
损失计算 | 计算每个时间步与真实词之间的损失 | 无损失计算,只预测输出 |
反向传播 | 使用反向传播计算梯度,并更新模型参数 | 不涉及反向传播,只进行前向传播和输出预测 |
Transformer 推理的步骤
1. 输入准备
- 输入序列
- 词嵌入(Embedding)
- 位置编码
2. 编码器处理
- 6个循环编码器层:
- 多头自注意力机制
- 残差和归一化层
- 前馈神经网络
- 残差和归一化层
3. 解码器初始化
- 解码器输入:推理过程通常从一个特殊的起始符号(如
<sos>
,表示序列开始)开始。
4. 逐步生成输出
采用自回归生成,直到生成终止符(如 <eos>
,表示序列结束)。
每一步生成的流程如下:
- 6个循环解码器层:
- 掩码(masking)
- 自注意力机制(Masked Self-Attention)
- 编码器-解码器注意力机制
- 前馈神经网络
- 输出预测
- 更新解码器输入
5. 终止条件
- 生成终止符
- 达到最大长度
6. 输出序列
Self-Attention的计算过程
Self-Attention 的计算过程可以分为以下几个关键步骤:
1. 输入嵌入(输入序列向量化+位置编码)。
- 首先,将输入序列(如句子中的词)转换为嵌入向量。假设输入是长度为(n)的序列,每个元素被嵌入为(d_{\text{model}})维的向量。整个输入矩阵可以表示为 X ∈ R n × d model X\in\mathbb{R}^{n\times d_{\text{model}}} X∈Rn×dmodel。
2. 计算 Query、Key 和 Value。
- 接下来,将输入序列的每个嵌入向量通过三组线性变换投影为Query(
Q
Q
Q)、Key(
K
K
K)和Value(
V
V
V)。
- Query矩阵: Q = X W Q Q = XW_Q Q=XWQ,其中 W Q ∈ R d model × d k W_Q\in\mathbb{R}^{d_{\text{model}}\times d_k} WQ∈Rdmodel×dk
- Key矩阵: K = X W K K = XW_K K=XWK,其中 W K ∈ R d model × d k W_K\in\mathbb{R}^{d_{\text{model}}\times d_k} WK∈Rdmodel×dk
- Value矩阵: V = X W V V = XW_V V=XWV,其中 W V ∈ R d model × d v W_V\in\mathbb{R}^{d_{\text{model}}\times d_v} WV∈Rdmodel×dv
- 其中, d k d_k dk和 d v d_v dv是Query/Key和Value的嵌入维度。
3. 计算点积注意力得分。
- 使用Query和Key的点积来计算每个词对其他词的相似性或相关性。通过点积计算得到的结果反映了Query与Key的匹配程度:
- Score ( Q , K ) = Q K T \text{Score}(Q,K)=QK^T Score(Q,K)=QKT
- 其中,得到的矩阵是一个 n × n n\times n n×n的矩阵,表示输入序列中每个位置与所有其他位置的相关性。
4. 对点积进行缩放。
- 由于点积的值随着
d
k
d_k
dk的增大而变大,为了避免这些值过大导致梯度不稳定,点积的结果会除以
d
k
\sqrt{d_k}
dk进行缩放:
- Scaled Scores = Q K T d k \text{Scaled Scores}=\frac{QK^T}{\sqrt{d_k}} Scaled Scores=dkQKT
5. (可选)对未来时间步进行掩码。
- 在一些场景中(如解码器中的自回归任务),需要对未来的时间步进行掩码,防止模型看到未来信息。这可以通过在注意力得分中将无效的位置设置为负无穷大( − ∞ -\infty −∞)来实现,确保这些位置的softmax输出接近0。
6. 使用 softmax 计算注意力权重。
- 通过softmax函数,将缩放后的注意力得分转换为概率分布,得到每个词对其他词的注意力权重:
- Attention Weights = softmax ( Q K T d k ) \text{Attention Weights}=\text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right) Attention Weights=softmax(dkQKT)
- 这些权重反映了当前词对序列中其他位置的关注程度。
7. 将注意力权重与 Value 进行加权求和。
- 将注意力权重与Value矩阵相乘,得到每个词的注意力输出。该步骤可以看作是通过注意力权重从所有位置的Value中提取信息:
- Attention Output = Attention Weights × V \text{Attention Output}=\text{Attention Weights}\times V Attention Output=Attention Weights×V
- 这一步生成了最终的输出矩阵 R n × d v \mathbb{R}^{n\times d_v} Rn×dv,每个位置的输出是所有其他位置Value的加权和。
8. (可选)使用多头注意力机制。
- 在实际的Transformer模型中,使用的是多头注意力机制,这意味着多个不同的Query、Key和Value组合会并行计算,生成多个注意力输出。
- 每个头分别执行上述的注意力计算,然后将这些输出拼接在一起,经过一个线性变换,得到最终的多头注意力输出:
- Multi - Head Output = Concat ( Head 1 , … , Head h ) W O \text{Multi - Head Output}=\text{Concat}(\text{Head}_1,\ldots,\text{Head}_h)W_O Multi - Head Output=Concat(Head1,…,Headh)WO
- 其中, h h h是注意力头的数量, W O ∈ R h d v × d model W_O\in\mathbb{R}^{hd_v\times d_{\text{model}}} WO∈Rhdv×dmodel是输出的线性变换矩阵。
9. 残差连接与层归一化。
- Transformer中常见的后处理步骤是将注意力输出与原始输入通过残差连接相加,并经过层归一化:
- Final Output = LayerNorm ( X + Multi - Head Output ) \text{Final Output}=\text{LayerNorm}(X + \text{Multi - Head Output}) Final Output=LayerNorm(X+Multi - Head Output)
- 这种残差连接帮助模型避免梯度消失,并加速训练收敛。
这些步骤构成了 Self-Attention 机制的核心计算流程,确保模型可以有效地捕捉输入序列中各个位置之间的依赖关系。
下面将按照顺序详细讲解这些步骤中可能的考点
位置编码
在Transformer模型中,位置编码(Positional Encoding)是用于引入位置信息的关键组件。由于Transformer没有像递归神经网络(RNN)那样的顺序处理机制,它不能天然地获取输入序列的顺序信息,因此需要通过位置编码显式地为输入数据引入位置信息。
1. 位置编码的目的
自注意力机制是并行执行的,因此模型本身不会隐式地知道输入序列的顺序(即词的位置)。为了让模型理解序列的顺序,在【输入嵌入(word embedding)】上添加了位置编码,使得嵌入向量同时包含语义信息和位置信息。这可以让模型感知每个词的位置,从而能够处理具有顺序关系的任务,如机器翻译或文本生成。
在输入序列中的每个词嵌入向量
x
x
x 上,模型会将该词的位置信息加到它的嵌入上:
x
final
=
x
embedding
+
P
E
position
x_{\text{final}}=x_{\text{embedding}}+PE_{\text{position}}
xfinal=xembedding+PEposition
其中
P
E
position
PE_{\text{position}}
PEposition 是词在序列中的位置信息。通过这种加法操作,嵌入向量不仅包含了词本身的语义信息,还引入了词的位置信息。
2. 位置编码的公式
位置编码通过正弦和余弦函数生成,每个位置的编码向量都不同,从而保留了词在序列中的位置信息。位置编码的公式如下:
偶数维度
奇数维度
位置编码通过正弦和余弦函数生成,每个位置的编码向量不同于其他位置,从而保留了词在序列中的位置信息。位置编码的公式如下:
P
E
(
pos
,
2
i
)
=
sin
(
pos
1000
0
2
i
d
)
PE_{(\text{pos},2i)}=\sin\left(\frac{\text{pos}}{10000^{\frac{2i}{d}}}\right)
PE(pos,2i)=sin(10000d2ipos)
P
E
(
pos
,
2
i
+
1
)
=
cos
(
pos
1000
0
2
i
d
)
PE_{(\text{pos},2i + 1)}=\cos\left(\frac{\text{pos}}{10000^{\frac{2i}{d}}}\right)
PE(pos,2i+1)=cos(10000d2ipos)
其中:
- pos \text{pos} pos 表示词在序列中的位置索引(即第 pos \text{pos} pos 个词的位置)。
- i i i 是嵌入维度中的索引(每个词的嵌入是一个向量,有 d d d 个维度)。
- d d d 是嵌入维度的大小,即每个词的嵌入向量的长度。
分析公式:
- 偶数维度:对于嵌入向量中的偶数维度(即第
2
i
2i
2i 维),使用正弦函数:
P E ( pos , 2 i ) = sin ( pos 1000 0 2 i d ) PE_{(\text{pos},2i)}=\sin\left(\frac{\text{pos}}{10000^{\frac{2i}{d}}}\right) PE(pos,2i)=sin(10000d2ipos) - 奇数维度:对于嵌入向量中的奇数维度(即第
2
i
+
1
2i + 1
2i+1 维),使用余弦函数:
P E ( pos , 2 i + 1 ) = cos ( pos 1000 0 2 i d ) PE_{(\text{pos},2i+1)}=\cos\left(\frac{\text{pos}}{10000^{\frac{2i}{d}}}\right) PE(pos,2i+1)=cos(10000d2ipos)
其中,10000 是一个基数,用于控制位置编码的周期性和范围。选择10000作为基数(scale factor)的原因主要与平衡模型的数值范围和稳定性有关。选择 10000 作为基数能够确保模型在短距离信息和长距离信息之间取得平衡,既能感知局部词与词的关系,又能捕捉到全局顺序信息。
这里,10000 控制着不同维度中的频率。小的维度具有较大的频率(变化较快),而大的维度具有较小的频率(变化较慢)。这样,模型可以通过这些不同的频率来编码序列中的位置信息。 如果基数过大或过小,会影响位置编码的数值范围,进而影响模型的表现。
- 如果基数太大:正弦和余弦函数的输入值会非常小,导致输出接近线性变化,这样位置编码无法充分反映序列的位置信息。
- 如果基数太小:正弦和余弦函数的输入值会非常大,导致它们快速进入周期性的震荡状态,失去了平滑变化的特性,进而难以捕捉序列中相对较长的依赖关系。
10000 是一个经验性选择,确保正弦和余弦函数的值在常见的序列长度范围内(如20到100个词)能够有效地变化,既能捕捉到短距离的依赖关系,也能捕捉到较长距离的依赖。
3. 位置编码的特点
-
周期性:由于正弦和余弦函数的周期性,位置编码具有周期性的特点。这意味着编码可以很好地捕捉到序列中位置之间的相对关系,而不仅仅是绝对位置。对于较小的维度,编码的周期较短,可以捕捉到细粒度的局部位置信息;对于较大的维度,周期较长,捕捉到全局信息。
-
唯一性:每个位置都有独特的编码。通过将正弦和余弦函数应用于偶数和奇数维度,位置编码在不同维度上具有不同的变化模式,这保证了每个位置的编码是唯一的。
-
无参数学习:位置编码的值是通过公式计算得出的,而不是通过训练学习的。这与嵌入向量不同,嵌入向量是通过反向传播优化得到的参数。
总结
- 位置编码通过正弦和余弦函数为输入序列中的每个词引入位置信息,使Transformer模型能够理解输入序列中的顺序关系。
- 位置编码的生成方式使其在不同维度上具有不同的频率变化,从而能够捕捉到序列中的局部和全局关系。
- 正弦函数和余弦函数分别用于偶数和奇数维度,通过这种方式,位置编码可以为每个位置提供独特的向量表示,并且这种表示是平滑、连续的。
Q K V 维度
在 注意力机制 中,Q(Query)、K(Key)、和 V(Value) 的维度不一定需要完全相同,但有一些具体的约束条件和常见的设置。下面对它们的维度关系进行详细说明。
1. Query (Q)、Key (K)、Value (V) 的作用:
- Query:用于查询注意力得分,代表需要关注什么。
- Key:与 Query 进行匹配,决定应该关注哪些内容。
- Value:代表具体要提取和返回的内容,在确定了哪些部分重要之后,用于输出相关信息。
2. 常见的维度关系
在计算注意力时,Q、K、和 V 的维度可以不同,以下是常见的设置及约束:
2.1 Q 和 K 的维度通常相同
Q 和 K 的维度通常是相同的。原因是:
- 在点积注意力(dot-product attention)中,注意力分数是通过 Q 和 K 的点积计算得到的。因此,它们的最后一维(即嵌入维度)需要相同,以保证点积运算的合法性。
如果 ( Q ) 的维度是 ( d q d_q dq ),而 ( K ) 的维度是 ( d k d_k dk ),那么在进行 ( Q ⋅ K T Q \cdot K^T Q⋅KT ) 的点积运算时,通常要求 ( d q = d k d_q = d_k dq=dk ),以便能够得到一个合适的注意力得分矩阵。
2.2 V 的维度可以与Q和K的维度不同
V 的维度通常与输出的维度 ( d m o d e l d_{model} dmodel) 相关,可以与 Q 和 K 的维度不同。
3. 总结
- Q 和 K 的维度必须相同,以便能够进行点积计算,产生注意力得分。
- V 的维度可以与 Q 和 K 不同,因为 Value 只是加权求和的内容,维度可以根据任务需求设置。
常见的做法是将 Q、K 和 V 的维度设为相同,尤其是在多头注意力机制中,这是为了简化计算。
计算公式中的权重矩阵初始化
权重矩阵( W Q W_Q WQ ), ( W K W_K WK ), ( W V W_V WV )、线性变换权重( W O W_O WO )
- Xavier初始化(也称Glorot初始化)是**Transformer中注意力层权重矩阵初始化的常用选择,**适用于大多数线性层和多头注意力机制中的权重初始化。
- He初始化是前馈网络的权重初始化的常用选择具有ReLU或其变体激活函数的网络中更为有效,适用于提高模型的稳定性。
- 偏置项:一般初始化为 0。
权重矩阵的训练与学习
在Transformer中,这些权重矩阵,即 ( W Q W_Q WQ ), ( W K W_K WK ), ( W V W_V WV ), ( W O W_O WO )都是模型的可训练参数。训练过程如下:
- 初始化:在训练开始时,这些权重矩阵使用Xavier初始化,随机初始化为小值。
- 前向传播:输入序列通过这些线性变换生成查询、键和值,然后经过注意力计算,得到输出。
- 计算损失:根据模型的输出和目标值,计算损失函数,如交叉熵损失(在分类任务中)。
- 反向传播:通过反向传播算法,损失函数的梯度从输出层逐层传递回这些线性变换的权重矩阵。
- 更新权重:使用优化算法(如Adam或SGD),根据梯度更新权重矩阵的值,从而逐步调整它们,使模型在后续的训练中能够更好地拟合数据。
激活函数相关知识点参考:深度学习——权重初始化、评估指标、梯度消失和梯度爆炸
为什么要进行缩放?
Scaled Dot-Product Attention,“scaled” 指的是对点积的结果进行缩放处理。
在 Transformer 的注意力机制中,Attention 的核心操作是计算"查询(Query)"和"键(Key)"的点积,来衡量输入序列中不同位置的信息相互关联的程度。公式如下:
Attention
(
Q
,
K
,
V
)
=
softmax
(
Q
K
T
d
k
)
V
\text{Attention}(Q,K,V)=\text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V
Attention(Q,K,V)=softmax(dkQKT)V
其中:
- Q Q Q 是查询向量(Query)。
- K K K 是键向量(Key)。
- V V V 是值向量(Value)。
- d k d_k dk 是键向量的维度。
原因
这个缩放步骤是为了避免点积值过大,导致后续的 softmax函数输出分布非常尖锐,产生梯度爆炸问题
这个操作可以将点积值缩小,使得它们处于更合理的范围内,从而保证 softmax 函数的输入不会过大或过小。从而使 Transformer 模型的注意力机制能够更有效地学习长距离依赖关系
在没有缩放的情况下,点积 ( Q K T QK^T QKT ) 的值随着维度 ( d k d_k dk ) 增大而变大。当维度较大时,点积的结果可能会非常大,导致在应用 softmax 函数时,输出分布非常尖锐(即某些注意力权重接近于 1,而其他权重接近于 0)。这会导致梯度爆炸的问题,影响模型的训练效果。
Scaled 的作用
-
数学解释:键的维度 ( d k d_k dk ) 增大时,点积 ( Q K T QK^T QKT ) 的期望值和方差也会增大。通过除以 ( d k \sqrt{d_k} dk ),可以将点积的方差标准化为 1,保持稳定的数值范围。
-
实际效果:缩放后的点积值较小,softmax 输出会更加平滑,能够更合理地分配注意力权重,从而改善训练的稳定性和模型的表现。