【从零开始的机器学习之旅】09-Transformer
从零开始的机器学习之旅
-Transformer
一、seq2seq
1.含义
输入一个序列,机器输出另一个序列,输出序列长度由机器决定。
文本翻译:文本至文本; 语音识别:语音至文本; 语音合成:文本至语音; 聊天机器人:语音至语音。
2.应用
① 自然语言处理(NLP问题),不过seq2seq有时候不一定是最佳的解决方法。
② 应用于Seq2seq for Syntactic Parsing句法分析(文法剖析),例如,给机器一段文字,Deep learning is very powerful,机器要做的事情是产生一个文法的剖析树 。
输出结果(剖析树)告诉我们,deep 加 learning 合起来是一个名词短语,very 加 powerful 合起来是一个形容词短语,形容词短语加 is 以后会变成一个动词短语,动词短语加名词片语合起来是一个句子
文法剖析要做的事情就是产生这样子的一个 Syntactic tree,所以在用 deep learning 解决 文法剖析的任务里面,输入是一段文字(一个Sequence),输出是一个树状的结构,(可以把他看作是一个Sequence,一个代表句法分析树的序列)
③ 应用于 multi-label classification(多标签分类问题:同一个对象可以属于多个class)
区分:
- multi-class classification:为样本从数个 class 中选择某一个 class(多对一)
- multi-label classification:同一个样本可以属于多个 class (一对多)
难点:每篇文章对应几个 class 不好确定 ⇒ seq2seq 决定要输出几个
④ Object Detection 物体检测
3. Seq2seq 实现方式
seq2seq’s model = Encder(编码器) + Decoder(解码器)
这两部分可以使用RNN或transformer实现,seq2seq主要是为了解决输入和输出长度不确定的情况。
Encoder:将输入(文字、语音、视频等)编码为单个向量,这个向量可以看成是全部输入的 抽象表示。
Decoder:接受 encoder 输出的向量,逐步解码,一次输出一个结果,每次输出会影响下一次的输出,开头加入
二、Encoder & Decoder
1.Encoder
可以使用:Self-attention,RNN,CNN
我们来仔细解释一下这个encoder:
A、encoder 就是通过多层 block(模块),将输入转换成向量。每一个 block 都包含若干层( self-attention 和 fully connect 等网络结构 ),每个 block 输入一排向量,输出相同数量的一排向量。
B、 block 的内部细节构成如下(在 input 送入 block 之前,需先进行 positional encoding,这个知识点在 self - attention 中有提过)。
C 、 它考虑所有输入向量后的输出向量,其中 b 是原来的 input 向量,经过残差网络(residual connection:把 a vector 加上它的 b input vector 作为 output )和标准化(Layer Norm)后,送到全连接神经网络 FC ,由于在 FC network 中也有 residual 的架构,因此需要再经过一组 残差网络 + 标准化 后得到输出。(注意:这里的标准化是 layer normalization 而不是 batch normalization)。这个输出才是 residual network 里一个 block 的输出。
batch normalization:对 不同的 example 不同 feature 的 同一个 dimention 去计算平均值 mean 和标准差 standard deviation。
layer normalization:对 同一个 example 同一个 feature的 不同 dimention 去计算平均值 mean 和标准差 standard deviation。
2. Decoder
decoder主要有两种:AT(autoregressive自回归模型)与 NAT(non-autoregressive非自回归),Decoder 要做的事情:产生最终的输出结果
2.1 Autoregressive(AT)
向 Decoder 输入 Encoder 产生的向量
在 Decoder 可能产生的文字库里多加一个标识字符 BEGIN ,它代表 “ Decoder 开始识别” 来提醒机器(BOS: begin of sentence)
NLP 的问题中,每一个 Token 用一个 One-Hot 的 Vector 来表示,其中正确的类别标识是 1,其他都是 0,其中 BEGIN 也是用 One-Hot Vector 来表示
- 经过 softmax 之后,Decoder 会输出一个和 输入的 Vocabulary Size 一样的向量长度的 向量结果。对比已知文字库,找到相似度最高的字符就是最终输出的字符。(这里“机”字 就是这个 Decoder 的第一个输出)
Vocabulary Size:取决于你输出的单位。比如输出中文,则size是中文方块字的数目。
- 再把上一步的输出当做下一个的输入。(在本例中,第二次 Decoder 把 “机” 当做是 Decoder 的 Input,在上一步 “机” 是 Decoder 的输出结果)经过一系列相同的操作后我们会得到第二次 Decoder 的输出,再作为第三次的输入,继续输出后续的文字,以此类推……
让我们看看Decoder的细节:
Decoder的细节: 点击查看更多
对比一下encoder和decoder:

如果我们吧decoder中间那块盖起来,我们发现好像二者没有那么大的区别。

不过decoder多了一个masked。
什么意思呢?
让我们看看原来的Self-attention:



Why masked?
Consider how does decoder work
由于解码器采用自回归auto-regressive,即 在过去时刻的输出作为当前时刻的输入,也就是说在预测时无法看到之后的输入输出,但是在注意力机制当中,可以看到完整的输入(每一个词都要和其他词做点积,计算相关性),为了避免这种情况的发生,在解码器训练时,在预测t时刻的输出时,不应该能看到t时刻以后的输入。做法是:采用带掩码的Masked注意力机制,从而保证在t时刻无法看到t时刻以后的输入,保证训练和预测时的行为一致性。

