Transformer 能做什么
在学习 Transformer 之前,我们先来看看它可以做什么。
NLP 是语言学和机器学习交叉领域,专注于理解与人类语言相关的一切。 NLP 任务的目标不仅是单独理解单个单词,而且是能够理解这些单词的上下文。常见的任务比如句子分类、文本生成、摘要和翻译等。NLP 不仅限于书面文本。它还解决语音识别和计算机视觉中的复杂挑战,例如生成音频样本的转录或图像描述。
Transformer 模型用于解决各种 NLP 任务。
一些准备工作
python -m venv hf source hf/bin/activate cd hf pip install "transformers[sentencepiece]"
我们来看一些例子:
零样本分类
我们首先处理一项非常具挑战性的任务,对尚未标记的文本进行分类。这是实际项目中的常见场景,因为注释文本通常很耗时并且需要专业领域知识。对于这项任务,zero-shot-classification
pipeline 非常强大:它允许您直接指定用于分类的标签,而不必依赖预训练模型的标签。下面的模型展示了如何使用标签将句子分类为正面或负面。
from transformers import pipeline classifier = pipeline("zero-shot-classification") classifier( "This is a course about the Transformers library", candidate_labels=["education", "politics", "business"], )
{'sequence': 'This is a course about the Transformers library', 'labels': ['education', 'business', 'politics'], 'scores': [0.8445963859558105, 0.111976258456707, 0.043427448719739914]}
此 pipeline 称为 zero-shot,因为您不需要对数据上的模型进行微调即可使用它。它可以直接返回您想要的任何标签列表的概率分数!
文本生成
现在让我们看看如何使用 pipeline 来生成一些文本。主要使用方法是您提供一个提示,模型将通过生成剩余的文本来自动完成整段话。这类似于许多手机上的预测文本功能。文本生成涉及随机性,因此如果您没有得到和如下所示相同的结果,是正常的。
from transformers import pipeline generator = pipeline("text-generation") generator("In this course, we will teach you how to")
[{'generated_text': 'In this course, we will teach you how to understand and use ' 'data flow and data interchange when handling user data. We ' 'will be working with one or more of the most commonly used ' 'data flows — data flows of various types, as seen by the ' 'HTTP'}]
您可以使用参数 num_return_sequences
控制生成多少个不同的序列,并使用参数 max_length
控制输出文本的总长度。
使用其他模型
前面的示例使用了默认模型,但您也可以从 Hub 中选择特定模型,在特定任务的 pipeline 中使用。以文本生成为例,让我们试试 distilgpt2 模型!以下是如何在与以前相同的 pipeline 中加载它:
from transformers import pipeline generator = pipeline("text-generation", model="distilgpt2") generator( "In this course, we will teach you how to", max_length=30, num_return_sequences=2, )
[{'generated_text': 'In this course, we will teach you how to manipulate the world and ' 'move your mental and physical capabilities to your advantage.'}, {'generated_text': 'In this course, we will teach you how to become an expert and ' 'practice realtime, and with a hands on experience on both real ' 'time and real'}]
填充空白
下一个 pipeline 是 fill-mask
,此任务填充给定文本中的空白:
from transformers import pipeline unmasker = pipeline("fill-mask") unmasker("This course will teach you all about <mask> models.", top_k=2)
[{'sequence': 'This course will teach you all about mathematical models.', 'score': 0.19619831442832947, 'token': 30412, 'token_str': ' mathematical'}, {'sequence': 'This course will teach you all about computational models.', 'score': 0.04052725434303284, 'token': 38163, 'token_str': ' computational'}]
top_k
参数控制要显示的结果有多少种。请注意,这里模型填充了特殊的<mask>
词,它通常被称为掩码标记。其他掩码填充模型可能有不同的掩码标记,因此在探索其他模型时要看下正确的掩码标记是什么。
命名实体识别
命名实体识别 (NER) 是一项任务,其中模型必须找到输入文本的哪些部分对应于诸如人员、位置或组织之类的实体。让我们看一个例子:
from transformers import pipeline ner = pipeline("ner", grouped_entities=True) ner("My name is Sylvain and I work at Hugging Face in Brooklyn.")
[{'entity_group': 'PER', 'score': 0.99816, 'word': 'Sylvain', 'start': 11, 'end': 18}, {'entity_group': 'ORG', 'score': 0.97960, 'word': 'Hugging Face', 'start': 33, 'end': 45}, {'entity_group': 'LOC', 'score': 0.99321, 'word': 'Brooklyn', 'start': 49, 'end': 57} ]
在这里,模型正确地识别出 Sylvain 是一个人 (PER),Hugging Face 是一个组织 (ORG),而布鲁克林是一个位置 (LOC)。
我们在 pipeline 创建函数中传递选项 grouped_entities=True
以告诉 pipeline 将对应于同一实体的句子部分重新组合在一起:这里模型正确地将“Hugging”和“Face”分组为一个组织,即使名称由多个词组成。事实上,预处理甚至会将一些单词分成更小的部分。例如,Sylvain 分割为了四部分:S、##yl、##va 和 ##in。在后处理步骤中,pipeline成功地重新组合了这些部分。
问答系统
问答 pipeline 使用来自给定上下文的信息回答问题:
from transformers import pipeline question_answerer = pipeline("question-answering") question_answerer( question="Where do I work?", context="My name is Sylvain and I work at Hugging Face in Brooklyn", )
{'score': 0.6385916471481323, 'start': 33, 'end': 45, 'answer': 'Hugging Face'}
请注意,此 pipeline 通过从提供的上下文中提取信息来工作;它不会凭空生成答案。
文本摘要
文本摘要是将文本缩减为较短文本的任务,同时保留文本中的主要(重要)信息。下面是一个例子:
from transformers import pipeline summarizer = pipeline("summarization") summarizer( """ America has changed dramatically during recent years. Not only has the number of graduates in traditional engineering disciplines such as mechanical, civil, electrical, chemical, and aeronautical engineering declined, but in most of the premier American universities engineering curricula now concentrate on and encourage largely the study of engineering science. As a result, there are declining offerings in engineering subjects dealing with infrastructure, the environment, and related issues, and greater concentration on high technology subjects, largely supporting increasingly complex scientific developments. While the latter is important, it should not be at the expense of more traditional engineering. Rapidly developing economies such as China and India, as well as other industrial countries in Europe and Asia, continue to encourage and advance the teaching of engineering. Both China and India, respectively, graduate six and eight times as many traditional engineers as does the United States. Other industrial countries at minimum maintain their output, while America suffers an increasingly serious decline in the number of engineering graduates and a lack of well-educated engineers. """ )
[{'summary_text': ' America has changed dramatically during recent years . The ' 'number of engineering graduates in the U.S. has declined in ' 'traditional engineering disciplines such as mechanical, civil ' ', electrical, chemical, and aeronautical engineering . Rapidly ' 'developing economies such as China and India, as well as other ' 'industrial countries in Europe and Asia, continue to encourage ' 'and advance engineering .'}]
与文本生成一样,您可以指定结果的 max_length
或 min_length
。
翻译
对于翻译,如果您在任务名称中提供语言对(例如“translation_en_to_fr
”),则可以使用默认模型,也可以在模型中心(hub)选择要使用的模型。在这里,我们将尝试从法语翻译成英语:
from transformers import pipeline translator = pipeline("translation", model="Helsinki-NLP/opus-mt-fr-en") translator("Ce cours est produit par Hugging Face.")
[{'translation_text': 'This course is produced by Hugging Face.'}]
与文本生成和摘要一样,您可以指定结果的 max_length
或 min_length
。
发展历史
以下是 Transformer 模型(简短)历史中的一些关键节点:
Transformer 架构 于 2017 年 6 月推出。原本研究的重点是翻译任务。随后推出了几个有影响力的模型,包括
- 2018 年 6 月: GPT, 第一个预训练的 Transformer 模型,用于各种 NLP 任务并获得极好的结果
- 2018 年 10 月: BERT, 另一个大型预训练模型,该模型旨在生成更好的句子摘要(下一章将详细介绍!)
- 2019 年 2 月: GPT-2, GPT 的改进(并且更大)版本,由于道德问题没有立即公开发布
- 2019 年 10 月: DistilBERT, BERT 的提炼版本,速度提高 60%,内存减轻 40%,但仍保留 BERT 97% 的性能
- 2019 年 10 月: BART 和 T5, 两个使用与原始 Transformer 模型相同架构的大型预训练模型(第一个这样做)
- 2020 年 5 月, GPT-3, GPT-2 的更大版本,无需微调即可在各种任务上表现良好(称为零样本学习)
这个列表并不全面,只是为了突出一些不同类型的 Transformer 模型。大体上,它们可以分为三类:
- GPT-like (也被称作自回归 Transformer 模型)
- BERT-like (也被称作自动编码 Transformer 模型)
- BART/T5-like (也被称作序列到序列的 Transformer 模型)
稍后我们将更深入地探讨这些分类。
Transformer 的工作原理
上面提到的所有 Transformer 模型(GPT、BERT、BART、T5 等)都被训练为语言模型。这意味着他们已经以无监督学习的方式接受了大量原始文本的训练。无监督学习是一种训练类型,其中目标是根据模型的输入自动计算的。这意味着不需要人工来标记数据!
这种类型的模型可以对其训练过的语言进行统计理解,但对于特定的实际任务并不是很有用。因此,一般的预训练模型会经历一个称为迁移学习的过程。在此过程中,模型在给定任务上以监督方式(即使用人工注释标签)进行微调。
除了一些特例(如 DistilBERT)外,实现更好性能的一般策略是增加模型的大小以及预训练的数据量。不幸的是,训练模型,尤其是大型模型,需要大量的数据,时间和计算资源。重复训练会导致大量的浪费。这就是为什么共享语言模型至关重要:共享经过训练的权重,当遇见新的需求时在预训练的权重之上进行微调,可以降低训练模型训练的算力和时间消耗。
迁移学习
预训练是训练模型前的一个操作:随机初始化权重,在没有任何先验知识的情况下开始训练。
这种预训练通常是在非常大量的数据上进行的。因此,它需要大量的数据,而且训练可能需要几周的时间。
另一方面,微调是在模型经过预训练后完成的训练。要执行微调,首先需要获取一个经过预训练的语言模型,然后使用特定于任务的数据集执行额外的训练。等等,为什么不直接为最后的任务而训练呢?有几个原因:
- 预训练模型已经在与微调数据集有一些相似之处的数据集上进行了训练。因此,微调过程能够利用模型在预训练期间获得的知识(例如,对于 NLP 问题,预训练模型将对您在任务中使用的语言有某种统计规律上的理解)。
- 由于预训练模型已经在大量数据上进行了训练,因此微调需要更少的数据就可以获得不错的结果。
- 获得好结果所需的时间和资源要少得多。
例如,可以利用英语的预训练过的模型,然后在 arXiv 语料库上对其进行微调,从而形成一个基于科学/研究的模型。微调只需要有限的数据量:预训练模型获得的知识可以“迁移”到目标任务上,因此被称为迁移学习。
因此,微调模型具有较低的时间、数据、财务和环境成本。迭代不同的微调方案也更快、更容易,因为与完整的预训练相比,训练的约束更少。
这个过程也会比从头开始的训练(除非你有很多数据)取得更好的效果,这就是为什么你应该总是尝试利用一个预训练的模型—一个尽可能接近你手头的任务的模型—并对其进行微调。
一般架构
Transformer 模型主要由两个块组成:
- Encoder (左侧): 编码器接收输入并构建其表示(其特征)。这意味着对模型进行了优化,以从输入中获得理解。
- Decoder (右侧): 解码器使用编码器的表示(特征)以及其他输入来生成目标序列。这意味着该模型已针对生成输出进行了优化。
这些部件中的每一个都可以独立使用,具体取决于任务:
- Encoder-only models: 适用于需要理解输入的任务,如句子分类和命名实体识别。
- Decoder-only models: 适用于生成任务,如文本生成。
- Encoder-decoder models 或者 sequence-to-sequence models: 适用于需要根据输入进行生成的任务,如翻译或摘要。
在后面的部分中,我们将单独地深入研究这些体系结构。
注意力层
Transformer 模型的一个关键特性是注意力层。事实上,介绍 Transformer 架构的文章的标题是“注意力就是你所需要的”!简单地说,这一层将告诉模型在处理每个单词的表示时,要特别重视您传递给它的句子中的某些单词(并且或多或少地忽略其他单词)。
把它放在语境中,考虑将文本从英语翻译成法语的任务。在输入“You like this course”的情况下,翻译模型还需要注意相邻的单词“You”,以获得单词“like”的正确翻译,因为在法语中,动词“like”的变化取决于主题。然而,句子的其余部分对于该词的翻译没有用处。同样,在翻译“this”时,模型也需要注意“course”一词,因为“this”的翻译不同,取决于相关名词是单数还是复数。同样,句子中的其他单词对于“this”的翻译也不重要。对于更复杂的句子(以及更复杂的语法规则),模型需要特别注意可能出现在句子中更远位置的单词,以便正确地翻译每个单词。
同样的概念也适用于与自然语言相关的任何任务:一个词本身有一个含义,但这个含义受语境的影响很大,语境可以是研究该词之前或之后的任何其他词(或多个词)。
现在您已经了解了注意力层的含义,让我们更仔细地了解 Transformer 架构。
原始的结构
Transformer 架构最初是为翻译而设计的。在训练期间,编码器接收特定语言的输入(句子),而解码器需要输出对应语言的翻译。在编码器中,注意力层可以使用一个句子中的所有单词(正如我们刚才看到的,给定单词的翻译可以取决于它在句子中的其他单词)。然而,解码器是按顺序工作的,并且只能注意它已经翻译过的句子中的单词。例如,当我们预测了翻译目标的前三个单词时,我们将它们提供给解码器,然后解码器使用编码器的所有输入来尝试预测第四个单词。
为了在训练过程中加快速度(当模型可以访问目标句子时),解码器会被输入整个目标,但不允许获取到要翻译的单词(如果它在尝试预测位置2的单词时可以访问位置2的单词,解码器就会偷懒,直接输出那个单词,从而无法学习到正确的语言关系!)。例如,当试图预测第4个单词时,注意力层只能获取位置1到3的单词。
最初的 Transformer 架构如下所示,编码器位于左侧,解码器位于右侧:
注意,解码器块中的第一个注意力层关联到解码器的所有(过去的)输入,但是第二注意力层使用编码器的输出。因此,它可以访问整个输入句子,以最好地预测当前单词。这是非常有用的,因为不同的语言可以有语法规则将单词按不同的顺序排列,或者句子后面提供的一些上下文可能有助于确定给定单词的最佳翻译。
也可以在编码器/解码器中使用注意力遮罩层,以防止模型注意某些特殊单词。例如,在批处理句子时,填充特殊词使所有句子的长度一致。
Transformer 模型的分类
“编码器”模型
“编码器”模型指仅使用编码器的 Transformer 模型。在每个阶段,注意力层都可以获取初始句子中的所有单词。这些模型通常具有“双向”注意力,被称为自编码模型。
这些模型的预训练通常围绕着以某种方式破坏给定的句子(例如:通过随机遮盖其中的单词),并让模型寻找或重建给定的句子。
“编码器”模型最适合于需要理解完整句子的任务,例如:句子分类、命名实体识别(以及更普遍的单词分类)和阅读理解后回答问题。
该系列模型的典型代表有:
“解码器”模型
“解码器”模型通常指仅使用解码器的 Transformer 模型。在每个阶段,对于给定的单词,注意力层只能获取到句子中位于将要预测单词前面的单词。这些模型通常被称为自回归模型。
“解码器”模型的预训练通常围绕预测句子中的下一个单词进行。
这些模型最适合于涉及文本生成的任务。
该系列模型的典型代表有:
序列到序列模型
编码器-解码器模型(也称为序列到序列模型)同时使用 Transformer 架构的编码器和解码器两个部分。在每个阶段,编码器的注意力层可以访问初始句子中的所有单词,而解码器的注意力层只能访问位于输入中将要预测单词前面的单词。
这些模型的预训练可以使用训练编码器或解码器模型的方式来完成,但通常涉及更复杂的内容。例如,T5 通过将文本的随机跨度(可以包含多个单词)替换为单个特殊单词来进行预训练,然后目标是预测该掩码单词替换的文本。
序列到序列模型最适合于围绕根据给定输入生成新句子的任务,如摘要、翻译或生成性问答。
该系列模型的典型代表有:
偏见和局限性
如果您打算在正式的项目中使用经过预训练或经过微调的模型。请注意:虽然这些模型是很强大,但它们也有局限性。其中最大的一个问题是,为了对大量数据进行预训练,研究人员通常会搜集所有他们能找到的内容,中间可能夹带一些意识形态或者价值观的刻板印象。
您需要记住,使用的原始模型的时候,很容易生成性别歧视、种族主义或恐同内容。这种固有偏见不会随着微调模型而使消失。