大语言翻译模型训练教程

翻译是将文本序列从一种语言转换为另一种语言,也是序列到序列 (sequence-to-sequence) 问题解决方案的一种。序列到序列任务是一个强大的框架,用于接受输入返回某些输出,例如翻译或摘要。翻译系统通常用于不同语言文本之间的翻译,但也可用于语音或两者之间的某种组合,如文本到语音或语音到文本。

本教程将告诉您如何

1.在 OPUS Books 数据集的英法子集上对 T5 进行微调,将英文文本翻译成法文。 2.使用经过微调的模型进行推理。

开始之前,请确保已安装所有必要的库:

pip install transformers datasets evaluate sacrebleu

我们鼓励您登录您的 Hugging Face 账户,以便上传并与社区分享您的模型。出现提示时,请输入您的密码登录:

>>> from huggingface_hub import notebook_login

>>> notebook_login()

加载 OPUS Books 数据集

首先从 🤗 数据集库中加载 OPUS Books 数据集的英语-法语子集:

>>> from datasets import load_dataset

>>> books = load_dataset("opus_books", "en-fr")

使用 train_test_split 方法将数据集拆分成训练集和测试集:

>>> books = books["train"].train_test_split(test_size=0.2)

看看其中的一个例子:

>>> books["train"][0]
{'id': '90560',
 'translation': {'en': 'But this lofty plateau measured only a few fathoms, and soon we reentered Our Element.',
  'fr': 'Mais ce plateau élevé ne mesurait que quelques toises, et bientôt nous fûmes rentrés dans notre élément.'}}

translation:文本的英文和法文译文。

预处理

下一步是加载 T5 分词器来处理英法语言对:

>>> from transformers import AutoTokenizer

>>> checkpoint = "t5-small"
>>> tokenizer = AutoTokenizer.from_pretrained(checkpoint)

您要创建的预处理函数需要

  1. 在输入前加上提示,让 T5 知道这是一项翻译任务。一些能完成多种 NLP 任务的模型需要对特定任务进行提示。
  2. 对输入文本(英文)和目标文本(法文)分别进行分词,因为用英语词汇预训练的分词器无法对法文文本进行分词。
  3. 截断序列,使其长度不超过 max_length 参数设置的最大长度。
>>> source_lang = "en"
>>> target_lang = "fr"
>>> prefix = "translate English to French: "


>>> def preprocess_function(examples):
...     inputs = [prefix + example[source_lang] for example in examples["translation"]]
...     targets = [example[target_lang] for example in examples["translation"]]
...     model_inputs = tokenizer(inputs, text_target=targets, max_length=128, truncation=True)
...     return model_inputs

要在整个数据集上应用预处理函数,请使用 🤗 Datasets map 方法。通过设置 batched=True 以同时处理数据集的多个元素,可以加快 map 函数的速度:

>>> tokenized_books = books.map(preprocess_function, batched=True)

现在使用 DataCollatorForSeq2Seq 创建一批示例。在整理过程中,将句子 动态填充 到批次中最长的长度,而不是将整个数据集填充到最大长度,这样效率更高。

Pytorch
Hide Pytorch content
>>> from transformers import DataCollatorForSeq2Seq

>>> data_collator = DataCollatorForSeq2Seq(tokenizer=tokenizer, model=checkpoint)
TensorFlow
Hide TensorFlow content
>>> from transformers import DataCollatorForSeq2Seq

>>> data_collator = DataCollatorForSeq2Seq(tokenizer=tokenizer, model=checkpoint, return_tensors="tf")

评估

在训练过程中引入指标(metric)通常有助于评估模型效果。您可以使用 🤗 Evaluate 库快速加载评估方法。为此,请加载 SacreBLEU 指标(请参阅 🤗 Evaluate quick tour 了解有关如何加载和计算指标的更多信息):

>>> import evaluate

>>> metric = evaluate.load("sacrebleu")

然后创建一个函数,将预测结果和标签传递给 compute,以计算 SacreBLEU 分数:

>>> import numpy as np


>>> def postprocess_text(preds, labels):
...     preds = [pred.strip() for pred in preds]
...     labels = [[label.strip()] for label in labels]

...     return preds, labels


