Transformers documentation

多项选择

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

多项选择

多项选择题任务类似于问答任务,不同之处在于,除了上下文之外,还会提供多个候选答案,模型被训练以选择正确的答案。

本指南将向您展示如何:

  1. 在 SWAG 数据集的 regular 配置上微调 BERT,根据多个选项和部分上下文选择最佳答案。
  2. 使用微调后的模型进行推理。

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

pip install transformers datasets evaluate

我们建议您登录 Hugging Face 账户,以便上传模型并与社区共享。当系统提示时,请输入您的令牌以完成登录:

>>> from huggingface_hub import notebook_login

>>> notebook_login()

加载 SWAG 数据集

首先,从 🤗 Datasets 库中加载 SWAG 数据集的 regular 配置:

>>> from datasets import load_dataset

>>> swag = load_dataset("allenai/swag", "regular")

然后来看一个示例:

>>> swag["train"][0]
{'ending0': 'passes by walking down the street playing their instruments.',
 'ending1': 'has heard approaching them.',
 'ending2': "arrives and they're outside dancing and asleep.",
 'ending3': 'turns the lead singer watches the performance.',
 'fold-ind': '3416',
 'gold-source': 'gold',
 'label': 0,
 'sent1': 'Members of the procession walk down the street holding small horn brass instruments.',
 'sent2': 'A drum line',
 'startphrase': 'Members of the procession walk down the street holding small horn brass instruments. A drum line',
 'video-id': 'anetv_jkn6uvmqwh4'}

虽然这里看起来有很多字段,但实际上非常简单明了:

  • sent1 和 sent2:这些字段展示了句子的开头部分,将两者组合起来即可得到 startphrase 字段。
  • ending:提示句子可能的结尾方式,但其中只有一种是正确的。
  • label:标识正确的句子结尾。

预处理

下一步是加载一个 BERT 分词器,以处理句子开头和四种可能的结尾:

>>> from transformers import AutoTokenizer

>>> tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-uncased")

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

  1. 创建 sent1 字段的四个副本,并将每个副本与 sent2 组合,以重现句子的开头。
  2. 将 sent2 与四种可能的句子结尾分别组合。
  3. 将这两个列表展平以便进行分词,之后再将其恢复原状,使每个示例都拥有对应的 input_ids、attention_mask 和 labels 字段。
>>> ending_names = ["ending0", "ending1", "ending2", "ending3"]


>>> def preprocess_function(examples):
...     first_sentences = [[context] * 4 for context in examples["sent1"]]
...     question_headers = examples["sent2"]
...     second_sentences = [
...         [f"{header} {examples[end][i]}" for end in ending_names] for i, header in enumerate(question_headers)
...     ]

...     first_sentences = sum(first_sentences, [])
...     second_sentences = sum(second_sentences, [])

...     tokenized_examples = tokenizer(first_sentences, second_sentences, truncation=True)
...     return {k: [v[i : i + 4] for i in range(0, len(v), 4)] for k, v in tokenized_examples.items()}

要对整个数据集应用预处理函数,请使用 🤗 Datasets 的 map 方法。你可以通过设置 batched=True 来一次处理数据集中的多个元素,从而加速 map 函数:

>>> tokenized_swag = swag.map(preprocess_function, batched=True)

要创建一批示例,在数据整理(collation)阶段将句子动态填充到该批次中最长的长度,比将整个数据集填充到最大长度更高效。DataCollatorForMultipleChoice 会先展平所有模型输入,应用填充,然后再将结果恢复为原始形状。

>>> from transformers import DataCollatorForMultipleChoice
>>> collator = DataCollatorForMultipleChoice(tokenizer=tokenizer)

评估

在训练过程中加入评估指标通常有助于评估模型的性能。您可以使用 🤗 Evaluate 库快速加载评估方法。对于本任务,请加载 accuracy 指标(请参阅 🤗 Evaluate 的 快速入门 以了解如何加载和计算指标):

>>> import evaluate

>>> accuracy = evaluate.load("accuracy")

然后创建一个函数,将你的预测值和标签传递给 compute 以计算准确率:

>>> import numpy as np


>>> def compute_metrics(eval_pred):
...     predictions, labels = eval_pred
...     predictions = np.argmax(predictions, axis=1)
...     return accuracy.compute(predictions=predictions, references=labels)

您的 compute_metrics 函数已准备就绪,在配置训练时您将再次用到它。

训练

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

现在可以开始训练模型了!使用 AutoModelForMultipleChoice 加载 BERT:

>>> from transformers import AutoModelForMultipleChoice, TrainingArguments, Trainer

>>> model = AutoModelForMultipleChoice.from_pretrained("google-bert/bert-base-uncased")

此时,只剩下三个步骤:

  1. 在 TrainingArguments 中定义训练超参数。唯一必需的参数是 output_dir,用于指定模型的保存位置。通过设置 push_to_hub=True,你可以将该模型推送到 Hub(上传模型前需要登录 Hugging Face 账户)。在每个 epoch 结束时,Trainer 会评估准确率并保存训练检查点。
  2. 将训练参数与模型、数据集、分词器、数据整理器以及 compute_metrics 函数一起传递给 Trainer。
  3. 调用 train() 来微调你的模型。
>>> training_args = TrainingArguments(
...     output_dir="my_awesome_swag_model",
...     eval_strategy="epoch",
...     save_strategy="epoch",
...     load_best_model_at_end=True,
...     learning_rate=5e-5,
...     per_device_train_batch_size=16,
...     per_device_eval_batch_size=16,
...     num_train_epochs=3,
...     weight_decay=0.01,
...     push_to_hub=True,
... )

>>> trainer = Trainer(
...     model=model,
...     args=training_args,
...     train_dataset=tokenized_swag["train"],
...     eval_dataset=tokenized_swag["validation"],
...     processing_class=tokenizer,
...     data_collator=collator,
...     compute_metrics=compute_metrics,
... )

>>> trainer.train()

训练完成后,使用 push_to_hub() 方法将您的模型共享到 Hub,以便所有人都能使用您的模型:

>>> trainer.push_to_hub()

如需了解如何针对多项选择任务微调模型的更详细示例,请参阅对应的 PyTorch notebook。

推理

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

想出一些文本和两个候选答案:

>>> prompt = "France has a bread law, Le Décret Pain, with strict rules on what is allowed in a traditional baguette."
>>> candidate1 = "The law does not apply to croissants and brioche."
>>> candidate2 = "The law applies to baguettes."

对每个提示和候选答案对进行分词,并返回 PyTorch 张量。您还应该创建一些 labels:

>>> from transformers import AutoTokenizer

>>> tokenizer = AutoTokenizer.from_pretrained("username/my_awesome_swag_model")
>>> inputs = tokenizer([[prompt, candidate1], [prompt, candidate2]], return_tensors="pt", padding=True)
>>> labels = torch.tensor(0).unsqueeze(0)

将输入和标签传入模型,并返回 logits:

>>> from transformers import AutoModelForMultipleChoice

>>> model = AutoModelForMultipleChoice.from_pretrained("username/my_awesome_swag_model")
>>> outputs = model(**{k: v.unsqueeze(0) for k, v in inputs.items()}, labels=labels)
>>> logits = outputs.logits

获取概率最高的类别:

>>> predicted_class = logits.argmax().item()
>>> predicted_class
0
Update on GitHub