翻译是将文本序列从一种语言转换为另一种语言,也是序列到序列 (sequence-to-sequence) 问题解决方案的一种。序列到序列任务是一个强大的框架,用于接受输入返回某些输出,例如翻译或摘要。翻译系统通常用于不同语言文本之间的翻译,但也可用于语音或两者之间的某种组合,如文本到语音或语音到文本。
本教程将告诉您如何
1.在 OPUS Books 数据集的英法子集上对 T5 进行微调,将英文文本翻译成法文。 2.使用经过微调的模型进行推理。
BART, BigBird-Pegasus, Blenderbot, BlenderbotSmall, Encoder decoder, FairSeq Machine-Translation, GPTSAN-japanese, LED, LongT5, M2M100, Marian, mBART, MT5, MVP, NLLB, NLLB-MOE, Pegasus, PEGASUS-X, PLBart, ProphetNet, SwitchTransformers, T5, UMT5, XLM-ProphetNet
开始之前,请确保已安装所有必要的库:
pip install transformers datasets evaluate sacrebleu
我们鼓励您登录您的 Hugging Face 账户,以便上传并与社区分享您的模型。出现提示时,请输入您的密码登录:
>>> from huggingface_hub import notebook_login
>>> notebook_login()
首先从 🤗 数据集库中加载 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)
您要创建的预处理函数需要
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
创建一批示例。在整理过程中,将句子 动态填充 到批次中最长的长度,而不是将整个数据集填充到最大长度,这样效率更高。
>>> from transformers import DataCollatorForSeq2Seq
>>> data_collator = DataCollatorForSeq2Seq(tokenizer=tokenizer, model=checkpoint)
>>> 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
函数已准备就绪,后续您将在设置训练参数时用到该函数。
如果你不熟悉如何使用 Trainer
对模型进行微调,请查看基础教程 此处 !
现在就可以开始训练模型了!使用 AutoModelForSeq2SeqLM
加载 T5:
>>> from transformers import AutoModelForSeq2SeqLM, Seq2SeqTrainingArguments, Seq2SeqTrainer
>>> model = AutoModelForSeq2SeqLM.from_pretrained(checkpoint)
至此,只剩下三个步骤:
Seq2SeqTrainingArguments
中定义训练超参数。唯一需要的参数是 output_dir
,它指定了保存模型的位置。通过设置 push_to_hub=True
,你将把模型推送到 Hub(你需要登录 Hugging Face 才能上传模型)。在每个 epoch 结束时,训练器
会评估 SacreBLEU 指标并保存训练检查点。compute_metrics
函数一起传递给 Seq2SeqTrainer
。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()
如果您不熟悉如何使用 Keras 对模型进行微调,请参阅基础教程 此处!
>>> 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 张量的形式返回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 张量的形式返回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.'