>>> def compute_metrics(eval_preds):
...     preds, labels = eval_preds
...     if isinstance(preds, tuple):
...         preds = preds[0]
...     decoded_preds = tokenizer.batch_decode(preds, skip_special_tokens=True)

...     labels = np.where(labels != -100, labels, tokenizer.pad_token_id)
...     decoded_labels = tokenizer.batch_decode(labels, skip_special_tokens=True)

...     decoded_preds, decoded_labels = postprocess_text(decoded_preds, decoded_labels)

...     result = metric.compute(predictions=decoded_preds, references=decoded_labels)
...     result = {"bleu": result["score"]}

...     prediction_lens = [np.count_nonzero(pred != tokenizer.pad_token_id) for pred in preds]
...     result["gen_len"] = np.mean(prediction_lens)
...     result = {k: round(v, 4) for k, v in result.items()}
...     return result

现在,您的 compute_metrics 函数已准备就绪,后续您将在设置训练参数时用到该函数。

Train

Pytorch
Hide Pytorch content

如果你不熟悉如何使用 Trainer 对模型进行微调,请查看基础教程 此处

现在就可以开始训练模型了!使用 AutoModelForSeq2SeqLM 加载 T5:

>>> from transformers import AutoModelForSeq2SeqLM, Seq2SeqTrainingArguments, Seq2SeqTrainer

>>> model = AutoModelForSeq2SeqLM.from_pretrained(checkpoint)

至此,只剩下三个步骤:

  1. Seq2SeqTrainingArguments 中定义训练超参数。唯一需要的参数是 output_dir ,它指定了保存模型的位置。通过设置 push_to_hub=True,你将把模型推送到 Hub(你需要登录 Hugging Face 才能上传模型)。在每个 epoch 结束时,训练器 会评估 SacreBLEU 指标并保存训练检查点。
  2. 将训练参数与模型、数据集、分词器、数据整理器和compute_metrics函数一起传递给 Seq2SeqTrainer
  3. 调用 train() 对模型进行微调。
>>> training_args = Seq2SeqTrainingArguments(
...     output_dir="my_awesome_opus_books_model",
...     evaluation_strategy="epoch",
...     learning_rate=2e-5,
...     per_device_train_batch_size=16,
...     per_device_eval_batch_size=16,
...     weight_decay=0.01,
...     save_total_limit=3,
...     num_train_epochs=2,
...     predict_with_generate=True,
...     fp16=True,
...     push_to_hub=True,
... )

>>> trainer = Seq2SeqTrainer(
...     model=model,
...     args=training_args,
...     train_dataset=tokenized_books["train"],
...     eval_dataset=tokenized_books["test"],
...     tokenizer=tokenizer,
...     data_collator=data_collator,
...     compute_metrics=compute_metrics,
... )

>>> trainer.train()

训练完成后,使用 ~transformers.Trainer.push_too_hub 方法将模型上传到 hugging face,这样每个人都可以使用你的模型:

>>> trainer.push_too_hub()
TensorFlow
Hide TensorFlow content

如果您不熟悉如何使用 Keras 对模型进行微调,请参阅基础教程 此处

要在 TensorFlow 中对模型进行微调,首先要设置优化器函数、学习率计划和一些训练超参数:
>>> from transformers import AdamWeightDecay

>>> optimizer = AdamWeightDecay(learning_rate=2e-5, weight_decay_rate=0.01)

然后就可以用 TFAutoModelForSeq2SeqLM加载 T5:

>>> from transformers import TFAutoModelForSeq2SeqLM

>>> model = TFAutoModelForSeq2SeqLM.from_pretrained(checkpoint)

使用 prepare_tf_dataset() 将数据集转换为 tf.data.Dataset 格式:

>>> tf_train_set = model.prepare_tf_dataset(
...     tokenized_books["train"],
...     shuffle=True,
...     batch_size=16,
...     collate_fn=data_collator,
... )

>>> tf_test_set = model.prepare_tf_dataset(
...     tokenized_books["test"],
...     shuffle=False,
...     batch_size=16,
...     collate_fn=data_collator,
... )

使用 compile 配置模型进行训练。请注意,Transformers 模型都有一个默认的任务相关损失函数,所以除非你想指定,否则不需要指定:

