介绍
“NLP’s ImageNet moment has arrived.”
– Sebastian Ruder
想象一下我们有能力构建支持谷歌翻译的自然语言处理(NLP)模型,并且在Python中仅需几行代码来完成,这听起来是不是让人非常兴奋。
而现在我们就可以坐在自己的机器前实现这个了!借助于被HuggingFace称为PyTorch-Transformers目前最先进的NLP工具。
我们可以简单地用Python导入它并进行实验。
我对现在NLP的研发速度感到非常惊讶,每一篇新论文、每一个框架和库都在推动着这个不可思议的强大领域的发展。由于围绕人工智能的研究的开放文化和大量免费可用的文本数据,几乎没有什么是我们今天不能做的。
无论我再怎么强调PyTorch-Transformers对研究社区和NLP行业的影响也不为过。我相信这有可能彻底改变我们所知的自然语言处理领域。
揭开NLP的神秘面纱
本质上,自然语言处理是教计算机理解人类语言的复杂性。
在讨论PyTorch-Transformers的技术细节之前,让我们快速回顾一下该库构建的概念——NLP。我们还将理解最先进的(state-of-the-art)意味着什么。
在我们开始PyTorch-Transformers的讲解之前,这里有一些你需要了解的东西:
最先进的(state-of-the-art)是指目前对于某项任务“最好的”算法或技术。当我们说“最好的”时,我们的意思是这些算法是由像谷歌、Facebook、微软和亚马逊这样的巨头所倡导的。
NLP有许多定义明确的任务,研究人员正在研究创建智能技术来解决这些问题。一些最受欢迎的任务像机器翻译、文本摘要、问答系统等。
深度学习技术如Recurrent Neural Networks (RNNs), Sequence2Sequence, Attention,还有Word Embeddings(Glove, Word2Vec)对NLP任务来说曾是最先进的。
然而这些技术被一个叫Transformers的框架取代了,其背后是几乎所有的当前最先进的NLP模型。
注意 这篇文章将多处提及Transformers ,所以我强烈建议你阅读下面的指南,以对Transformers有个理解
PyTorch-Transformers是什么?
PyTorch-Transformers是一个最先进的自然语言处理预训练模型库。
我从PyTorch-Transformers的文档中选取了这一部分。这个库目前包含PyTorch实现、预训练的模型权重、使用脚本和用于以下模型的转换工具:
BERT(来自谷歌) 与论文BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding 一起发布
GPT(来自OpenAI) 与论文 Improving Language Understanding by Generative Pre-Training 一起发布
GPT-2(来自OpenAI) 与论文 Language Models are Unsupervised Multitask Learners 一起发布
Transformer-XL(来自谷歌/CMU) 与论文 Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context 一起发布
XLNet (来自谷歌/CMU) 与论文 XLNet: Generalized Autoregressive Pretraining for Language Understanding 一起发布
XLM (来自Facebook) 与论文 Cross-lingual Language Model Pretraining一起发布
上述所有模型都是适用于各种NLP任务的最佳模型。
大多数最先进的模型需要大量的训练数据和花费数天时间在昂贵的GPU硬件上进行训练,而这些只有大型技术公司和研究实验室才能负担得起。但随着PyTorch-Transformers的推出,现在任何人都可以利用这些最先进的模型!
在你的机器上安装PyTorch-Transformers
在Python中 Pytorch-Transformers非常简单。你可以只使用pip安装:
pip install pytorch-transformers
或者在Colab上使用以下命令:
!pip install pytorch-transformers
由于大多数这些模型都是GPU密集型的,因此我建议按照本文使用谷歌Colab。
注意:本文中的代码是使用PyTorch框架编写的。
使用GPT-2预测下一个单词
因为PyTorch-Transformers支持许多经过语言建模训练的NLP模型,所以它支持自然语言生成任务,比如完形填空(sentence completion)。
2019年2月,OpenAI发布了一种新的基于transformer语言模型GPT-2,引起了不小的轰动。GPT-2是一种于基于transformer的生成语言模型,它基于来自互联网上的40GB的精选文本进行训练。
在无监督的方式下进行训练,它只学会根据通过训练学会识别的模式预测最可能遵循给定句子的序列(即单词)。
让我们使用GPT-2构建我们自己的完形填空模型,我们试着预测句子中的下一个单词:
what is the fastest car in the _________
我选择这个例子是因为这是谷歌的文本补全给出的第一个例子,下面是实现预测的代码:
# 导入必要的库
import torch
from pytorch_transformers import GPT2Tokenizer, GPT2LMHeadModel
# 加载预训练模型tokenizer (vocabulary)
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
# 对文本输入进行编码
text = "What is the fastest car in the"
indexed_tokens = tokenizer.encode(text)
# 在PyTorch张量中转换indexed_tokens
tokens_tensor = torch.tensor([indexed_tokens])
# 加载预训练模型 (weights)
model = GPT2LMHeadModel.from_pretrained('gpt2')
#将模型设置为evaluation模式,关闭DropOut模块
model.eval()
# 如果你有GPU,把所有东西都放在cuda上
tokens_tensor = tokens_tensor.to('cuda')
model.to('cuda')
# 预测所有的tokens
with torch.no_grad():
outputs = model(tokens_tensor)
predictions = outputs[0]
# 得到预测的单词
predicted_index = torch.argmax(predictions[0, -1, :]).item()
predicted_text = tokenizer.decode(indexed_tokens + [predicted_index])
# 打印预测单词
print(predicted_text)
代码很直观,我们将文本标记为数字序列并将其索引,然后将其传递给GPT2LMHeadModel。
是不是很棒! 该模型成功地预测出了下一个单词 “world”。这是非常惊人的,因为这就是谷歌的例子。我建议你输入不同的句子来尝试这个模型,看看它预测的下一个单词时是怎样的。
使用GPT-2、Transformer-XL和XLNet生成自然语言
在让我们把文本生成带到下一个层次。我们将根据给定的输入生成一段文本,而不是只预测下一个单词。让我们看看我们的模型为以下输入文本生成了什么输出:
In a shocking finding, scientist discovered a herd of unicorns living in a remote, previously unexplored valley, in the Andes Mountains. Even more surprising to the researchers was the fact that the unicorns spoke perfect English.
我们将使用PyTorch-Transformers为此任务提供的现成脚本,我们先克隆他们的仓库:
!git clone https://github.com/huggingface/pytorch-transformers.git
GPT-2
现在,你只需要一个命令就可以启动模型了!
!python pytorch-transformers/examples/run_generation.py \
--model_type=gpt2 \
--length=100 \
--model_name_or_path=gpt2 \
我们看看我们的GPT-2模型为输入文本生成了什么输出:
The unicorns had seemed to know each other almost as well as they did common humans. The study was published in Science Translational Medicine on May 6. What's more, researchers found that five percent of the unicorns recognized each other well. The study team thinks this might translate into a future where humans would be able to communicate more clearly with those known as super Unicorns. And if we're going to move ahead with that future, we've got to do it at least a
这个结果看起来似乎很疯狂,模型生成的文本具有很强的内聚性,并且实际上有可能被误认为是真实的新闻文章。
XLNet
XLNet将来自Transformer-XL(最先进的自回归模型)的思想运用到预训练中。从经验上看,XLNet在20个任务上的表现都比BERT好,而且通常是占据很大的优势。XLNet在18项任务上取得了最先进的结果,包括问答、自然语言推理、情感分析和文档排序。
你可以用下面的代码来做实现同样的功能:
!python pytorch-transformers/examples/run_generation.py \
--model_type=xlnet \
--length=50 \
--model_name_or_path=xlnet-base-cased \
这是XLNet生成的输出:
St. Nicholas was located in the valley in Chile. And, they were familiar with the southern part of Spain. Since 1988, people had lived in the valley, for many years. Even without a natural shelter, people were getting a temporary shelter. Some of the unicorns were acquainted with the Spanish language, but the rest were completely unfamiliar with English. But, they were also finding relief in the valley. Bioinfo < The Bioinfo website has an open, live community about the
很有趣,虽然GPT-2模型直接从科学角度关注关于独角兽的新闻,但XLNet实际上很好地构建了上下文并巧妙地引入了独角兽的主题。接下来让我们看看Transformer-XL的效果怎样!
Transformer-XL
Transformer网络受到固定长度上下文的限制,因此可以通过学习长期依赖(longer-term dependency)来改进。这就是为什么谷歌提出了一种称为Transformer-XL(意为超长)的语言建模新方法,它使Transformer体系结构能够学习长期依赖。
Transformer-XL比标准Transformer快1800倍。
你可以使用以下代码运行Transformer-XL:
!python pytorch-transformers/examples/run_generation.py \
--model_type=transfo-xl \
--length=100 \
--model_name_or_path=transfo-xl-wt103 \
以下是生成的文本:
both never spoke in their native language ( a natural language ). If they are speaking in their native language they will have no communication with the original speakers. The encounter with a dingo brought between two and four unicorns to a head at once, thus crossing the border into Peru to avoid internecine warfare, as they did with the Aztecs. On September 11, 1930, three armed robbers killed a donkey for helping their fellow soldiers fight alongside a group of Argentines. During the same year
这太棒了,有趣的是,可以看到不同的模型关注输入文本的不同方面来进一步生成输出文本。这种差异是由很多因素造成的,但主要归因于不同的训练数据和模型架构。
但是,最近,神经文本生成一直有一些强烈反对的声音,因为人们担心神经文本生成会增加与假新闻相关的问题。但是我们应该想想它积极的一面! 我们可以将它用于许多积极的应用,比如帮助作家或是创意人员提出新想法等等。
为BERT训练一个遮蔽语言模型(Masked Language Model)
BERT框架是来自谷歌AI的一种新的语言表征模型,它使用预训练和微调来为各种任务创建最先进的NLP模型。这些任务包括问答系统、情感分析和语言推理。
BERT使用以下两个无监督预测任务进行预训练:
Masked Language Modeling (MLM)
Next Sentence Prediction
你可以使用PyTorch-Transformers实现这两个任务。实际上,你可以从头构建自己的BERT模型,也可以对预训练版本进行微调。那么,让我们看看如何为BERT实现遮蔽语言模型。
问题定义
让我们正式定义我们的问题:
给定一个输入序列,我们将随机屏蔽一些单词。然后,模型应该根据上下文中提供的其他非屏蔽词预测屏蔽词的原始值。
那么我们为什么要这么做呢?因为模型在训练过程中学习语言规则。我们很快就会看到这个过程有多有效。
首先,让我们使用BertTokenizer从一个文本字符串准备一个标记化的输入:
import torch
from pytorch_transformers import BertTokenizer, BertModel, BertForMaskedLM
# 加载预训练模型 tokenizer (vocabulary)
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
# 标记化输出
text = "[CLS] Who was Jim Henson ? [SEP] Jim Henson was a puppeteer [SEP]"
tokenized_text = tokenizer.tokenize(text)
这是我们的文本在标记化之后的样子:
下一步将把它转换成一个整数序列,并创建它们的PyTorch张量,以便我们可以直接使用它们进行计算:
# 掩码一个标记,我们将尝试用' BertForMaskedLM '预测回来
masked_index = 8
tokenized_text[masked_index] = '[MASK]'
assert tokenized_text == ['[CLS]', 'who', 'was', 'jim', 'henson', '?', '[SEP]', 'jim', '[MASK]', 'was', 'a', 'puppet', '##eer', '[SEP]']
# 将标记转换为词汇表索引
indexed_tokens = tokenizer.convert_tokens_to_ids(tokenized_text)
segments_ids = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1]
# 将输入转换为PyTorch张量
tokens_tensor = torch.tensor([indexed_tokens])
segments_tensors = torch.tensor([segments_ids])
注意,我们将[MASK]设置在句子的第8个索引处,即单词' Hensen '。这就是我们的模型要预测的。
现在我们的数据已经正确地为BERT进行了预处理,我们将创建一个遮蔽语言模型。现在让我们使用BertForMaskedLM来预测一个屏蔽标记:
# 加载预训练模型 (weights)
model = BertForMaskedLM.from_pretrained('bert-base-uncased')
model.eval()
# :如果你有GPU,把所有东西都放在cuda上
tokens_tensor = tokens_tensor.to('cuda')
segments_tensors = segments_tensors.to('cuda')
model.to('cuda')
# 预测所有的tokens
with torch.no_grad():
outputs = model(tokens_tensor, token_type_ids=segments_tensors)
predictions = outputs[0]
# 证实我们能够预测到'henson'
predicted_index = torch.argmax(predictions[0, masked_index]).item()
predicted_token = tokenizer.convert_ids_to_tokens([predicted_index])[0]
assert predicted_token == 'henson'
print('Predicted token is:',predicted_token)
让我们看看我们的模型输出是什么:
Predicted token is: henson
这是一个在单个输入序列上训练遮蔽语言模型的小演示。然而,对于许多基于Transformer的架构来说,它是训练过程中非常重要的一部分。这是因为它允许模型中的双向训练——这在以前是不可能的。
恭喜你,因为你刚刚实现了你的第一个遮蔽语言模型! 如果你想训练BERT,你只完成了一半的工作。这个例子将使你对如何使用PyTorch-Transformers来处理BERT模型有一个很好的了解。
总结
在本文中,我们使用PyTorch-Transformers实现并探索了各种最先进的NLP模型,如BERT、GPT-2、Transformer-XL和XLNet。我这样做是为了让你们对如何使用这个神奇的库有一个很好的直观感受。
下是我认为你会喜欢这个库的6个理由:
预训练模型:为6种最先进的NLP架构提供了预训练模型,并为27种模型的变化提供了预训练的权重
预处理和微调API:PyTorch-Transformers不会在预训练权重停止。它还提供了一个简单的API,用于执行这些模型所需的所有预处理和微调步骤。现在,如果你读过最近的研究论文,你就会知道许多最先进的模型都有独特的预处理数据的方法,而且很多时候为整个预处理管道编写代码会很麻烦
使用脚本:它还附带了一些脚本,用于在基准NLP数据集上运行这些模型,比如SQUAD2.0(Stanford Question Answering Dataset)和GLUE(General Language Understanding Evaluation)。通过使用yTorch-Transformers,你可以直接针对这些数据集运行模型,并相应地评估性能
多语言:PyTorch-Transformers支持多种语言。这是因为有些模型已经可以很好地用于多种语言
TensorFlow兼容性:你可以将ensorFlow checkpoints作为PyTorch中的模型导入
BERTology:越来越多的研究领域关注于研究像BERT这样的大型transformers的内部工作(有人称之为“BERT学”)