这里写目录标题
- 前言
- 第 1 节 · N 元文法语言模型
- 1.2、平滑(Smoothing)
- 1.2.1、加 1 平滑 / 拉普拉斯平滑(Add-One Smoothing / Laplace Smoothing)
- 1.2.2、 δ \delta δ 平滑(Add-K Smoothing / Delta Smoothing)
- 1.2.3、困惑度(Perplexity)
- 1.3、回退(Back-off)
- 1.4、插值(Interpolation)
- 第 2 节 · 感知器(Perceptron)
- 2.1、线性回归(Linear Regression)
- 2.2、逻辑回归(Logistic Regression)
- 2.3、Sigmoid 回归
- 2.4、Softmax 回归
- 2.6、多层感知器(Multi-Layer Perceptron)
- 2.7、简述如何训练一个模型:正向传播与反向传播
- 第 3 节 · 卷积神经网络(CNN)
- 第 4 节 · 循环神经网络(RNN)
- 4.1、经典结构的 RNN(N vs N RNN)
- N vs.1 的 RNN
- 1 vs. N 的 RNN
- 4.4、LSTM(Long Short-Term Memory)长短时记忆网络
- 4.5、双向 RNN 和双向 LSTM
- 4.6、堆叠循环神经网络(Stacked RNN)、堆叠长短时记忆网络(Stacked LSTM)
- 4.7、N vs. M 的 RNN (Encoder-Decoder)
- 第 5 节 · 为什么说 RNN 模型没有体现「注意力」?
- 第 6 节 · 基于 Attention 机制的 Encoder-Decoder 模型
- 第 7 节 · 自注意力机制(Self-Attention)
- 第 8 节 · 多头注意力(Multi-Head attention)
- 第 9 节 · 退化现象、残差网络与 Short-Cut
- 第 10 节 · Transformer 的位置编码(Positional Embedding)
- 10.2、绝对位置编码
- 10.3、相对位置编码与其他位置编码
- 第 11 节 · Transformer 的编码器 Encoder 和解码器 Decoder
- 11.1、Encoder 和 Decoder 的图示结构
- 第一个 masked multi-head attention
- 第二个 multi-head attention
- 11.2、Decoder 的第一个输出结果
- 11.3、Decoder 后续的所有输出
- 11.4、Decoder 之后的 Linear 和 Softmax
- 第 12 节 · Transformer 模型整体
前言
这篇文章是关于《如何从浅入深理解transformer》 的一个阅读笔记。
因为是第一次接触 transformer,找了半天,感觉这篇文章作为入门来说还不错,可以将整个发展的历程串联起来讲。
但是这毕竟是一篇阅读笔记,我只会对个人不太清楚的概念详细了解。
第 1 节 · N 元文法语言模型
n-Gram 模型的主体思想就是:下一个词出现的概率只依赖于它前面 n-1 个词,也被称为 n 阶马尔科夫链。
文中出现的公式: P ( w t ∣ w 1 , w 2 , . . . , w t − 1 ) = C ( w 1 , w 2 , . . . , w t ) C ( w 1 , w 2 , . . . , w t − 1 ) P(w_t|w_1, w_2,...,w_{t-1}) = \frac{C(w_1, w_2,...,w_{t})}{C(w_1, w_2,...,w_{t-1})} P(wt∣w1,w2,...,wt−1)=C(w1,w2,...,wt−1)C(w1,w2,...,wt) 其中的参数 C ( w 1 , w 2 , . . . , w t ) C(w_1, w_2,...,w_{t}) C(w1,w2,...,wt) 表示词序列 w 1 , w 2 , . . . , w t w_1, w_2,...,w_{t} w1,w2,...,wt 在训练语料中出现的次数(count)。 C ( w 1 , w 2 , . . . , w t − 1 ) C(w_1, w_2,...,w_{t-1}) C(w1,w2,...,wt−1) 也是一样的含义。但是根据条件概率的定义的,本来的公式应该是: P ( w t ∣ w 1 , w 2 , . . . , w t − 1 ) = P ( w 1 , w 2 , . . . , w t ) P ( w 1 , w 2 , . . . , w t − 1 ) P(w_t|w_1, w_2,...,w_{t-1}) = \frac{P(w_1, w_2,...,w_{t})}{P(w_1, w_2,...,w_{t-1})} P(wt∣w1,w2,...,wt−1)=P(w1,w2,...,wt−1)P(w1,w2,...,wt)也就是应该使用词序列在训练语料里出现的概率来进行计算的。
为什么第一个公式使用了次数(count)来代替概率(probability)来计算条件概率呢?
由于在实际应用中,直接计算词序列的联合概率 P ( w 1 , w 2 , . . . , w t ) P(w_1, w_2,...,w_{t}) P(w1,w2,...,wt) 通常不可行,因为它们涉及到整个词序列的概率计算,而这些概率往往非常小,容易导致数值下溢。因此,通常使用词频来近似这些概率。
根据大数定律,当语料库足够大时,词频可以近似为概率。因此,可以将上述公式中的概率用词频来替代:
接着,我们就可以对词序列 w 1 , w 2 , . . . , w t w_1, w_2,...,w_{t} w1,w2,...,wt 的概率 P ( w 1 , w 2 , . . . , w t ) P(w_1, w_2,...,w_{t}) P(w1,w2,...,wt) 进行计算了: P ( w 1 , w 2 , . . . , w t ) = P ( w t ∣ w 1 , w 2 , . . . , w t − 1 ) ⋅ P ( w t − 1 ∣ w 1 , w 2 , . . . , w t − 2 ) … P ( w 1 ) = ∏ t − 1 i = 1 P ( w i ∣ w 1 : i − 1 ) \begin{align*} P(w_1, w_2,...,w_{t}) &= P(w_t|w_1, w_2,...,w_{t-1}) \cdot P(w_{t-1}|w_1, w_2,...,w_{t-2}) \dots P(w_1) \\ &=\prod_{t-1}^{i=1} P(w_i|w_{1:i-1}) \end{align*} P(w1,w2,...,wt)=P(wt∣w1,w2,...,wt−1)⋅P(wt−1∣w1,w2,...,wt−2)…P(w1)=t−1∏i=1P(wi∣w1:i−1) 上面这个是 n-gram 模型计算词序列概率的式子,也就是第 n 个词只依赖于它前面的 n-1 个词。
如果是 n = 2 的情况,也就是二元文法 bi-gram 模型的情况呢,第 n 个词只依赖于它前面的第 n-1 个词,也就是当前词语出现的概率只由上一个词决定。我们可以稍微简化一下上面的公式,就可以得到: P ( w 1 , w 2 , . . . , w t ) = ∏ i = 1 t − 1 P ( w i ∣ w i − 1 ) = ∏ i = 1 t − 1 C ( w i − 1 , w i ) C ( w i − 1 ) P(w_1, w_2,...,w_{t}) = \prod_{i=1}^{t-1} P(w_i|w_{i-1}) = \prod_{i=1}^{t-1}\frac{C(w_{i-1}, w_i)}{C(w_{i-1})} P(w1,w2,...,wt)=i=1∏t−1P(wi∣wi−1)=i=1∏t−1C(wi−1)C(wi−1,wi) 这就是二元文法 bi-gram 模型计算词序列出现概率的公式。
- 如果有词出现次数为了 0,这一串乘出来就是 0 了,咋办?
- 因为基于马尔科夫假设,所以 N 固定窗口取值,对长距离词依赖的情况会表现很差。
- 如果把 N 值取很大来解决长距离词依赖,则会导致严重的数据稀疏(零频太多了),参数规模也会急速爆炸(高维张量计算)。
文中提出了上面 3 个问题,这个三个问题其实是有某种递进关系的,归纳起来就是
- 零频
- N 取值过小
- N 取值过大
首先我们可以观察上面的 n-gram 公式,如果连乘的概率中出现一个词序列的概率为 0 的话,就会导致整个结果都变为 0。这个问题要怎么尽可能避免了呢,通过减少 N 的取值?尽可能杜绝零频率词序列的出现?但是这会导致长距离词依赖(Long-Range Dependencies)变现变差的问题,如果为了解决长距离词依赖的问题,将 N 值取得很大呢,这又会导致参数爆炸和数据稀疏的问题(也就是回到了问题一,出现词序列零频的问题)。所以这三个问题就像是一个恶性循环,如果尝试解决一个问题,就会引入另一个问题。
所以我们要另辟蹊径,通过外部的手段解决零频的问题,而不是简单的通过调整 N 值的大小。
1.2、平滑(Smoothing)
词序列零频的问题是普遍存在的:
- 未登录词:N 值比较大的时候,可能导致的未登录词问题(Out Of Vocabulary,OOV),N 越大,代表着词序组合的长度越长,很多词序组合可能在训练数据中可能就出现了一两次,甚至没有出现过,并不具备统计学意义。
- 有限的训练数据:训练数据很可能也不是 100% 完备覆盖实际中可能遇到的词的。
为了解决零频的问题,我们引入是平滑(smoothing)的概念。
简单来说就是
1.2.1、加 1 平滑 / 拉普拉斯平滑(Add-One Smoothing / Laplace Smoothing)
bi-gram 的加 1 平滑公式: P ( w i ∣ w i − 1 ) = C ( w i − 1 , w i ) + 1 ∑ j = 1 V ( C ( w i − 1 , w j ) + 1 ) = C ( w i − 1 , w i ) + 1 C ( w i − 1 ) + V P(w_i|w_{i-1}) = \frac{C(w_{i-1}, w_i) +1}{ {\textstyle \sum_{j=1}^{V}} (C(w_{i-1}, w_j) + 1)} = \frac{C(w_{i-1}, w_i)+1}{C(w_{i-1}) + V} P(wi∣wi−1)=∑j=1V(C(wi−1,wj)+1)C(wi−1,wi)+1=C(wi−1)+VC(wi−1,wi)+1 其中:
- C ( w i − 1 , w i ) C(w_{i-1}, w_i) C(wi−1,wi): 表示词序列 w i − 1 , w i w_{i-1}, w_i wi−1,wi 的词频
- ∑ j = 1 V ( C ( w i − 1 , w j ) + 1 ) {\textstyle\sum_{j=1}^{V}} (C(w_{i-1}, w_j) + 1) ∑j=1V(C(wi−1,wj)+1):因为 j j j 是从 1 到 V,其中 V 表示的是词汇表的数量,也就是说 w j w_j wj 是词汇表中出现的每一个词。 w i − 1 , w j w_{i-1}, w_j wi−1,wj 表示第一个词为 w i − 1 w_{i-1} wi−1 的情况下,后面跟着不同词的总次数,所以化简之后可以得到最后部分的式子。
其中 N N N 表示所有词的词频之和, V V V 表示词汇表的大小。
原文中提到上面这句话,这个 N N N 可能是指原文公式的求和的上标 n n n,表示 token 的数量,但是我觉得公式里求和的上标应该是词汇表(vocabulary)的大小。
uni-gram 的加 1 平滑公式是: P ( w i ) = C ( w i ) + 1 N + V P(w_i) = \frac{C(w_i) + 1}{N+V} P(wi)=N+VC(wi)+1这里涉及的 N N N 就是训练的 token 总数,即便是有重复的词语,都会被计算在内, V V V 是词汇表的大小,表示在训练数据中唯一的存在,相当于 set 处理之后的 token。
1.2.2、 δ \delta δ 平滑(Add-K Smoothing / Delta Smoothing)
这是对加 1 平滑的优化,对于某些
bi-gram 的加 δ \delta δ 平滑公式: P ( w i ∣ w i − 1 ) = C ( w i − 1 , w i ) + δ ∑ j = 1 V ( C ( w i − 1 , w j ) + δ ) = C ( w i − 1 , w i ) + δ C ( w i − 1 ) + δ V P(w_i|w_{i-1}) = \frac{C(w_{i-1}, w_i) +\delta}{ {\textstyle \sum_{j=1}^{V}} (C(w_{i-1}, w_j) + \delta)} = \frac{C(w_{i-1}, w_i)+\delta}{C(w_{i-1}) + \delta V} P(wi∣wi−1)=∑j=1V(C(wi−1,wj)+δ)C(wi−1,wi)+δ=C(wi−1)+δVC(wi−1,wi)+δ 和加 1 平滑基本一样,就是将 1 换成了 δ \delta δ。
与加 1 平滑相比,加 δ \delta δ 平滑允许对于低频词的平滑程度进行更灵活的控制。当 δ \delta δ 较小时,对低频事件的平滑效果较小,而 δ \delta δ 较大时,平滑效果更加显著。这使得模型在平滑概率时能够更好地适应不同的数据特点。
δ \delta δ 是一个超参数,如果可以寻找到最优的值,就可以使得模型的效果更好,原文中说确定这个 δ \delta δ 值需要用到困惑度(Perplexity),但是其实个人觉得,只是一种比较间接的影响关系。
首先加 δ \delta δ 平滑操作的对象都是训练集,然后训练出一个语言模型,然后困惑度是用来评价语言模型在测试集上的性能的。通过调整 δ \delta δ 值,进行多次训练,使得语言模型在特定测试集的困惑度最小,这样便能得到最优的模型。
1.2.3、困惑度(Perplexity)
(在这里突然插入一个评价指标有点奇怪)
困惑度:评价一个概率模型预测测试集的能力,困惑度越低,表示模型越好。
下面是针对单一词序列 w 1 , w 2 , … , w N w_1, w_2, \dots ,w_N w1,w2,…,wN 的困惑度计算公式,并不是整个测试集的: Perplexity ( W ) = P ( w 1 , w 2 , … , w N ) − 1 N = 1 P ( w 1 , w 2 , … , w N ) N \text{Perplexity}(W) =P(w_1, w_2, \dots ,w_N)^{-\frac{1}{N} }= \sqrt[N]{\frac{1}{P(w_1, w_2, \dots, w_N)}} Perplexity(W)=P(w1,w2,…,wN)−N1=NP(w1,w2,…,wN)1我们可以看到,公式里是将这段词序列的出现概率开了 N 次根,然后再求了倒数。
为什么要进行开 N 次方根的操作?
为了将不同长度的词序列归一化到一个统一的尺度来进行比较。我们将联合概率标准化为每个词的平均概率,即平均每个词的预测概率。这样,我们可以更好地比较模型在不同长度序列上的性能,而不受序列长度的影响。
我们将前面的联合概率的公式代入进去,就可以得到: Perplexity ( W ) = ∏ i = 1 N 1 P ( w i ∣ w 1 , w 2 , … , w i − 1 ) N \text{Perplexity}(W) = \sqrt[N]{\prod_{i=1}^{N} \frac{1}{P(w_i|w_1,w_2,\dots ,w_{i-1})} } Perplexity(W)=Ni=1∏NP(wi∣w1,w2,…,wi−1)1也可以得到 bi-gram 的单一词序列困惑度计算公式: Perplexity ( W ) = ∏ i = 1 N 1 P ( w i ∣ w i − 1 ) N \text{Perplexity}(W) = \sqrt[N]{\prod_{i=1}^{N} \frac{1}{P(w_i| w_{i-1})} } Perplexity(W)=Ni=1∏NP(wi∣wi−1)1
1.3、回退(Back-off)
在回退模型中,计算一个3-gram的概率时,如果这个3-gram在训练数据中存在,则直接使用其概率;如果不存在,则回退到2-gram,然后再回退到1-gram,依此类推。这样,即使某个组合在3-gram中没有观察到,仍然可以通过回退到2-gram等较低阶的模型来估计其概率。
这个感觉还是挺好理解的,一句话来说就是:退而求其次。
公式也挺好理解的: P ( w i ∣ w i − 2 , w i − 1 ) = { P ( w i ∣ w i − 2 , w i − 1 ) C ( w i − 2 , w i − 1 , w i ) > 0 P ( w i ∣ w i − 1 ) C ( w i − 2 , w i − 1 , w i ) = 0 and C ( w i − 1 , w i ) > 0 P(w_i|w_{i-2},w_{i-1}) = \begin{cases} P(w_i|w_{i-2},w_{i-1}) & C(w_{i-2},w_{i-1},w_i)>0 \\ P(w_i|w_{i-1}) & C(w_{i-2},w_{i-1},w_i)=0 \space\space\space\space \text{and} \space\space\space\space C(w_{i-1},w_i)>0 \end{cases} P(wi∣wi−2,wi−1)={P(wi∣wi−2,wi−1)P(wi∣wi−1)C(wi−2,wi−1,wi)>0C(wi−2,wi−1,wi)=0 and C(wi−1,wi)>0
1.4、插值(Interpolation)
在计算 n-gram 的概率的时候,也考虑 n-1-gram,甚至是 n-2-gram 的概率:
P
(
w
i
∣
w
i
−
2
,
w
i
−
1
)
=
λ
1
P
(
w
i
∣
w
i
−
2
,
w
i
−
1
)
+
λ
2
P
(
w
i
∣
w
i
−
1
)
+
λ
3
P
(
w
i
)
P(w_i|w_{i-2},w_{i-1}) = \lambda_1P(w_i|w_{i-2},w_{i-1}) + \lambda_2P(w_i|w_{i-1}) + \lambda_3P(w_i)
P(wi∣wi−2,wi−1)=λ1P(wi∣wi−2,wi−1)+λ2P(wi∣wi−1)+λ3P(wi)
第 2 节 · 感知器(Perceptron)
感知器一般用于处理二分类问题: y = { 1 , if w x + b > 0 0 , othrewise y = \begin{cases} 1, & \text{ if } wx + b > 0 \\ 0, & \text{othrewise} \end{cases} y={1,0, if wx+b>0othrewise其中 w w w 是权重, b b b 是偏置项。
2.1、线性回归(Linear Regression)
上面的公式中 w x + b wx+b wx+b 的计算结果是需要映射到 0,1 两个结果中,是离散值,解决的是分类问题。但是如果我们直接将 w x + b wx+b wx+b 的计算结果拿过来使用,而不进行映射的话,结果将会是一个连续值,问题也会变成线性回归问题。
原本中有一个使用 pytorch 库中 nn.Linear 进行代码实操的代码片段,这里就不多说了。
2.2、逻辑回归(Logistic Regression)
如果说线性回归的结果是没有限制范围的,那么逻辑回归就会将计算结果限制在一个特定范围之内。
在线性回归的公式为: y = w x + b y = wx + b y=wx+b
那么在逻辑回归中: y = σ ( w x + b ) y = \sigma (wx + b) y=σ(wx+b)
激活函数会将线性回归 w x + b wx+b wx+b 的计算结果,再限制在一个确定的范围了。
上面这张图展示了逻辑回归的流程,已经有点神经网络的神经元的雏形了。
2.3、Sigmoid 回归
sigmoid 函数是我们在神经网络中常见到的激活函数,简单来说,当逻辑回归中的
σ
(
z
)
\sigma(z)
σ(z) 是 sigmoid 函数的时候,这个逻辑回归也叫做 sigmoid 回归。
y
=
Sigmoid
(
w
x
+
b
)
=
1
1
+
e
−
(
w
x
+
b
)
y = \text{Sigmoid} (wx + b) = \frac{1}{1+e^{-(wx+b)}}
y=Sigmoid(wx+b)=1+e−(wx+b)1 其中
Sigmoid
(
z
)
=
1
1
+
e
−
z
\text{Sigmoid}(z) = \frac{1}{1+e^{-z}}
Sigmoid(z)=1+e−z1,这个 sigmoid 函数会将结果值限制在
[
0
,
1
]
[0, 1]
[0,1] 之间。
一般是用在二分类问题中预测概率。
2.4、Softmax 回归
上面说到 sigmoid 回归主要是针对二分类的问题,现在要介绍的 softmax 回归主要就是针对多分类的问题。
如上图所示,一个输入 x x x,如果要进行 softmax 回归,进行类别为 K K K 的 多元分类。首先和 sigmoid 一样,需要经过各自类别的权重 w K w_K wK 和偏置 b K b_K bK 处理之后,得到每个类别的原始得分 z K z_K zK。然后一起送入到 softmax 函数内计算对应类别的概率。
这个公式就是计算输入在类别
i
i
i 的概率:
y
i
=
σ
(
z
)
i
=
e
z
i
∑
j
=
1
K
e
z
j
=
e
z
i
e
z
1
+
e
z
2
+
⋯
+
e
z
K
y_i = \sigma (\bold{z})_i = \frac{e^{z_i}}{\sum_{j=1}^{K} e^{z_j}} = \frac{e^{z_i}}{ e^{z_1} + e^{z_2} + \dots + e^{z_K} }
yi=σ(z)i=∑j=1Kezjezi=ez1+ez2+⋯+ezKezi其中有
z
K
=
w
K
x
+
b
K
z_K = w_K x + b_K
zK=wKx+bK。
一般来说,输入 x x x 其实也是一个维度为 K K K 的向量,如果不足的可以进行补零,超出的话就进行保留最主要的 K K K 个特征。这里我假设这个输入向量 x \bold{x} x 的所有维度的值都是 x x x。
2.6、多层感知器(Multi-Layer Perceptron)
MLP 是一种全连接的前馈神经网络,每一层的每个神经元都与上一层的所有神经元相连,有点全连接层的意思。
而且,MLP 中的激活函数必须得是非线性激活函数,如果是线性,不管是多少层,其实都只是一个简单的线性模型,只能解决简单的线性问题,没有非线性的学习能力。
因为全连接的关系,所以一个比较大的缺点就是:计算量非常大。
MLP 主要有输入层,隐藏层和输出层三个部分组成。
其中最重要的是隐藏层,加权求和,还有激活函数的操作都是在隐藏层进行的。
为了加深对 MLP 的理解,我自己画了一下 MLP 的一个简单的网络结构图。输入层和输出层没有像大多数图那样画成节点的形式,也将权重偏置显式地标注了出来。
图中的 w 0 , 00 w_{0, 00} w0,00 的下标逗号之前的 0 0 0 表示这个参数属于第 0 0 0 层隐藏层的。下标逗号后面的 00 00 00 表示这是输入参数 x 0 x_0 x0 与隐藏单元 h 0 , 0 h_{0, 0} h0,0 之间的参数。
如果将这个网络结构用向量公式表现出来就是下面的式子: A 0 = f ( W 0 ⋅ X + b 0 ) Y = f ( W 1 ⋅ A 0 + b 1 ) \begin{matrix} \mathbf{A_0} = f(\mathbf{ W_0 \cdot X + b_0})\\ \mathbf{Y} = f(\mathbf{W_1 \cdot A_0 + b_1} ) \end{matrix} A0=f(W0⋅X+b0)Y=f(W1⋅A0+b1)其中 W 0 = [ w 0 , 00 w 0 , 10 w 0 , 01 w 0 , 11 w 0 , 02 w 0 , 12 ] , X = [ x 0 x 1 ] , b 0 = [ b 0 , 00 + b 0 , 10 b 0 , 01 + b 0 , 11 b 0 , 02 + b 0 , 12 ] \mathbf{W_0} = \begin{bmatrix} w_{0,00} & w_{0, 10} \\ w_{0,01} & w_{0, 11}\\ w_{0,02} & w_{0, 12} \end{bmatrix}, \space \space \space \space \space \mathbf{ X} = \begin{bmatrix} x_0\\ x_1 \end{bmatrix}, \space \space \space \mathbf{b_0} =\begin{bmatrix} b_{0,00} + b_{0, 10}\\ b_{0,01} + b_{0, 11} \\ b_{0,02} + b_{0,12} \end{bmatrix} W0= w0,00w0,01w0,02w0,10w0,11w0,12 , X=[x0x1], b0= b0,00+b0,10b0,01+b0,11b0,02+b0,12 可以得到: W 0 ⋅ X + b 0 = [ w 0 , 00 w 0 , 10 w 0 , 01 w 0 , 11 w 0 , 02 w 0 , 12 ] ⋅ [ x 0 x 1 ] + [ b 0 , 0 b 0 , 1 b 0 , 2 ] = ( w 0 , 00 ⋅ x 0 + w 0 , 10 ⋅ x 1 + b 0 , 0 ) + ( w 0 , 01 ⋅ x 0 + w 0 , 11 ⋅ x 1 + b 0 , 1 ) + ( w 0 , 02 ⋅ x 0 + w 0 , 12 ⋅ x 1 + b 0 , 2 ) \begin{align*} \mathbf{ W_0 \cdot X + b_0} &= \begin{bmatrix} w_{0,00} & w_{0, 10} \\ w_{0,01} & w_{0, 11}\\ w_{0,02} & w_{0, 12} \end{bmatrix} \cdot \begin{bmatrix} x_0\\x_1\end{bmatrix} + \begin{bmatrix} b_{0,0} \\ b_{0,1} \\ b_{0,2} \end{bmatrix}\\ &= (w_{0,00}\cdot x_0 + w_{0,10}\cdot x_1 + b_{0,0}) \\ & \space \space \space \space + (w_{0,01}\cdot x_0 + w_{0,11}\cdot x_1 + b_{0,1}) \\ & \space \space \space \space + (w_{0,02}\cdot x_0 + w_{0,12}\cdot x_1 + b_{0,2}) \end{align*} W0⋅X+b0= w0,00w0,01w0,02w0,10w0,11w0,12 ⋅[x0x1]+ b0,0b0,1b0,2 =(w0,00⋅x0+w0,10⋅x1+b0,0) +(w0,01⋅x0+w0,11⋅x1+b0,1) +(w0,02⋅x0+w0,12⋅x1+b0,2) 因为偏置项 b b b 是常数,所以这里我将两个常数直接合并了。
最后得出来的结果也是我们非常熟悉的形式。然后和之前的逻辑回归类似,将这个加权求和得到的结果,送到激活函数中,进行非线性的变换,得到我们所需的下一个隐藏层的输入项 A 0 \mathbf{A_0} A0。
合并偏置常数项之后,我们的 MLP 结构图也可以画成上图的形式。
第二隐藏层的具体式子在这里就不列出来了。
2.7、简述如何训练一个模型:正向传播与反向传播
这个原文中也没做过多的展开,我这里也留着
第 3 节 · 卷积神经网络(CNN)
MLP 里每一层的每个元素,都要乘以一个独立参数的权重 W,再加上一个偏置 b,这样的神经网络层常被我们叫做「全连接层(Fully Connected Layer)或稠密层(Dence Layer)。但是这样有个显著问题:如果输入内容的局部重要信息只是发生轻微移动并没有丢失,在全连接层处理后,整个输出结果都会发生很大变化 —— 这不合理
即全连接层可能在处理输入时过于强调整体特征,而不足够关注输入中的局部结构信息。
所以为了让全连接层也能关注局部信息,是否可以设置一个滑动窗口来对局部输入进行处理。这就会 n-gram 设置 N 值的大小思路一样。这就引出了我们熟悉的 CNN 卷积神经网络,使用卷积核在原图上的滑动来提取图像的局部特征。
- CNN 与 MLP 有什么区别?
- CNN 的共享权重是什么意思?
- CNN 的局部连接是什么意思?
上面我画的示意图中,MLP 的输入数据是一维的,所以所有输入 MLP 进行全连接处理的数据都得先展平成一维的数据,而 CNN 的输入数据则是二维的,也就是可以。
其实某种意义上,可以将 MLP 理解成一个 1 × 1 1\times1 1×1 的卷积,但是和真正的 1 × 1 1\times1 1×1 卷积又有一些微秒的区别,在 CNN 中我们也常使用 1 × 1 1\times1 1×1 卷积来实现全连接结构,但是 1 × 1 1\times1 1×1 卷积的输入可以是二维的数据,而 MLP 还是只能输入一维的数据。
让我们修改一下上面的图,将输入数据变成我们熟悉的二维图像数据。
第 4 节 · 循环神经网络(RNN)
4.1、经典结构的 RNN(N vs N RNN)
也就是输入和输出的维度是一样的。
N vs.1 的 RNN
1 vs. N 的 RNN
4.4、LSTM(Long Short-Term Memory)长短时记忆网络
LSTM 因为在图像处理中基本用不上,所以我比较陌生。是一种特殊的 RNN 网络。
我们通过 RNN 的结构就可以看出来,后向传播的时候,连续的乘法结构很容易造成梯度消失或者梯度爆炸的问题。在 CNN 的时候,我们会通过 dropout 对某些神经元进行舍弃,来进行正则化,缓解梯度消失和爆炸的问题。而 LSTM 中呢,我们也会设计一个模块对过往的信息进行舍弃,来缓解 RNN 中出现的梯度消失或者爆炸问题。
LSTM将长短期记忆文本管理问题分为两个子问题:
- 从上下文中删除不再需要的信息(舍弃部分过往信息)
- 添加可能在后续决策中需要的信息(添加当前输入信息)
LSTM 引入了 “门(gate)” 的概念来控制信息的流向,可以分成 3 个门:
- 遗忘门(forget gate):用于去除上文中所不需要的信息。
- 输入门(input gate):将当前的信息输入到上下文中。
- 输出门(output gate):输出当前的上下文信息。
其实 LSTM 的结构和公式都不难理解,但是我希望在这里一步步从 RNN 推导到 LSTM,就有很多细节不清楚了,这里暂时也不过多的纠结了。
4.5、双向 RNN 和双向 LSTM
在经典的循环神经网络中,状态的传输是从前往后单向的。然而,在有些问题中,当前时刻的输出不仅和之前的状态有关系,也和之后的状态相关。这时就需要双向RNN(BiRNN)来解决这类问题。例如预测一个语句中缺失的单词不仅需要根据前文来判断,也需要根据后面的内容,这时双向RNN就可以发挥它的作用。
原文中给了一张简单的 bi-RNN 示意图,但是我感觉有点容易误解的地方。它只是对前向和反向的隐藏层权重
W
W
W 和
W
′
W'
W′ 进行了区分,但是没有区分
V
V
V 和
V
′
V'
V′ ,
U
U
U 和
U
′
U'
U′ 的权重。
一般计算的步骤是从前向后算一次,然后再从后向前计算一次。
原文虽然小标题中提到了双向 LSTM,但是实际没有具体的提到双向 LSTM 的,所以我这里也暂时略过。
4.6、堆叠循环神经网络(Stacked RNN)、堆叠长短时记忆网络(Stacked LSTM)
就是一层的输出作为下一层的输入,多层堆叠
4.7、N vs. M 的 RNN (Encoder-Decoder)
上图是一个抽象化的 Encoder-Decoder 模型示意图,相当于一个 N vs 1 和一个 1 vs M 的 RNN 网络的串联。一般我们也称之为 Seq2Seq 模型。
Encoder-Decoder 的结构有多种,但是大体的原理都是一样的。
仅管 Encoder-Decoder 模型可以实现序列到序列的任务,对于语音识别,翻译任务,问答任务的效果很不错,但是也存在一些问题:
- 长序列信息丢失问题:Encoder 将输入编码为固定大小的向量的过程实际上是一个“信息有损的压缩过程”,如果信息量越大,那么这个转化向量的过程对信息的损失就越大。
- 梯度消失或者爆炸:因为传统 Encoder-Decoder 是采用 RNN 作为编码器和解码器的,所以自然,RNN 存在的梯度消失和梯度爆炸问题也是不可避免的。
- 并行效果差:因为每一时刻都依赖于前一时刻的输出。
第 5 节 · 为什么说 RNN 模型没有体现「注意力」?
其实从 4.7 就可以看出来,传统的 Encoder-Decoder 对于长序列的处理能力是很差的,因为不管序列多长,在经过编码器之后,都会压缩成固定尺寸的上下文向量(context vector),在这个压缩编码的过程中,很多长序列的信息就会丢失,导致后续解码部分也没办法获得全部的长序列信息。
举个简单的例子,如果长序列信息类似于山洞里的宝库,这时候一个盗贼进入了山洞,他只有一个箱子可用于搬运且只能搬运一次的话,可能是没办法将山洞内的财宝全部取走。想要实现利益最大化的话,自然是聚焦于高价值的宝物,也就是尽可能的用高价值的宝物填满箱子。
这就引出我们久有耳闻的 attention 机制。将注意力放到有价值的信息上面。
在传统的 Encoder-Decoder 模型里引入 attention 模块。
第 6 节 · 基于 Attention 机制的 Encoder-Decoder 模型
从Encoder-Decoder(Seq2Seq)理解Attention的本质 :这篇文章挺不错的。
从上面的 Encoder-Decoder 示意图,我们可以知道上下文向量(context vector)可以通过下式:
C
=
f
(
x
1
,
x
2
,
…
,
x
n
)
C = f(x_1, x_2, \dots ,x_n)
C=f(x1,x2,…,xn) 计算得到,而想要对于最后的输出结果
y
i
y_i
yi,我们可以通过:
y
k
=
g
(
C
,
y
1
,
y
2
,
…
,
y
k
−
1
)
y_k = g(C, y_1, y_2, \dots, y_{k-1})
yk=g(C,y1,y2,…,yk−1)但是我们也可以看出来,不管是计算
y
1
y_1
y1,
y
2
y_2
y2 还是
y
3
y_3
y3,我们都是通过
C
C
C 来计算的,也就是说 Encoder 中任意单词对于 Decoder 的输出的影响都是一样的,不存在注意力机制的。
如果加入了 attention 模块,我们就可以看出来,对于不同的输出
y
i
y_i
yi,我们有着不同的
C
i
C_i
Ci,则对应的输出:
y
k
=
g
(
C
k
,
y
1
,
y
2
,
…
,
y
k
−
1
)
y_k = g(C_k, y_1, y_2, \dots, y_{k-1})
yk=g(Ck,y1,y2,…,yk−1)
但是问题来了,这个
C
k
C_k
Ck 是怎么计算出来的?
也就是说,对于不同的 C k C_k Ck,attention 模块会给出不同的注意力向量 a k \mathbf{a^k} ak 来进行计算,上面的式子中, n n n 为输入序列的长度,而 k k k 为输出序列的长度。
a i k a_{ik} aik 就是 attention 注意力权重,表示第 i i i 个输入在第 k k k 个输出上分配的注意力。数值越高表示第 j j j 个输出受到第 i i i 个输入的影响越大。
如果将他们看成一个矩阵运算的话,则可以写成下面的形式: [ h 1 h 2 ⋯ h i h 1 h 2 ⋯ h i ⋮ ⋮ ⋱ ⋮ h 1 h 2 ⋯ h i ] ⋅ [ a 1 , 1 a 1 , 2 ⋯ a 1 , k a 2 , 1 a 1 , 2 ⋯ a 2 , k ⋮ ⋮ ⋱ ⋮ a i , 1 a i , 2 ⋯ a i , k ] = [ C 1 , C 2 , ⋯ , C k ] \begin{bmatrix} h_1 & h_2 & \cdots & h_i \\ h_1 & h_2 & \cdots & h_i \\ \vdots & \vdots & \ddots & \vdots \\ h_1 & h_2 & \cdots & h_i \end{bmatrix} \cdot \begin{bmatrix} a_{1,1} & a_{1,2} & \cdots & a_{1,k}\\ a_{2,1} & a_{1,2} & \cdots & a_{2,k}\\ \vdots & \vdots & \ddots & \vdots\\ a_{i,1} & a_{i,2} & \cdots & a_{i,k} \end{bmatrix} = [C_1, C_2, \cdots , C_k] h1h1⋮h1h2h2⋮h2⋯⋯⋱⋯hihi⋮hi ⋅ a1,1a2,1⋮ai,1a1,2a1,2⋮ai,2⋯⋯⋱⋯a1,ka2,k⋮ai,k =[C1,C2,⋯,Ck]其中等式左边第一个向量的维度为 k × i k \times i k×i,第二个向量 attention 权重矩阵的维度为 i × k i \times k i×k,最后获得的上下文权重向量的维度为 1 × k 1 \times k 1×k。
但是问题又来了,
a
i
k
a_{ik}
aik 是怎么计算获得的?
在 attention 模块中,注意力评价值
e
i
k
e_{ik}
eik 是由两部分组成的:
- 第 i i i 个输入(当前时刻输入)的隐藏层输出 h i h_i hi
- 第 k − 1 k-1 k−1 个输出(前一时刻输出)的隐藏层输出 s k − 1 s_{k-1} sk−1
也就是说这个注意力的值其实既和当前输入有关,也和前一时刻的输出相关。
公式可以写成: e i k = α ( h i , s k − 1 ) e_{ik} = \alpha(h_i, s_{k-1}) eik=α(hi,sk−1)我们这里的 attention 机制是 soft attention,所以和 softmax 类似,我们要对上面这个注意力评价值进行加权平均: a i k = exp ( e i k ) ∑ i = 1 n exp ( e i k ) a_{ik} = \frac{\exp(e_{ik})}{\sum_{i=1}^n \exp(e_{ik})} aik=∑i=1nexp(eik)exp(eik)其中:
- ∑ i = 1 n exp ( e i k ) \sum_{i=1}^n \exp(e_{ik}) ∑i=1nexp(eik):计算了每个时刻输入和前一时刻的输出的评价值之和
- exp ( e i k ) \exp(e_{ik}) exp(eik):表示当前时刻输入和前一时刻输出的评价值
感觉有种当前时刻输入,在总输入中的贡献占比的感觉。
为什么要使用 exp 来计算 attention 权重呢?
最后我们列出计算输出 y i y_i yi 的完整流程:
- 已知所有的输入 h i h_i hi 和 s k − 1 s_{k-1} sk−1,计算 e i k = α ( h i , s k − 1 ) e_{ik} = \alpha(h_i, s_{k-1}) eik=α(hi,sk−1)
- 已知 e i k e_{ik} eik,计算 a i k = exp ( e i k ) / ∑ i = 1 n exp ( e i k ) a_{ik} = \exp(e_{ik}) / \sum_{i=1}^n \exp(e_{ik}) aik=exp(eik)/∑i=1nexp(eik)
- 已知所有的输入 h i h_i hi 和 a i k a_{ik} aik, 计算 C k = ∑ i = 1 n a i k h i C_k = \sum^n_{i=1} a_{ik}h_i Ck=∑i=1naikhi
- 已知 s k − 1 s_{k-1} sk−1, y k − 1 y_{k-1} yk−1 和 C k C_{k} Ck,计算当前时刻输出的隐藏状态 s k = f ( s k − 1 , y k − 1 , C k ) s_{k} = f(s_{k-1}, y_{k-1}, C_{k}) sk=f(sk−1,yk−1,Ck)
- 已知 s k s_k sk, y k − 1 y_{k-1} yk−1 和 C k C_{k} Ck,计算当前时刻输出 y k = g ( y k − 1 , s k , C k ) y_k = g(y_{k-1}, s_k, C_k) yk=g(yk−1,sk,Ck)
- 有了 s k s_k sk 和 y k y_k yk,又可以继续下一时刻的循环了
第 7 节 · 自注意力机制(Self-Attention)
下面的章节就正式的进入到 transformer 的邻域了。
参考文章:The Illustrated Transformer
这是我参考文章内的图片自己做的一个示意图。通过这个示意图,我来大概地讲解一下 self attention 的计算流程:
- 首先一句话中的单词经过 embedding 之后,每个单词都会生成对应的输入向量 x i \mathbf{x_i} xi。
- 然后 X \mathbf{X} X 通过和对应权重 W Q \mathbf{W^Q} WQ, W K \mathbf{W^K} WK 和 W V \mathbf{W^V} WV 进行矩阵乘法,获得 Q \mathbf{Q} Q, K \mathbf{K} K 和 V \mathbf{V} V。
- 通过计算 A = Softmax ( Q ⋅ K T / d k ) \mathbf{A} = \text{Softmax}(\mathbf{Q \cdot K^T /\sqrt{d_k}}) A=Softmax(Q⋅KT/dk) 来获得自注意力权重矩阵。
- 最后将自注意力权重矩阵 A \mathbf{A} A 与 value 矩阵 V \mathbf{V} V 进行矩阵乘法,就可以获得 Z \mathbf{Z} Z。
为什么要除以 d k \sqrt{d_k} dk ?
d k d_k dk 表示的是 key 矩阵的中 k i k_i ki 的维度,除以 d k \sqrt{d_k} dk 是为了:
- 防止 Q ⋅ K T \mathbf{Q \cdot K^T} Q⋅KT 的值过大,导致 softmax 计算的时候出现上溢出(overflow)。
- 使得 Q ⋅ K T \mathbf{Q \cdot K^T} Q⋅KT 的结果满足期望为 0,方差为 1 的分布。
为什么要计算 Q ⋅ K T \mathbf{Q \cdot K^T} Q⋅KT ?
计算 Q ⋅ K T \mathbf{Q \cdot K^T} Q⋅KT 时,从几何的角度来说,相当于对内部的向量 q \mathbf{q} q 和 k \mathbf{k} k 进行点积操作,来计算两个向量的相似度。
q ⋅ k = ∥ q ∥ ∥ k ∥ ⋅ cos θ \mathbf{q \cdot k} =\left \| \mathbf{q} \right \| \left \| \mathbf{k} \right \| \cdot \cos \theta q⋅k=∥q∥∥k∥⋅cosθ
- 当两个向量垂直的时候, θ = 9 0 ∘ \theta = 90^{\circ} θ=90∘,就是点积为 0,表示这两个向量没有相似的地方。
- 当两个向量平行的时候,两个向量的点积即为 ∥ q ∥ ∥ k ∥ \left \| \mathbf{q} \right \| \left \| \mathbf{k} \right \| ∥q∥∥k∥
- 当两个向量存在夹角 θ \theta θ,两个向量的点积就如上面公式一样。点积就是 q \mathbf{q} q 在 k \mathbf{k} k 上投影的模。
这里 self attention 的 Z \mathbf{Z} Z 和 soft attention 中的 C \mathbf{C} C 是等效的。
第 8 节 · 多头注意力(Multi-Head attention)
多头注意力,其实相当于多次求 self attention,上面的 self attention 的产物是一个 Z \mathbf{Z} Z 矩阵,在多头注意力里,我们通过多组的 W Q \mathbf{W^Q} WQ, W K \mathbf{W^K} WK 和 W V \mathbf{W^V} WV,来获得多组的 Z \mathbf{Z} Z。
我们将上面 self attention 中计算 Z \mathbf{Z} Z 的过程简化一下,直接得到对应的 Z 0 , Z 1 , ⋯ , Z n \mathbf{Z_0, Z_1, \cdots, Z_n} Z0,Z1,⋯,Zn。然后将其组合起来,与一个新设置的权重矩阵 W o \mathbf{W^o} Wo 相乘,获得最终的 Z \mathbf{Z} Z。
多头注意力中的每个头都能关注不同的信息。
第 9 节 · 退化现象、残差网络与 Short-Cut
ResNet 残差网络在 CV 中也经常用到,所及就不详细解说了。
第 10 节 · Transformer 的位置编码(Positional Embedding)
在计算 attention 的时候,我们只是关注词与词之间的相似关系,但是却忽略了位置关系。
在 Transformer 中,为了解决这个问题,新增了位置编码(Positional Encoding)。
大致的流程如上图所示,就是在 embedding 和计算
Q
\mathbf{Q}
Q,
K
\mathbf{K}
K 和
V
\mathbf{V}
V 之间加入一个位置编码的流程,来将每个词或者说 token 的位置信息加入到输入向量
x
\mathbf{x}
x 中。
矩阵 P E \mathbf{PE} PE 中的向量 p e \mathbf{pe} pe 内的元素具体是怎么计算的呢? p e t , i = { sin ( 1 1000 0 2 i d x ⋅ t ) if i = 2 k cos ( 1 1000 0 2 i d x ⋅ t ) if i = 2 k + 1 for k = 0 , 1 , 2 , ⋯ , d x 2 − 1 pe_{t,i} = \begin{cases} \sin(\frac{1}{10000^{\frac{2i}{d_x} }} \cdot t) & \text{ if } i = 2k \\ \cos(\frac{1}{10000^{\frac{2i}{d_x} }} \cdot t) & \text{ if } i= 2k + 1 \end{cases} \space \space \space \space \space \space \space \space \text{for} \space \space k = 0, 1, 2, \cdots, \frac{d_x}{2}-1 pet,i=⎩ ⎨ ⎧sin(10000dx2i1⋅t)cos(10000dx2i1⋅t) if i=2k if i=2k+1 for k=0,1,2,⋯,2dx−1其中:
- d x d_x dx 是向量 x \mathbf{x} x 的维度。
- k k k 是 0 0 0 到 d x / 2 − 1 d_x/2-1 dx/2−1 的整数
如果 i i i 是偶数的话,就是计算 sin \sin sin,如果 i i i 是奇数的话就是计算 cos \cos cos。一个完整的 p e \mathbf{pe} pe 向量可以写成下面形式: p e t = [ p e t , 0 , p e t , 1 , ⋯ , p e t , d x ] \mathbf{pe}_t = [pe_{t,0}, pe_{t,1}, \cdots, pe_{t,d_x}] pet=[pet,0,pet,1,⋯,pet,dx]而一个完整的位置编码矩阵可以写成下面形式: P E = [ p e 0 p e 1 ⋮ p e t ] = [ p e 0 , 0 p e 0 , 1 ⋯ p e 0 , d x p e 1 , 0 p e 1 , 1 ⋯ p e 1 , d x ⋮ ⋮ ⋱ ⋮ p e t , 0 p e t , 1 ⋯ p e t , d x ] \mathbf{PE}=\begin{bmatrix} \mathbf{pe}_0 \\ \mathbf{pe}_1 \\ \vdots \\ \mathbf{pe}_t \end{bmatrix}=\begin{bmatrix} pe_{0,0} & pe_{0,1} & \cdots & pe_{0,d_x}\\ pe_{1,0} & pe_{1,1} & \cdots & pe_{1,d_x}\\ \vdots & \vdots & \ddots & \vdots\\ pe_{t,0} & pe_{t,1} & \cdots & pe_{t,d_x} \end{bmatrix} PE= pe0pe1⋮pet = pe0,0pe1,0⋮pet,0pe0,1pe1,1⋮pet,1⋯⋯⋱⋯pe0,dxpe1,dx⋮pet,dx
上面介绍的这种,是绝对编码中的三角式位置编码(Sinusoidal Positional Encoding),除此之外还有相对位置编码。
10.2、绝对位置编码
除了上面提到的三角式位置编码,还有下面几种绝对位置编码:
- 习得式位置编码:将位置编码矩阵作为可学习的超参数来进行训练,缺点是外推性比较差,推理时输入文本超出训练的最大长度,则无法处理。
- 循环式位置编码:将向量 x \mathbf{x} x 一个一个送入 RNN 中,RNN 中的模块是 Transformer,因为 RNN 暗含位置信息,所以就不需要进行额外的编码了,但是缺点就是 RNN 的并行性比较差。
- 相乘式位置编码:使用哈达玛德积(Hadamard product),也就是逐元素相乘来替代相加,也就是 x ⊙ p e x_ \odot pe x⊙pe 代替 x + p e x + pe x+pe 。
10.3、相对位置编码与其他位置编码
感觉暂时也不需要详细展开了,后续有时间的话再写吧。
第 11 节 · Transformer 的编码器 Encoder 和解码器 Decoder
11.1、Encoder 和 Decoder 的图示结构
沿用之前的参数符号,上图是 Transformer 的 Encoder 示意图,可以看出来:
- 输入是经过位置编码的 X p e \mathbf{X}_{pe} Xpe
- 经过第一个多头注意力模块(其中 MHA \text{MHA} MHA 是 Multi-Head Attention 的缩写)之后,输出的 Z \mathbf{Z} Z
- 然后经过 Add & Norm 层,将 X p e \mathbf{X}_{pe} Xpe 与 Z \mathbf{Z} Z 相加之后进行层归一化(LayerNorm),输出 X out 1 \mathbf{X}_{\text{out}1} Xout1
- 然后输入 Feed Forward 层,这是由两个全连接层组成的,第一个全连接层的激活函数是 ReLU,第二个全连接层没有激活函数。得到我们的 F \mathbf{F} F
- 最后再经过一次 Add & Norm 层,进行层归一化操作,得到 Encoder 的最终输出 X out 2 \mathbf{X}_{\text{out}2} Xout2
其中可以看到 Encoder 中存在两条 short-cut。
第一个 masked multi-head attention
接下来看看 Decoder 的结构,除了一个新的 masked multi-head attention 模块,其他模块都和 Encoder 的类似,所以具体的计算公式就不标注出来了。
我们说一下 masked multi-head attention 模块,这个 masked 的对象是什么,具体有什么用?
我们这里以单个注意力模块,也就是 self attention 来举例子,其实 masked 的操作主要是加在注意力权值矩阵进行 softmax 操作之前。
这是我从 self attention 示意图中抽取的注意力权值矩阵计算部分,左边是普通的计算注意力权值矩阵,在求解
A
′
\mathbf{A'}
A′ 之后,直接对其进行 softmax 操作就行了。
而右边则是包含 mask 操作的,在进行 softmax 操作之前,先进行一个 mask 操作,防止后续标签进行对前面的预测进行影响,因为我们知道 Transformer 中 Decoder 也会输入一次输入序列,但是和 Encoder 部分不同的是,会对输入数列进行一个右移(shifted right)的操作。类似 Encoder 如果输入 [i am a student],那么 Decoder 部分,则会输入 [ I am a student],多了一个起始符,这个起始符就是用于预测 “I” 的。
第二个 multi-head attention
这个注意力模块也可以叫做 cross attention 模块,或者是 encoder-decoder attention 模块
第二个多头注意力模块,其实我们注意到,有两条线是来自于 Encoder,我们知道在计算 self attention 的时候,首先我们要计算 Q \mathbf{Q} Q, K \mathbf{K} K 和 V \mathbf{V} V 三个矩阵,一般来说,这三个矩阵都是一个输入和对应的权重矩阵计算获得的。
但是在 Decoder 的第二个多头注意力模块中,其中 K \mathbf{K} K 和 V \mathbf{V} V 是由 Encoder 的输出 X out 2 \mathbf{X}_{\text{out}2} Xout2 计算获得的,而 Q \mathbf{Q} Q 是由 Decoder 的第一个 masked multi-head attention 模块的输出计算获得的。
11.2、Decoder 的第一个输出结果
我理解为 Transformer 是由很多个 Decoder block 组成的,但是第一个 Decoder block 和后续的 Decoder block 有一点细微的差别
假设 Transformer 一共有
N
N
N 个 Decoder block,第一个 Decoder block 是不含 masked multi-head attention 模块的。后续的
N
−
1
N-1
N−1 个 Decoder block 才是我们上面分析的正常的 Decoder block,这是为什么?
为什么 transformer的第一个 decoder blcok 不需要经过 masked multi-head attention 模块?
在 Transformer 模型中,第一个 Decoder block 的出结果是基于 Encoder 的输出和 Decoder 的初始输入(通常是起始符号,如)生成的。这个过程不需要经过 Masked Multi-Head Attention Layer,因为即便是经过了多头注意力模块,
11.3、Decoder 后续的所有输出
没看懂
11.4、Decoder 之后的 Linear 和 Softmax
这个部分其实和 cv 中的分类最后是一样的,只是 transformer 中的类别是词汇表。
第 12 节 · Transformer 模型整体
- 首先输入数据生成词的嵌入式向量表示(Embedding),生成位置编码(Positional Encoding,简称 PE)。进入
- Encoders 部分。先进入多头注意力层(Multi-Head Attention),是自注意力处理,然后进入全连接层(又叫前馈神经网络层),每层都有 ResNet、Add & Norm。
- 每一个Encoder 的输入,都来自前一个 Encoder 的输出,但是第一个 Encoder 的输入就是 Embedding + PE。
- 进入 Decoders 部分。先进入第一个多头注意力层(是 Masked 自注意力层),再进入第二个多头注意力层(是 Encoder-Decoder 注意力层),每层都有 ResNet、Add & Norm。
- 每一个 Decoder 都有两部分输入。
- Decoder 的第一层(Maksed 多头自注意力层)的输入,都来自前一个 Decoder 的输出,但是第一个 Decoder 是不经过第一层的(因为经过算出来也是 0)
- Decoder 的第二层(Encoder-Decoder 注意力层)的输入,Q 都来自该 Decoder 的第一层,且每个 Decoder 的这一层的 K、V 都是一样的,均来自最后一个 Encoder。* 最后经过 Linear、Softmax 归一化。
后面的部分基本都是实际训练部分了。
参考文章:举个例子讲下transformer的输入输出细节及其他
但是感觉 transformer decoder 的输入输出维度还是不是很清晰
- 输入输出的维度是多少?
- 上一个 decoder 的输出是怎么整合到下一个 decoder 的输入的
- 训练的时候输入的是 ground truth,但是推理的时候 decoder 的输入维度是多少?
- transformer 的并行训练体现在哪里?