自注意力机制明确的知道这句话有多少个单词,并且一次性给足,而掩码是分批次给,最后一次才给足。
Masked(掩码) Self-Attention–>在自注意力模型上面做了改进
为什么要做这个改进:生成模型,生成单词,一个一个生成的
当我们做生成任务的时候,我们也想对生成的这个单词做注意力计算,但是,生成的句子是一个一个单词生成的
I have a dream
- I 第一次注意力计算,只有 I
- I have 第二次,只有 I 和 have
- I have a
- I have a dream
- I have a dream
掩码自注意力机制应运而生
掩码后 1
掩码后2
- 机器自己决定输出的长度:一个特别的标识符 “END” 代表工作结束

缺点:如果Decoder 看到错误的输入,让 Decoder 产生错误的输出并被代入到下一步 Decoder 工作的输入中,会会造成 Error Propagation(一步错,步步错)⇒ 解决:Teacher Forcing技术(但是测试的时候 显然没有正确答案可以给 Decoder 看)

由于 Teacher Forcing的存在,训练跟测试的情景不一致。Decoder 在训练的时候永远只看过正确的东西(也就是说在训练的时候给decoder看到正确的答案),但是在测试的时候,仍然会导致一步错、步步错(测试的时候没有正确答案呀,它仍然有可能出错)。
解决:给 Decoder 的输入加一些错误的东西 ⇒ Scheduled Sampling(计划采样)(但是也会一定程度损害平行化的能力)
总结: 除了中间的部分,Encoder 跟 Decoder 并没有太大的差别。最后我们可以再做一个 Softmax,可以通过计算输出的概率分布与 Ground Truth 之间的 交叉熵(Cross Entropy)并求梯度实现优化,交叉熵的值越小越好。
2.2 Non-autoregressive(NAT)
AT v.s. NAT

① 特点:NAT 不是依次有序进行 decoder 工作并挨个输出,而是一次性在输入时赋予 整个句子 一整排的 “BEGIN” 标识,把整个句子的 decoder 结果一次性都输出
② 思路:如何确定BEGIN的个数:
- 另外训练一个 Classifier,输入 Encoder 的 Input vector,输出是一个数字(代表 Decoder 应该要输出的长度)
- 给它若干个 BEGIN 的 Token,比如输出句子的最大长度不超过 300,就给 input 300 个 BEGIN token,然后就会相应地一次性输出 300 个字(遇到有输出 END 时表示这个句子输出结束),但是可能会比较耗费内存空间
③ 好处:
- 并行化。NAT 的 Decoder 不管 input 句子的长度大小,都是一次性输出完整的句子结果,所以在执行速度上 NAT 的 Decoder 比 AT 的 Decoder 要快
- 容易控制输出长度。
④ 应用:
常用在语音合成,例如:利用其中一个 决定 NAT 的 Decoder 应该输出的长度的 Classifier,我们可以通过设置这个输出长度的大小以调整语音的速度。(如果要让输出的语音讲快一点,就把 Classifier 输出的长度数值 除以 N,它讲话速度就变成 N 倍速;同理,如果想要合成的语音变为慢速,就把 Classifier 输出的长度数值乘 N 倍)
⑤ 缺点:虽然 NAT 看起来有很多优点(尤其是并行化),但是 NAT 的 Decoder 实际上 Performance 往往都不如 AT 的 Decoder。为什么NAT 没有 AT 实际效果好? ⇒ Multi-Modality
现在我们就要来讲刚刚Decoder被遮起来的部分啦!

Cross attention

三、Training过程
以“我爱你”到“I am a student”为例,在训练过程中,encoder输入的是待翻译句子“我有一个梦想”,得到k,v;decoder输入的是“S I am a student”(S位起始符);最终计算loss的label是“I am a student E”。
生成一个词:
生成所有词:
Transformer完整框架

四、Q & A
Q1:为什么 Decoder 需要做 Mask
机器翻译:源语句(我爱中国),目标语句(I love China)
为了解决训练阶段和测试阶段的 gap(不匹配)
训练阶段:解码器会有输入,这个输入是目标语句,就是 I love China,通过已经生成的词,去让解码器更好的生成(每一次都会把所有信息告诉解码器)
测试阶段:解码器也会有输入,但是此时,测试的时候是不知道目标语句是什么的,这个时候,你每生成一个词,就会有多一个词放入目标语句中,每次生成的时候,都是已经生成的词(测试阶段只会把已经生成的词告诉解码器)
为了匹配,为了解决这个 gap,masked Self-Attention 就登场了,我在训练阶段,我就做一个 masked,当你生成第一个词,我啥也不告诉你,当你生成第二个词,我告诉第一个词
Q2:为什么 Encoder 给予 Decoders 的是 K、V 矩阵
Q来源解码器,K=V来源于编码器
Q是查询变量,Q 是已经生成的词
K=V 是源语句
当我们生成这个词的时候,通过已经生成的词和源语句做自注意力,就是确定源语句中哪些词对接下来的词的生成更有作用,首先他就能找到当前生成词
我爱中国
通过部分(生成的词)去全部(源语句)的里面挑重点
Q 是源语句,K,V 是已经生成的词,源语句去已经生成的词里找重点 ,找信息,已经生成的词里面压根就没有下一个词
解决了以前的 seq2seq 框架的问题
lstm 做编码器(得到词向量 C),再用 lstm 做解码器做生成
用这种方法去生成词,每一次生成词,都是通过 C 的全部信息去生成
很多信息对于当前生成词而言都是没有意义的
用 Pytorch 去构建 Transformer 的源码。
- Title: 【从零开始的机器学习之旅】09-Transformer
- Author: Nannan
- Created at : 2024-07-09 22:30:00
- Updated at : 2024-09-29 23:21:38
- Link: https://redefine.ohevan.com/2024/07/09/09-Transformer/
- License: This work is licensed under CC BY-NC-SA 4.0.