现在我来做transformer的学习笔记!
回顾:
先来回顾:transformer是一个seq2seq的模型。input是一个sequence;output也是一个sequence,长度由机器决定。应用例子有:语音识别、机器翻译、语音翻译、LLM、文法剖析。
其中,类比算法竞赛的知识点,文法剖析要将结果作为先序遍历的树 来表示,才能应用seq2seq模型表示。不过我忘了算法竞赛的知识点啦,所以,我要来回忆一下先序遍历:
先序遍历(Pre-order Traversal):
根 → 左子树 → 右子树
此外,seq2seq还可以作multi-label分类(将多个label视为一个sequence),目标检测。
seq2seq的模型主要由input、encoder、decoder、output四个部分组成。现在,我来学习transformer。
1. Encoder
先看encoder。Encoder 的作用是将输入序列(input sequence)转化成一个包含其语义信息的隐藏表示(hidden representation) ,以便 Decoder 使用这个表示生成输出。不同的seq2seq模型里,它可以 是一个 RNN 或者 CNN,也可以是这里我们正在学习的 Transformer Encoder。
Transformer encoder用的就是self attention。现在来解释Transformer Encoder的架构:
看,这个encoder里面会分成很多的block,每一个block都是输入一排向量、输出一排向量,输出的向量再进入下一个block。
每一个block在做的事情,是好几个layer在做的事情。具体一点,一个block是这样的:先做一个self-attention,考虑整个sequence的资讯,然后丢入FC层,得到这个block的输出。
但事实上,在transformer里面,做的事情更加复杂,它加入了一个设计,不仅输出self-attention层的vector,还会把它加上input vector (回忆一下我之前学的ResNet,这实际上就是residual connection) 。得到residual结果以后,进行normalization。注意 ,用的不是batch normalization,而是layer normalization 。如何做的?是对一个向量,也就是同一个feature、同一个example,求解它的mean和standard deviation。batch normalization是对同一个dimension进行normalization,也就是feature不同、example不同、同一个dimension。具体过程如图:
均值方差归一化可以达到:中心化 数据(均值为 0),以及标准化 尺度(标准差为 1)。我询问ChatGPT为什么要这么做,它回答我:
🌟 核心目的:
让特征的数值“处于统一的尺度”,避免某些特征因为数值过大而主导模型学习。
📌 具体目的包括:
目的 说明 🚀 提升模型收敛速度 尤其对梯度下降类模型(如神经网络、逻辑回归)非常重要 📉 防止某些特征主导训练 特征值差异太大可能导致学习不平衡 🛠提高数值稳定性 避免数值太大或太小带来的精度问题 📊 更好地可视化 数据变得更可比、更直观
经过layer normalization以后,输出才会去作为FC层的输入。进一步,FC层也要进行一个residual残差,最后把residual再做一次layer normalization。
这样就完成了一个block。原论文的图像是这样的:
这个block会重复N次。
回过头来看,我们在input的地方也加了一个positional encoding。这在我的上一份笔记中有提到,它可以提供位置的信息。
此外,Bert用的也是transformer的encoder。
对于encoder的设计,有这样的讨论,比如,讨论layer normalization与residual的位置等等。
这样,就是transformer的encoder架构。接下来我开始学习transformer的decoder架构。
2. Decoder
transformer的decoder架构有两种,课程里花较多时间会介绍autoregressive的decoder(AT)。我们先不看decoder里面的具体架构,先从表面看看它对数据的处理。现在以语音识别为例,decoder的第一个输出是这么来的:
接下来,把“機”这个汉字再作为输入。现在decoder有两个输入,一个是begin,另一个是“機”,现在接着往后得到输出。
然而,这可能会有error propagation的问题。会不会把“器”识别为“气”之后,整个句子都坏掉了?这个问题在稍后讨论。
现在可以看看decoder的具体内容了。让我们看看transformer原文里,decoder的图片:
似乎除了中间的由encoder传入输入的多头注意力以外,与encoder没有太大不同。此外,要注意block里的最下面的多头注意力多了一个“masked”。现在来解释masked:
正常的self-attention,会浏览所有vector的信息。masked之后,只能考虑输出的编号以前的输入的信息。
再具体一点,以b2为例,就是
为什么要masked?因为本来输出就是从左到右一个一个产生的,只能考虑左侧的东西。
最后,decoder必须自己决定输出sequence的长度。如何知道停止?准备一个“END”符号即可,也就是
接下来,我简单学习了Non-autoregressive的decoder(NAT)。
对比一下刚刚学的AT:
3. Encoder 与 Decoder之间的Cross Attention
现在,我来学习encoder与decoder之间是怎么传递信息的,也就是原论文里的这个部分:
首先,根据输入的向量,encoder得到了一组向量。向masked的self-attention输入begin,得到了一个向量,把它乘上Wq,得到q。刚刚encoder得到的向量也乘相应的矩阵得到k1、k2、k3,用q去问询它们,得到α1、α2、α3,再给它们做个softmax与normalization,得到α1’、α2’、α3’,把它们与v1、v2、v3相乘并加起来,得到v。把v输入FC层,进行下一步操作。
这整个过程,就是Cross attention。可以看到,k、v来自encoder,q来自decoder的masked self-attention。
产生了第二个向量(图中的“機”)之后,再次进行同样的步骤,以此类推:
就会产生最终的结果。encoder有很多层,decoder也有很多层。它们的关系是这样的:decoder不管哪一层,都以encoder的最后一层输出作为输入(下图的图a)。当然,也可以不这样:
以上,就是整个transformer模型的构架。我们一共讨论了给予一个input sequence之后,模型是怎么经过encoder和decoder,最终得到一个output sequence的。现在,我要来学习模型的训练部分啦。
4. 训练
依然以语音识别为例。首先,人类听到“机器学习”,然后label出来“機”“器”“學”“習”四个汉字,独热表示一下,这样只有那个正确的汉字用1表示 。现在,给decoder一个begin和encoder送来的output,得到第一个输出的distribution概率分布(因为经过了softmax)。如果希望distribution与人标注的独热越接近越好,那么,loss就应该用它们俩的交叉熵 。最后,minimize这个cross entropy就可以啦。
刚刚只是第一个字。总体来看,是
特别要注意的是,训练的时候,decoder的输入是Ground Truth,是人类标注的正确答案 ,而不是它自己的输出。也就是,我们会给它看看某个输出要求之前的“正确答案”。
这就叫做Teacher Forcing 。
Teacher Forcing的情况下,decoder每次都根据正确答案生成后面的输出。但是,进行测试集输入的时候,可没有正确答案帮助decoder啊?这个问题的解决方式在后面说明 。现在,我要关注一下训练transformer这种 seq2seq model的一些注意事项。
5. Tips
1. copy mechanism
很多任务,decoder需要copy mechanism。例如,制作聊天AI时,人对AI说“你好呀,我是Palind。”AI就应该回复:
AI没有必要创造“Palind”这个词汇,也肯定没有从训练资料里见过这个词汇。因此,机器要做的是,学会“看到人类输入‘我是某某某’,就输出‘你好某某某’”,就是“复制”。此外,AI做文章摘要时,也需要这个copy能力,因为很多词汇是从原文章里复制过来的。
pointer network、copy network可以实现这个功能,我先放一放,以后再学习。
2. Guided Attention
由于DL是黑箱,很多时候有无法解释的错误。例如,TTS任务中,AI单独念一个很短的汉语字词时,有时会出现念不出第一个汉字的问题。
如何解决呢?我们可以让机器把输入的每一个东西都看一下。这个方法是guided attention,较为适合语音辨识、语音合成任务。
guided attention领导机器在做attention时,要有固定的方式。仍以语音合成为例子,读音时,肯定是先注意到左边,再注意到右边的(上侧的图),不能按随意的顺序注意(下侧的图)。
3. Beam Search
假设只有A、B两个tokens。回忆一下贪心算法,现在采用每次生成“概率最大”的那个token的策略,这就是Greedy Decoding。
然而,会不会有更好的路径呢?先选择一个教差的输出,但后期道路上可能更为匹配。如图:
但不可能去检查所有的路径啊。因此,采用beam search算法,找到分数较高的路径。然而,beam search有一定争议。这种算法可能会导致AI在生成文本时,反反复复地重复某句话。
4. BLEU Score
BLEU Score是一种评估的标准。它将完整生成的句子与正确句子相比较。然而,我们训练时,一直是在minimize交叉熵,这是否可以maximize BLEU Score?不一定。因此,挑选最好的model时,不一定是要挑选cross entropy最低的。
能不能把loss换为BLEU Score(的负数)?较为困难。因为BLEU Score很复杂,是不能做微分的。所以,李老师建议:
When you don’t know how to optimize, just use reinforcement learning!
(aka. “用RL硬train一發!”)
我还没有学习RL,看来得放在学习计划里了。
5. scheduled sampling
最后,我们讨论之前的问题:decoder在训练时,可以“看到标准答案”,但是在测试时,只能“看到它自己刚刚生成的结果”。由于decoder只看过正确的input,而从来没有看过错误的东西,因此,在测试时,decoder前面生成的结果只要有一个错,后面生成的内容不就一步错、步步错了吗?
有一个思考方向就是:给decoder的输入加上一些错误的东西,而不是一直给它正确的答案。这个方法是就scheduled sampling。这个方法可能会伤害到“transformer的平行化能力”。我没有听明白,而ChatGPT这样教我,解释得很清晰:
🎯 Scheduled Sampling 的做法:
在训练时,有一定概率把“前一个真实词”替换成“模型自己预测的词”,让模型逐渐学会在不完美输入下也能继续生成。
⚡ Transformer 的并行化能力
Transformer 的最大优势之一就是:
所有位置的 token 是同时处理的,不是一步一步来的!
比如在训练阶段,如果我们要训练一句话的所有输出,Transformer 可以一次性处理整个序列:
- 因为输入是一个完整的 embedding 序列(比如整句话的前 n 个词),不需要等前一个词的预测结果;
- 所以它能用 GPU 高效并行计算,非常快 ⚡。
💥 Scheduled Sampling 为什么会伤害并行化?
Scheduled Sampling 引入了随机性和依赖性:
当前时间步的输入词,可能来自模型前一步的输出,而这个输出又必须通过前向传播才能获得。
这会带来两个问题:
❌ 1)破坏“全部同时处理”的能力
- 如果你要生成长度为 10 的序列;
- 并且你用 Scheduled Sampling 的方式,每一步都可能使用模型预测的前一个 token;
- 那就意味着你必须一步一步走完,不能“并行计算所有 token”。
⛔ 换句话说:你不再能一次性喂给 Transformer 一整个输入序列并让它算出全部输出,必须每次预测一步,然后用这个结果作为下一步的输入。
❌ 2)导致训练效率大幅下降
- Transformer 的训练效率是靠“并行化整个 batch、整个序列”实现的;
- 如果你引入 Scheduled Sampling,就会退化成类似 RNN 的“逐步生成”过程,导致效率大大降低,GPU 吃力 🐢。
以上就是我对Attention Is All You Need 的学习笔记啦