文本摘要¶
文本摘要是将文档或文章的重要信息压缩成更短版本的任务。与翻译一样,它也是可以表述为序列到序列任务的另一个例子。摘要可以是:
- 提取式:从文档中提取最相关的信息。
- 抽象式:生成新的文本,捕捉最相关的信息。
本指南将向您展示如何:
- 在 BillSum 数据集的加利福尼亚州法案子集上微调 T5 模型,用于抽象式摘要。
- 使用微调后的模型进行推理。
要查看所有与该任务兼容的架构和检查点,我们建议您查看任务页面。
在开始之前,请确保您已安装所有必要的库:
pip install transformers datasets evaluate rouge_score
我们鼓励您登录您的 Hugging Face 账户,这样您就可以上传并与社区分享您的模型。当提示时,输入您的令牌以登录:
from huggingface_hub import notebook_login
notebook_login()
加载 BillSum 数据集¶
首先,从 🤗 Datasets 库中加载 BillSum 数据集的较小的加利福尼亚州法案子集:
from datasets import load_dataset
billsum = load_dataset("billsum", split="ca_test")
使用 train_test_split 方法将数据集分成训练集和测试集:
billsum = billsum.train_test_split(test_size=0.2)
然后查看一个示例:
billsum["train"][0]
from transformers import AutoTokenizer
checkpoint = "google-t5/t5-small"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
您需要创建的预处理函数需要执行以下操作:
- 在输入前加上提示,以便 T5 知道这是一个摘要任务。一些能够处理多种 NLP 任务的模型需要针对特定任务进行提示。
- 在对标签进行分词时使用
text_target参数。 - 截断序列,使其长度不超过
max_length参数设置的最大长度。
prefix = "summarize: "
def preprocess_function(examples):
inputs = [prefix + doc for doc in examples["text"]]
model_inputs = tokenizer(inputs, max_length=1024, truncation=True)
labels = tokenizer(text_target=examples["summary"], max_length=128, truncation=True)
model_inputs["labels"] = labels["input_ids"]
return model_inputs
要使用 🤗 Datasets 的 map 方法在整个数据集上应用预处理函数,请设置 batched=True 以同时处理数据集中的多个元素,从而加快 map 函数的速度:
tokenized_billsum = billsum.map(preprocess_function, batched=True)
现在使用 DataCollatorForSeq2Seq 创建一个示例批次。在整理过程中,动态地将句子填充到批次中最长的长度,而不是将整个数据集填充到最大长度,这样做更有效率。
from transformers import DataCollatorForSeq2Seq
data_collator = DataCollatorForSeq2Seq(tokenizer=tokenizer, model=checkpoint)
评估¶
在训练过程中包含一个指标通常有助于评估模型的性能。您可以使用 🤗 Evaluate 库快速加载评估方法。对于此任务,加载 ROUGE 指标(请参阅 🤗 Evaluate 快速入门,以了解更多关于如何加载和计算指标的信息):
import evaluate
rouge = evaluate.load("rouge")
然后创建一个函数,将您的预测和标签传递给 compute 以计算 ROUGE 指标:
import numpy as np
def compute_metrics(eval_pred):
predictions, labels = eval_pred
decoded_preds = tokenizer.batch_decode(predictions, skip_special_tokens=True)
labels = np.where(labels != -100, labels, tokenizer.pad_token_id)
decoded_labels = tokenizer.batch_decode(labels, skip_special_tokens=True)
result = rouge.compute(predictions=decoded_preds, references=decoded_labels, use_stemmer=True)
prediction_lens = [np.count_nonzero(pred != tokenizer.pad_token_id) for pred in predictions]
result["gen_len"] = np.mean(prediction_lens)
return {k: round(v, 4) for k, v in result.items()}
您的 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 结束时,Trainer 将评估 ROUGE 指标并保存训练检查点。 - 将训练参数传递给
Seq2SeqTrainer,以及模型、数据集、分词器、数据整理器、compute_metrics函数。 - 调用
train()以微调您的模型。
training_args = Seq2SeqTrainingArguments(
output_dir="my_awesome_billsum_model",
eval_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=4,
predict_with_generate=True,
fp16=True, # 对于 XPU,更改为 bf16=True
push_to_hub=True,
)
trainer = Seq2SeqTrainer(
model=model,
args=training_args,
train_dataset=tokenized_billsum["train"],
eval_dataset=tokenized_billsum["test"],
tokenizer=tokenizer,
data_collator=data_collator,
compute_metrics=compute_metrics,
)
trainer.train()
一旦训练完成,使用 push_to_hub() 方法将您的模型分享到 Hub,以便每个人都可以使用您的模型:
trainer.push_to_hub()
text = "summarize: The Inflation Reduction Act lowers prescription drug costs, health care costs, and energy costs. It's the most aggressive action on tackling the climate crisis in American history, which will lift up American workers and create good-paying, union jobs across the country. It'll lower the deficit and ask the ultra-wealthy and corporations to pay their fair share. And no one making under $400,000 per year will pay a penny more in taxes."
尝试使用微调后的模型进行推理的最简单方法是将其用于 pipeline()。为摘要实例化一个 pipeline,并将您的文本传递给它:
from transformers import pipeline
summarizer = pipeline("summarization", model="username/my_awesome_billsum_model")
summarizer(text)
如果您愿意,您也可以手动复制 pipeline 的结果:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("username/my_awesome_billsum_model")
inputs = tokenizer(text, return_tensors="pt").input_ids
from transformers import AutoModelForSeq2SeqLM
model = AutoModelForSeq2SeqLM.from_pretrained("username/my_awesome_billsum_model")
outputs = model.generate(inputs, max_new_tokens=100, do_sample=False)
tokenizer.decode(outputs[0], skip_special_tokens=True)