图解 Transformer——功能概览
一、引言
随着大型语言模型如 的横空出世,我们进入了自然语言处理(NLP)的一个新纪元。在这个纪元中, 架构扮演着至关重要的角色。其独特之处不仅在于其技术上的突破,更在于它如何彻底改变了我们对语言模型潜力的理解。
是一种深度学习架构,它使用注意力来显著提高深度学习 NLP 翻译模型的性能,其首次在论文《 is all you need》中出现。其问世标志着从序列建模的传统方法(如长短期记忆网络和门控循环单元)转变到一个更加高效、更能捕捉复杂语言模式的新框架,它允许模型同时处理输入序列的所有元素,并捕捉它们之间的复杂关系。这种全面的注意力机制使得在处理长序列时,相比于其前辈们更加高效与准确。
的以上特点不仅提高了模型处理语言的能力,还极大增强了其学习复杂语言模式的能力。使得类 GPT 系列这样的模型,不仅能理解和生成自然语言,还能在多种任务上表现出色,如文本摘要、问答、翻译等。这种多功能性和灵活性的提升,为我们处理和理解自然语言提供了前所未有的可能性。
本文来自于 2023 年初翻译的 Ketan Doshi 博客中关于 的系列文章。作者在系列文章中,介绍了 的基本知识,架构,及其内部工作方式,并深入剖析了 内部的细节。
系列文章共有四篇,本文为第一篇,主要从整体上介绍了 的整体架构,工作过程。
二、何为 ?
架构擅长处理文本数据,这些数据本身是有顺序的。它们将一个文本序列作为输入,并产生另一个文本序列作为输出。例如,将一个输入的英语句子翻译成西班牙语。
的核心部分,包含一个编码器层和解码器层的堆栈。为了避免混淆,我们把单个层称为编码器或解码器,并使用编码器堆栈或解码器堆栈分别表示一组编码器与一组解码器。(原文为 stack 和 stack)。
在编码器堆栈和解码器堆栈之前,都有对应的嵌入层。而在解码器堆栈后,有一个输出层来生成最终的输出。
编码器堆栈中的每个编码器的结构相同。解码器堆栈亦然。其各自结构如下:
编码器:一般有两个子层:包含自注意力层 self-,用于计算序列中不同词之间的关系;同时包含一个前馈层 feed-。
解码器:一般有三个子层:包含自注意力层self-,前馈层 feed-,编码器-解码器注意力层 - self 。
每个编码器和解码器都有独属于本层的一组权重。
注意,编码器与解码器的自注意力层self-、前馈层feed-,以及解码器中的编码器-解码器注意力层- 均有残差连接以及正则化层。
基于 的变体有许多。一些 架构甚至没有 结构,而仅仅依赖 。
三、 在做什么?
的突破性表现关键在于其对注意力的使用。
在处理一个单词时,注意力使模型能够关注输入中与该单词密切相关的其他单词。
例如,在以下的英文句子中,ball 与 blue 、hold 密切相关。另一方面,boy 与 blue 没有关系。
通过将输入序列中的每个词与其他词关联起来(同一序列中),形成 self- 机制。
考虑以下两个句子:
第一个句子中,单词 'it' 指'cat’;第二个句子中,'it' 指 'milk'。当模型处理 'it'这个词时,self- 给了模型更多关于 'it' 意义的信息,这样就能把 'it '与正确的词联系起来。
为了使模型能够处理有关于句子意图和语义的更多细微差别, 对每个单词都进行注意力打分。
在处理 'it '这个词时,第一个分数突出 'cat',而第二个分数突出 ''。因此,当模型解码'it'这个词时,即把它翻译成另一种语言的单词时,将会把 'cat' 和 '' 某些语义方面的性质纳入到目标语言中。
四、 训练过程
的训练和推理有一些细微差别。
首先来看训练。每一条训练数据都包括两部分内容:
输入序列,或称为“源序列”(例如对于一个翻译问题,“You are ” 是一个输入序列)
输出序列,或称为“目标序列(上述的翻译问题 “De nada” 即为“You are ” 的西班牙语翻译,为输出序列)
而 训练的目标就是,通过对训练数据中源序列与目标序列之间规律的学习,在测试或实际的任务中,给定源序列,生成目标序列。
如上图所示,在训练过程中,模型对数据的处理过程如下,大体可分为 6 个步骤:
在送入第一个编码器之前,输入序列 () 首先被转换为嵌入(同时带有位置编码),产生词嵌入表示(),之后送入第一个编码器。
由各编码器组成的编码器堆栈按照顺序对第一步中的输出进行处理,产生输入序列的编码表示()。
在右侧的解码器堆栈中,目标序列首先加一个句首标记,被转换成嵌入(带位置编码),产生词嵌入表示(),之后送入第一个解码器。
由各解码器组成的解码器堆栈,将第三步的词嵌入表示(),与编码器堆栈的编码表示()一起处理,产生目标序列的解码表示()。
输出层将其转换为词概率和最终的输出序列()。
损失函数将这个输出序列()与训练数据中的目标序列()进行比较。这个损失被用来产生梯度,在反向传播过程中训练模型。
五、 推理过程
在推理过程中,我们只有输入序列,而没有目标序列作为输入传递给解码器。 推理的目标是仅通过输入序列产生目标序列。
因此,与 模型类似,我们在一个时间步的完整循环中生成当前时间步的输出,并在下一个时间段将前一个时间段的输出序列传给解码器作为其输入,直到我们遇到句末标记。
但与 模型的不同之处在于,在每个时间步,我们输入直到当前时间步所产生的整个输出序列,而不是只输入上一个时间步产生的词(类似输入序列长度可变的自回归模型)。
非常重要,把原文粘过来:The from the model is that, at each , we re-feed the thus far, than just the last word.
推理过程中的数据流转如下:
第一步与训练过程相同:输入序列 () 首先被转换为嵌入(带有位置编码),产生词嵌入表示(),之后送入第一个编码器。
第二步也与训练过程相同:由各编码器组成的编码器堆栈按照顺序对第一步中的输出进行处理,产生输入序列的编码表示()。
从第三步开始一切变得不一样了:在第一个时间步,使用一个只有句首符号的空序列来代替训练过程中使用的目标序列。空序列转换为嵌入带有位置编码的嵌入(),并被送入解码器堆栈中的第一个解码器。
解码器堆栈将第三步的空序列嵌入表示(),与编码器堆栈的编码表示()一起处理,产生目标序列第一个词的编码表示()。
输出层将其()转换为词概率和第一个目标单词()。
将这一步产生的目标单词填入解码器输入的序列中的第二个时间步位置。在第二个时间步,解码器输入序列包含句首符号产生的 token 和第一个时间步产生的目标单词。
回到第3个步骤,与之前一样,将新的解码器序列输入模型。然后取输出的第二个词并将其附加到解码器序列中。重复这个步骤,直到它预测出一个句末标记。需要明确的是,由于编码器序列在每次迭代中都不会改变,我们不必每次都重复第1和第2步。
六、
训练时向解码器输入整个目标序列的方法被称为 。
训练时,我们本可以使用与推理时相同的方法。即在一个时间步运行 ,从输出序列中取出最后一个词,将其附加到解码器的输入中,并将其送入解码器进行下一次迭代。最后,当预测到句末标记时,Loss 函数将比较生成的输出序列和目标序列,以训练网络。
但这种训练机制不仅会导致训练时间更长,而且还会增加模型训练难度:若模型预测的第一个词错误,则会根据第一个错误的预测词来预测第二个词,以此类推。
相反,通过向解码器提供目标序列,实际上是给了一个提示。即使第一个词预测错误,在下一时间步,它也可以用正确的第一个词来预测第二个词,避免了错误的持续累加。
此外,这种机制保证了 在训练阶段并行地输出所有的词,而不需要循环,这大大加快了训练速度。
七、 应用场景
的用途非常广泛,可用于大多数NLP任务,如语言模型和文本分类。它们经常被用于 的模型,如机器翻译、文本总结、问题回答、命名实体识别和语音识别等应用。
对于不同的问题,有不同的 架构。基本的编码器层被用作这些架构的通用构件,根据所解决的问题,有不同的特定应用 '头'。
1. 分类器架构
如下所示,一个情感分析程序,把一个文本文件作为输入。一个分类头接收 的输出,并生成预测的类别标签,如正面或负面情绪。
2. Model
Model 架构将把输入序列的初始部分,如一个文本句子作为输入,并通过预测后面的句子来生成新的文本。一个 Model 头接受 的输出作为 head 的输入,产生关于词表中每个词的概率输出。概率最高的词成为句子中下一个词的预测输出。
八、与 RNN 类型的架构相比,为什么 的效果要好?
RNNs 和 LSTMs、GRU也是之前 NLP 常用的架构,直到 的出现。
然而,这有两个限制:
对于长句中相距较远的单词,其间的长距离依赖关系是一个挑战。
RNNs 每个时间步值处理输入序列的一个词。这意味着在完成时间步 T-1 计算之前,它无法进行时间步骤 T 的计算。(即无法进行并行计算)这降低了训练和推理速度。
对于CNN来说,所有的输出都可以并行计算,这使得卷积速度大大加快。然而,它们在处理长距离的依赖关系方面也有限制:
卷积层中,只有图像(或文字,如果应用于文本数据)中足够接近于核大小的部分可以相互作用。对于相距较远的项目,你需要一个有许多层的更深的网络。
架构解决了这两个限制。它摆脱了RNNs,完全依靠 的优势:
并行地处理序列中的所有单词,从而大大加快了计算速度。
输入序列中单词之间的距离并不重要。 同样擅长计算相邻词和相距较远的词之间的依赖关系。
总结:
作为系列文章的第一篇,本文介绍了 的整体架构,以及训练、推理的过程。下一篇文章将深入到 的各层,从数据流转的过程,介绍 各层的原理及作用。
我来说两句