>>> import tensorflow as tf

>>> model.compile(optimizer=optimizer) # 没有损失参数!

开始训练前需要设置的最后两件事是根据预测结果计算 SacreBLEU 指标,以及提供一种将模型推送到 Hub 的方法。这两项工作都可以通过使用 Keras callbacks 来完成。

将你的 compute_metrics 函数传递给 KerasMetricCallback

>>> from transformers.keras_callbacks import KerasMetricCallback

>>> metric_callback = KerasMetricCallback(metric_fn=compute_metrics, eval_dataset=tf_validation_set)

PushToHubCallback 中指定模型上传的位置和分词器:

>>> from transformers.keras_callbacks import PushToHubCallback

>>> push_to_hub_callback = PushToHubCallback(
...     output_dir="my_awesome_opus_books_model",
...     tokenizer=tokenizer,
... )

然后将回调放在一个数组里面:

>>> callbacks = [metric_callback, push_to_hub_callback]

最后,您就可以开始训练模型了!调用 fit ,输入训练数据集和验证数据集、epochs 数量以及回调来微调模型:

>>> model.fit(x=tf_train_set, validation_data=tf_test_set, epochs=3, callbacks=callbacks)

训练完成后,您的模型将自动上传到 hugging face,以便每个人都能使用!

有关如何对翻译模型进行微调的更深入示例,请参阅相应的 PyTorch笔记本TensorFlow notebook

推理

很好,现在你已经对模型进行了微调,可以用它进行推理了!

想一些要翻译成另一种语言的文本。对于 T5,您需要根据您正在完成的任务为输入内容添加前缀。从英语翻译成法语时,您应在输入前加上如下所示的前缀:

>>> text = "translate English to French: Legumes share resources with nitrogen-fixing bacteria."

试用微调模型进行推理的最简单方法是在 pipline 中使用它。用你的模型实例化一个用于翻译的 pipeline ,并将文本传递给它:

>>> from transformers import pipeline

>>> translator = pipeline("translation", model="my_awesome_opus_books_model")
>>> translator(text)
[{'translation_text': 'Legumes partagent des ressources avec des bactéries azotantes.'}]

如果愿意,您还可以手动实现 pipline 得到相同的结果:

Pytorch
Hide Pytorch content

对文本进行分词,并以 PyTorch 张量的形式返回input_ids

>>> from transformers import AutoTokenizer

>>> tokenizer = AutoTokenizer.from_pretrained("my_awesome_opus_books_model")
>>> inputs = tokenizer(text, return_tensors="pt").input_ids

使用 generate() 方法生成翻译。有关不同文本生成策略和控制生成参数的更多详情,请查阅 Text Generation API。

>>> from transformers import AutoModelForSeq2SeqLM

>>> model = AutoModelForSeq2SeqLM.from_pretrained("my_awesome_opus_books_model")
>>> outputs = model.generate(inputs, max_new_tokens=40, do_sample=True, top_k=30, top_p=0.95)

将生成的 token ID 解码回文本:

>>> tokenizer.decode(outputs[0], skip_special_tokens=True)
'Les lignées partagent des ressources avec des bactéries enfixant l'azote.'
TensorFlow
Hide TensorFlow content

对文本进行分词,并以 TensorFlow 张量的形式返回input_ids

>>> from transformers import AutoTokenizer

>>> tokenizer = AutoTokenizer.from_pretrained("my_awesome_opus_books_model")
>>> inputs = tokenizer(text, return_tensors="tf").input_ids

使用 generate() 方法生成翻译。有关不同文本生成策略和控制生成参数的详细信息,请查看 Text Generation API。

>>> from transformers import TFAutoModelForSeq2SeqLM

>>> model = TFAutoModelForSeq2SeqLM.from_pretrained("my_awesome_opus_books_model")
>>> outputs = model.generate(inputs, max_new_tokens=40, do_sample=True, top_k=30, top_p=0.95)

将生成的 token ID 解码回文本:

>>> tokenizer.decode(outputs[0], skip_special_tokens=True)
'Les lugumes partagent les ressources avec des bactéries fixatrices d'azote.'