Hugging Face 是行业领先的 NLP 初创公司,包括 Bing、Apple 和 Monzo 在内的千余家企业均在使用该公司的库。本教程所用的所有示例均可在 Colab 中查看。您可通过每个部分的链接进入相应的详情页面。
简介
Hugging Face 是一家专注于 NLP 的创业公司,拥有大型开源社区,在 Transformer 库方面表现尤为出色。🤗/Transformer 是基于 Python 的库,对外提供诸多热门转换器架构(例如 BERT、RoBERTa、GPT-2 或 DistilBERT)的 API。使用该API 可获得文本分类、信息提取、问题回答与文本生成等多种 NLP 任务的最高水准(SOTA)结果。我们已用多套权重对上述架构进行预训练。仅需安装 PIP 软件包管理工具,即可开始使用 Transformer:
pip install transformers
Transformer
https://github.com/huggingface/transformers
此库在 PyTorch 中发展迅猛,最近我们已将其移植到 TensorFlow 2.0 中,该库现可提供能与 Keras’ fit API、TensorFlow Extended 和 TPU 搭配使用的 API 👏。本文将专门介绍采用 TensorFlow 的 Transformer 库的用途:使用 Keras API 及 TensorFlow TPUStrategy 对先进的 Transformer 模型进行微调。
库和理念
Transformer 库以预训练转换器模型的概念为基础。这些模型的形状、大小和架构各不相同,在接收输入数据方面自成体系 – 进行词条化 (tokenization) 处理。
{
"attention_probs_dropout_prob": 0.1,
"hidden_act": "gelu",
"hidden_dropout_prob": 0.1,
"hidden_size": 768,
"initializer_range": 0.02,
"intermediate_size": 3072,
"max_position_embeddings": 512,
"num_attention_heads": 12,
"num_hidden_layers": 12,
"type_vocab_size": 2,
"vocab_size": 28996
}
bert-base-cased Configuration file as a JSON
分词器类:分词器类负责将 Python 字符串转换成数组或充当模型词汇索引的整数张量。在将字符串拆分成词条方面,该类具备许多便利特性。这一词条化过程因模型而异,因此每个模型都有自己的分词器。
模型类:模型类包含神经网络建模逻辑本身。使用 TensorFlow 模型时,该类会继承 tf.keras.layers.Layer,这意味着兼容 Keras 的 API 可以非常方便地使用该类,用户也可使用自定义训练循环语句和 GradientTape 对其加以训练。
简洁之美
使用 Transformer 的优势在于与模型无关 API。只需几行代码,即可加载预训练模型及其分词器。加载 BERT 和 GPT-2 TensorFlow 模型及其分词器的示例如下:
from transformers import (TFBertModel, BertTokenizer,
TFGPT2Model, GPT2Tokenizer)
bert_model = TFBertModel.from_pretrained("bert-base-cased") # Automatically loads the config
bert_tokenizer = BertTokenizer.from_pretrained("bert-base-cased")
gpt2_model = TFGPT2Model.from_pretrained("gpt2") # Automatically loads the config
gpt2_tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
系统会下载 HuggingFace S3 存储中的权重,并将其缓存到本地机器上。这些模型可随时用于推理,或在需要时进行微调。我们来看看如何进行微调操作。
微调 Transformer 模型
训练(使用 CPU/GPU 上的 Keras 以及 TPUStrategy)
我们制作了一个相应的 Colab notebook,以便您快速追踪所有代码,并利用 tensorflow_datasets 软件包来加载数据。Tensorflow 数据集提供了一个 tf.data.Dataset,我们可以将该类返回至 glue_convert_examples_to_features 方法。
Colab notebook
https://colab.research.google.com/drive/1l39vWjZ5jRUimSQDoUcuWGIoNjLjA2zu
tensorflow_datasets
https://www.tensorflow.org/datasets/
tf.data.Dataset
https://www.tensorflow.org/api_docs/python/tf/data/Dataset
glue_convert_examples_to_features
https://huggingface.co/transformers/main_classes/processors.html#transformers.data.processors.glue.glue_convert_examples_to_features
此方法会利用分词器将输入内容拆分成词条,并会根据模型需要,在序列的开头和结尾添加特殊词条(例如 [SEP]、[CLS]、</s> 或 <s>)。此方法会返回含有特定输入内容的 tf.data.Dataset。
然后我们可以使用标准的 tf.data.Dataset 方法打乱此数据集,应以每批 32 个单元的规模进行批处理。
import tensorflow_datasets
from transformers import glue_convert_examples_to_features
data = tensorflow_datasets.load("glue/mrpc")
train_dataset = data["train"]
validation_dataset = data["validation"]
train_dataset = glue_convert_examples_to_features(train_dataset, bert_tokenizer, 128, 'mrpc')
validation_dataset = glue_convert_examples_to_features(validation_dataset, bert_tokenizer, 128, 'mrpc')
train_dataset = train_dataset.shuffle(100).batch(32).repeat(2)
validation_dataset = validation_dataset.batch(64)
为模型构建流水线
使用兼容 Keras 的方法训练模型从未如此简单。当我们设置好输入流水线后,便可以定义超参数,并调用兼容 Keras’ 的方法来处理我们的数据集。
optimizer = tf.keras.optimizers.Adam(learning_rate=3e-5, epsilon=1e-08, clipnorm=1.0)
loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
metric = tf.keras.metrics.SparseCategoricalAccuracy('accuracy')
bert_model.compile(optimizer=optimizer, loss=loss, metrics=[metric])
bert_history = bert_model.fit(
bert_train_dataset,
epochs=2,
steps_per_epoch=115,
validation_data=bert_validation_dataset,
validation_steps=7
)
Training with Keras’ fit method
运用策略进行训练让您可以更好地掌控训练过程中的情况。通过切换策略,用户可以选择训练模型所用的分布式方式,从多 GPU 到 TPU均可。
撰写本文时,TPUStrategy 是使用 TensorFlow 2 在 TPU 上训练模型的唯一可靠方法。由于我们可以在 GPU 上开展实际训练时轻松切换策略,并无需作出任何代码更改,这使得使用策略构建自定义循环会更加有效。
TPUStrategy
https://www.tensorflow.org/api_docs/python/tf/distribute/experimental/TPUStrategy
构建自定义循环需要完成一些设置工作,因此我们建议读者打开下方的 Colab notebook,以获得更好地理解。该 notebook不会像第一个 Colab 那样详细介绍词条化,但会展示如何构建可为 TPUStrategy 所用的输入流水线。
由于使用本地文件系统时,处理 TPU 会非常复杂,因此该策略使用 Google Cloud Platform 存储数据。
查看 Colab notebook
https://colab.research.google.com/drive/1yWaLpCWImXZE2fPV0ZYDdWWI8f52__9A#scrollTo=mnhwpzb73KIL
Transformer 现在有权访问 TensorFlow API - 这会带来哪些影响?
Transformer 库的主要特点就是模型无关性,并且拥有非常简单的 API 。在作为可获取 NLP 最高水准结果的模型前端时,用户可以根据正在进行的任务来轻松切换模型。
例如,以下是对语言分类任务 (MRPC) 上的 BERT 进行微调的完整脚本:
model = TFBertForSequenceClassification.from_pretrained("bert-base-cased")
tokenizer = BertTokenizer.from_pretrained("bert-base-cased")
data = tensorflow_datasets.load("glue/mrpc")
train_dataset = data["train"]
train_dataset = glue_convert_examples_to_features(train_dataset, tokenizer, 128, 'mrpc')
optimizer = tf.keras.optimizers.Adam(learning_rate=3e-5, epsilon=1e-08, clipnorm=1.0)
loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
metric = tf.keras.metrics.SparseCategoricalAccuracy('accuracy')
model.compile(optimizer=optimizer, loss=loss, metrics=[metric])
model.fit(train_dataset, epochs=3)
在 MNLI 上微调 BERT
然而,在生产环境中,内存资源往往十分紧张。您可能会改用较小的模型(如,DistilBERT 模型)。只需将前两行代码更改为以下内容,即可完成切换:
model = TFDistilBertForSequenceClassification.from_pretrained("distilbert-base-uncased")
tokenizer = DistilbertTokenizer.from_pretrained("distilbert-base-uncased")
Loading DistilBERT with its tokenizer
使用分词器加载 DistilBERT作为内含 10 余种 Transformer 架构的平台,🤗/Transformer 可支持您轻松使用、微调以及比较曾改善 NLP 领域深度学习的模型。许多使用转换器模型的下游应用会将其用于后端,并且多家公司也在生产环境中使用。欢迎您在 GitHub 代码库中提出问题。
GitHub 代码库
https://github.com/huggingface/transformers/issues/new/choose