AGI 之 【Hugging Face】 的【Transformer】的 [ 解码器 ] / [ 认识 Transformer ]的简单整理
目录
AGI 之 【Hugging Face】 的【Transformer】的 [ 解码器 ] / [ 认识 Transformer ]的简单整理
一、简单介绍
AGI,即通用人工智能(Artificial General Intelligence),是一种具备人类智能水平的人工智能系统。它不仅能够执行特定的任务,而且能够理解、学习和应用知识于广泛的问题解决中,具有较高的自主性和适应性。AGI的能力包括但不限于自我学习、自我改进、自我调整,并能在没有人为干预的情况下解决各种复杂问题。
Hugging Face作为当前全球最受欢迎的开源机器学习社区和平台之一,在AGI时代扮演着重要角色。它提供了丰富的预训练模型和数据集资源,推动了机器学习领域的发展。Hugging Face的特点在于易用性和开放性,通过其Transformers库,为用户提供了方便的模型处理文本的方式。随着AI技术的发展,Hugging Face社区将继续发挥重要作用,推动AI技术的发展和应用,尤其是在多模态AI技术发展方面,Hugging Face社区将扩展其模型和数据集的多样性,包括图像、音频和视频等多模态数据。
AGI作为未来人工智能的高级形态,具有广泛的应用前景,而Hugging Face作为开源社区,将在推动AGI的发展和应用中扮演关键角色。
(注意:以下代码运行,可能需要科学上网)
二、Transformer
Transformer 是一种深度学习模型架构,最初由 Vaswani 等人在 2017 年的论文《Attention is All You Need》中提出。它引入了基于注意力机制的结构,克服了传统 RNN(递归神经网络)在处理长序列输入时的效率和效果问题。Transformer 模型特别适用于自然语言处理(NLP)任务,如机器翻译、文本生成和文本分类等。
Hugging Face 是一个致力于推动 NLP 研究和应用的公司。其主要产品是开源的 Transformers 库,该库实现了各种基于 Transformer 架构的模型,并提供了易于使用的 API。
三、解码器
解码器(Decoder)是神经网络的一部分,通常在序列到序列(sequence-to-sequence)任务中使用,比如机器翻译、文本生成和对话系统。解码器的主要功能是将编码器(Encoder)生成的中间表示转换成目标序列。Transformer 架构中的解码器由多个解码器层(Decoder Layers)组成,每个解码器层包括多头自注意力机制、编码器-解码器注意力机制和前馈神经网络(Feed-Forward Neural Network)。下面是解码器及其组件的详细介绍:
Transformer 解码器是一个复杂的模块,通过多头注意力机制和前馈神经网络对序列数据进行处理。解码器的设计使其能够在序列生成任务中发挥重要作用,生成高质量的目标序列。理解解码器的各个组件及其工作原理,对于构建和优化序列到序列模型至关重要。
如图所示,解码器和编码器的主要区别在于解码器有两个注意力子层:
对编码器栈的输出key和value向量执行多头注意力,并以解码器的中间表示作为query 。在这种方式中,编码器-解码器注意力层学习如何关联来自两个不同序列(例如两种不同语言)的词元。在每个块中,解码器都可以访问编码器的key和value。
我们来看一下需要进行哪些修改才能在自注意力层中添加掩码,然后将编码器-解码器注意力层的实现作为一道作业题留给你。掩码自注意力的技巧是引入一个掩码矩阵,该矩阵对角线下方的元素为1,上方的元素为0:
# 获取输入序列的长度
seq_len = inputs.input_ids.size(-1)
# 创建一个下三角矩阵,表示遮掩未来的标记
# tril 函数用于创建一个下三角矩阵,其中只有主对角线及以下部分为1,其余部分为0
mask = torch.tril(torch.ones(seq_len, seq_len)).unsqueeze(0)
# 查看第一个遮掩矩阵
mask[0]
运行结果:
tensor([[1., 0., 0., 0., 0.], [1., 1., 0., 0., 0.], [1., 1., 1., 0., 0.], [1., 1., 1., 1., 0.], [1., 1., 1., 1., 1.]])
这里我们使用了PyTorch的tril()函数来创建下三角矩阵。一旦我们有了这个掩码矩阵,我们可以使用Tensor.masked fill()将所有的0替换为负无穷来防止每个注意力头查看后面的词元:
# 使用 mask 填充 scores 矩阵中需要遮掩的位置
# masked_fill 函数用于将 mask 中为 0 的位置在 scores 矩阵中替换为 -inf
# 这样可以确保在计算注意力权重时,被遮掩的位置不会影响结果
scores.masked_fill(mask == 0, -float("inf"))
运行结果:
tensor([[[27.1825, -inf, -inf, -inf, -inf], [ 0.1586, 28.4586, -inf, -inf, -inf], [ 0.7316, 0.1006, 28.5450, -inf, -inf], [-0.3873, 0.6837, -0.4750, 26.8700, -inf], [ 0.4209, -1.1623, -1.7036, -0.7450, 28.0119]]], grad_fn=<MaskedFillBackward0>)
通过将矩阵对角线上方的值设为负无穷,可以保证当我们对分数进行softmax时,注意力权重都为0,因为e-=0(回想一下softmax计算的是规范化指数)。我们只需要对本章早先实现的缩放点积注意力函数进行一点点修改,就能轻松地包含这种掩码行为:
def scaled_dot_product_attention(query, key, value, mask=None):
# 计算缩放点积注意力得分
dim_k = query.size(-1)
scores = torch.bmm(query, key.transpose(1, 2)) / sqrt(dim_k)
if mask is not None:
# 使用 mask 填充 scores 矩阵中需要遮掩的位置
scores = scores.masked_fill(mask == 0, float("-inf"))
# 计算注意力权重
weights = F.softmax(scores, dim=-1)
# 使用注意力权重加权 value 矩阵,得到最终的注意力输出
return weights.bmm(value)
这里的解码器层实现相当简单。如果你想了解更多,我们建议读者参考Andrej Karpathy创作的minGPT的优秀实现(https://oreil.ly/kwsOP)。
至此我们讲述了很多技术细节,希望你现在应该对Transformer架构每个部分的工作原理有了很好的理解。在开始构建比文本分类更高级的任务模型之前,我们稍微退后一步,看一看Transformer模型的各种分支,以及它们之间的关系。
四、认识 Transformer
Transformer模型有三种主要的架构:编码器、解码器和编码器-解码器。早期Transformer模型的初步成功触发了模型开发的寒武纪爆发,研究人员在各种大小和性质的数据集上使用新的预训练目标构建各种模型,并调整架构以进一步提高性能。虽然模型的种类仍在迅速增长,但它们仍然可以分为三大类。
1、Transformer的生命树
随着时间的推移,三种主要的架构都进行了各自的演进。如下图,展示了一些最著名的模型及其后代。
Transformer模型总计有超过50种不同的架构,因此上图未能涵盖所有架构,它只列出了一些重要的里程碑。我们前面介绍了Transformer模型最初的架构,现在我们着重研究一些比较关键的后代架构,我们先从编码器分支开始。
2、编码器分支
A. Wang et al., “GLUE: A Multi-Task Benchmark and Analysis Platform for Natural Language Understanding”(https://arxiv.org/abs/1804.07461),(2018).
基于Transformer架构的第一个纯编码器模型是BERT。当初它发布时,在流行的GLUE基准测试中 (该测试度量跨几个难度级别的NLU任务),它的表现优于所有当时最先进的模型。在此之后,BERT的预训练目标和架构持续进行适配并进一步提高了性能。纯编码器模型仍然在NLU任务(如文本分类、命名实体识别和问答)的研究和工业中占主导地位。我们简要地讲述一下BERT模型及其变体:
2.1 BERT
J. Devlin et al., “BERT:Pre-Training of Deep BidirectionalTransformersfor Language Understanding”(https://arxiv.org/abs/1810.04805),(2018).
BERT针对这两个目标进行预训练:预测文本中的掩码词元,确定一个文本段是否有可能跟随另一个文本段 。前者称为掩码语言建模(MLM),后者称为下一句预测(NSP)。
2.2 DistilBERT
V. Sanh et al., “DistilBERT,a Distilled Version of BERT:Smaller,Faster,Cheaper and Lighter”(https://arxiv.org/abs/1910.01108),(2019).
虽然BERT取得了极好的结果,但它太大了,使其在需要低延迟的环境中部署变得棘手。通过在预训练期间使用一种称为知识蒸馏的技术,DistilBERT实现了97%的BERT性能,同时使用的内存量减少了40%,速度提高了60% 。有关知识蒸馏的更多详细信息,后面会介绍。
2.3 RoBERTa
Y. Liu et al., “RoBERTa:A Robustly Optimized BERT Pretraining Approach”(https://arxiv.org/abs/1907.11692),(2019).
在BERT发布之后进行的一项研究表明,通过修改预训练方案,可以进一步提高其性能。RoBERTa采用更大的批量、更多的训练数据进行更长时间的训练,并且放弃了NSP任务 。这些改变与原始的BERT模型相比显著提高了性能。
2.4 XLM
G. Lample, and A. Conneau, “Cross-Lingual Language Model Pretraining”(https://arxiv.org/abs/1901.07291), (2019).
跨语言语言模型(XLM) 探索了几种用于构建多语言模型的预训练目标,包括来自类GPT模型的自回归语言建模和来自BERT的MLM。此外,XLM预训练论文的作者还介绍了翻译语言建模(TLM),这是MLM对多语言输入的扩展。通过实验这些预训练任务,它们在几个多语言NLU基准测试以及翻译任务中取得了最先进的结果。
2.5 XLM-RoBERTa
A. Conneau et al., “Unsupervised Cross-Lingual Representation Learning at Scale”(https://arxiv.org/abs/1911.02116),(2019).
基于XLM和RoBERTa的研究,XLM-RoBERTa或XLM-R模型通过大规模扩展训练数据将多语言预训练推向了更高的水平 。该模型的开发人员使用Common Crawl语料库(https://commoncrawl.org)创建了一个包含2.5TB文本的数据集,并在此数据集上训练了一个编码器MLM。由于该数据集没有平行文本(即译文),因此放弃了XLM的TLM目标。这种方法在低资源语言方面大幅领先于XLM和多语言BERT变体。
2.6 ALBERT
Z. Lan et al., “ALBERT:A Lite BERT for Self-Supervised Learning of Language Representations”(https://arxiv.org/abs/1909.11942),(2019).
ALBERT模型做了三处改进使得编码器的架构更加高效 。首先,它从隐藏维度解耦了词元嵌入的维度,从而能够让嵌入维度更小,从而节省参数,尤其是当词汇量很大时。其次,所有层共享相同的参数,从而能够进一步降低参数数量。最后,将NSP目标替换为句子排序预测:模型预测两个连续句子的顺序是否交换了,而不是预测它们是否属于同一个文档或主题。这些改变令使用更少的参数训练更大的模型,并在NLU任务中达到更高的性能成为可能。
2.7 ELECTRA
K. Clark et al., “ELECTRA:Pre-Training Text Encoders as Discriminators Rather Than Generators”(https://arxiv.org/abs/2003.10555),(2020).
标准MLM的预训练目标有一个局限性,在每个训练步骤中,只更新了掩码词元的表示,而没有更新其他输入词元。为解决这个问题,ELECTRA采用了一种双模型方法 :第一个模型(通常很小)像标准的掩码语言模型一样工作,预测掩码的词元;然后,第二个模型(鉴别器)预测第一个模型输出中的哪些词元最初是被掩码的。换句话说,鉴别器需要对每个词元进行二分类,这种方法使训练效率提高了30倍。在使用ELECTRA模型执行下游任务时,判别器将像标准BERT模型一样进行微调。
2.8 DeBERTa
P. He et al., “DeBERTa:Decoding-Enhanced BERT with Disentangled Attention”(https://arxiv.org/abs/2006.03654),(2020).
A. Wang et al., “SuperGLUE:A Stickier Benchmark for General-Purpose Language Understanding Systems”(https://arxiv.org/abs/1905.00537),(2019).
DeBERTa模型做了两个架构上的改进 。首先,每个词元表示为两个向量:一个表示内容,另一个表示相对位置。通过将词元的内容与相对位置分离,自注意力层可以更好地建模相邻词元对的依赖关系。另一方面,单词的绝对位置也很重要,特别是对于解码。因此,在词元解码头的softmax层之前添加了一个绝对位置嵌入。DeBERTa是第一个(作为集合)在SuperGLUE基准测试 上击败人类基线的模型(SuperGLUE是GLUE的更难版本,由用于度量NLU性能的几个子任务组成)。
至此我们讲述了一些主要的纯编码器模型,我们来看一下纯解码器模型。
3、解码器分支
Transformer解码器模型的进展在很大程度上是由OpenAI所推动的。这些模型在预测序列中下一个单词方面表现出色,因此主要用于文本生成任务。它们的进展是通过使用更大的数据集和将语言模型扩展到更大规模来推动的。我们来看看这些迷人的生成模型的演变历史:
3.1 GPT
A. Radford et al., “Improving Language Understanding by Generative Pre-Training”(https://openai.com/blog/language-unsupervised),OpenAI(2018).
GPT将自然语言处理中的两个关键思想融合在了一起 :新颖高效的Transformer解码器架构和迁移学习。在该架构中,模型通过基于前面的单词预测下一个单词来预训练。该模型使用了BookCorpus进行训练,在分类等下游任务上取得了优秀的结果。
3.2 GPT-2
A. Radford et al., “Language Models Are Unsupervised Multitask Learners”(https://openai.com/blog/betterlanguage-models),OpenAI(2019).
受以上GPT简单且可扩展的预训练方法成功的启发,GPT-2对原始模型和训练集进行了升级 。GPT-2能够产生一系列连贯的文本。由于担心可能被误用,因此GPT-2分阶段发布,先发布较小的模型,然后再发布完整的模型。
3.3 CTRL
N.S. Keskar et al., “CTRL:A ConditionalTransformerLanguage Model for Controllable Generation”(https://arxiv.org/abs/1909.05858),(2019).
像GPT-2这样的模型可以根据输入序列(即提示)生成延续输出。然而,用户对所生成序列的风格控制较弱。条件转换语言(CTRL)模型通过在序列开头添加“控制词元”来解决这个问题 。这样可以控制所生成文本的风格,实现多样化的生成。
3.4 GPT-3
J. Kaplan et al., “Scaling Laws for Neural Language Models”(https://arxiv.org/abs/2001.08361),(2020).
T. Brown et al., “Language Models Are Few-Shot Learners”(https://arxiv.org/abs/2005.14165),(2020).
GPT在升级成GPT-2之后取得了成功,OpenAI对不同规模的语言模型的行为进行了彻底的分析,发现计算量、数据集大小、模型大小和语言模型的性能之间存在着简单的幂律规律 。受到这些分析的启发,OpenAI对GPT-2放大100倍,得到了拥有1750亿个参数的GPT-3 。GPT-3除了能够生成令人印象深刻的逼真文本段落外,还展现出少样本学习的能力:只需要提供少量的几个任务样本(如将文本翻译成代码),GPT-3就能够在新样本上完成新的任务。OpenAI没有开源GPT-3,但提供了API(https://oreil.ly/SEGRW)接口供人们调用。
3.5 GPT-Neo/GPT-J-6B
S. Black et al., “GPT-Neo:Large Scale Autoregressive Language Modeling with Mesh-TensorFlow”(https://doi.org/10.5281/zenodo.5297715),(2021); B. Wang and A. Komatsuzaki,“GPT-J-6B:A 6 Billion Parameter Autoregressive Language Model”(https://github.com/kingoflolz/mesh-transformer-jax),(2021).
GPT-Neo和GPT-J-6B类似于GPT,由EleutherAI(https://eleuther.ai)训练,EleutherAI是一个旨在重新创建和发布GPT-3同等规模模型的研究人员组织 。GPT-Neo和GPT-J-6B是GPT-3的1750亿个参数完整版本的较小变体,具有13亿、27亿和60亿个参数,主要与OpenAI提供的GPT-3模型较小版本相竞争。
Transformer生命树的最后一个分支是编码器-解码器模型。
4、编码器-解码器分支
虽然目前业内通常使用纯编码器或纯解码器栈来构建模型,但是Transformer架构有几种编码器-解码器变体在自然语言理解和生成领域都具有创新应用。
4.1 T5
C. Raffel et al., “Exploring the Limits of Transfer Learning with a Unified Text-to-Text Transformer”(https://arxiv.org/abs/1910.10683),(2019).
T5模型将所有的自然语言理解和生成任务都转化为文本到文本任务 (即序列到序列任务),统一了它们的处理方式。既然所有任务都被定义为序列到序列任务,因此就自然而然采用了编码器-解码器架构。例如,对于文本分类问题,编码器的输入是文本,而解码器的输出则是文本而不是类(即将预测标注生成为文本)。我们将在第6章中更详细地讨论这个问题。T5模型使用Transformer原始架构,数据使用C4数据集(一个超大规模的文本语料库,爬取了各种来源的网页文本数据)。T5模型将所有SuperGLUE任务转换为文本到文本任务进行掩码语言建模预训练。其中110亿个参数的最大版本在几个基准测试中取得了当时业界最好的成绩。
4.2 BART
M. Lewis et al., “BART: Denoising Sequence-to-Sequence Pre-Training for Natural Language Generation, Translation, and Comprehension”(https://arxiv.org/abs/1910.13461), (2019).
BART将BERT和GPT的预训练流程整合进编码器-解码器架构中 。BART对输入序列进行了多种变换,包括从简单掩码到句子置换、词元删除和文档反转。这些修改后的输入被传入编码器中进行处理,然后由解码器重构为原始文本。通过这种方式,BART模型具有更强的灵活性,既可以用于NLU任务,也可以用于自然语言生成(N L G)任务,并且在两方面都取得了最先进的性能表现。
4.3 M2M-100
A. Fan et al., “Beyond English-Centric Multilingual Machine Translation”(https://arxiv.org/abs/2010.11125),(2020).
传统上,翻译模型是针对一种语言对和一个翻译方向构建的。显然,这无法扩展到众多语言,而实际上有些知识是可以在多种语言对之间共享的,这些知识可以用于在罕见语言之间进行翻译。M2M-100是第一个可以在任意100种语言之间进行翻译的翻译模型 。这样就可以对罕见和少数民族语言进行高质量的翻译。该模型使用前缀词元(类似于[CLS]特殊词元)来表示源语言和目标语言。
4.4 BigBird
M. Zaheer et al., “Big Bird:Transformersfor Longer Sequences”(https://arxiv.org/abs/2007.14062),(2020).
Transformer模型的一个主要局限是注意力机制的二次存储需求,导致最大上下文大小受到限制。BigBird通过使用线性缩放的稀疏注意力形式来解决这个问题 。这种方法令BigBird的最大上下文大小从大多数BERT模型的512个词元扩展到了4096个词元,从而能够容纳更多的上下文知识。这对需要保存长依赖项的场景特别有用,例如文本摘要。