Transformers 选择题(Multiple Choice)微调实战:基于 BERT 与 SWAG 数据集的完整指南
Transformers 选择题Multiple Choice微调实战基于 BERT 与 SWAG 数据集的完整指南【免费下载链接】transformers Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers本指南面向希望在 Transformers 框架下完成选择题Multiple Choice任务微调的开发者。你将基于 SWAG 数据集的regular配置对 BERT 进行 fine-tuning让模型学会在给定上下文后从多个候选中选出正确答案并掌握预处理、动态填充dynamic padding、训练与推理的完整流程。读完本文你将能够独立复现一条从原始数据集到可部署选择题模型的端到端链路。什么是选择题Multiple Choice任务选择题任务与问答Question Answering任务非常相似区别在于它会随上下文一并提供多个候选答案模型被训练为从这些候选中选出正确的那一个。它天然适配阅读理解、常识推理、考试题目等场景也是评测模型文本理解能力的重要基准任务之一。在 Transformers 中选择题任务的入口类是AutoModelForMultipleChoice。以本文使用的 BERT 为例对应实现为 BertForMultipleChoice它在 BERT 编码器之上挂接了一个 dropout 层和一个将隐藏状态映射为单一标量分数的线性分类头nn.Linear(config.hidden_size, 1)每个候选答案得到一个分数最终通过 softmax 归一化后选择得分最高的候选。环境准备开始之前请确认已安装所需依赖库pip install transformers datasets evaluatetransformers提供模型、分词器、Trainer与数据整理器datasets提供数据集加载与map预处理接口evaluate提供准确率accuracy等评估指标。如果你希望将训练好的模型上传分享到 Hugging Face Hub可先登录账号按提示输入 token from huggingface_hub import notebook_login notebook_login()加载 SWAG 数据集SWAGSituations With Adversarial Generations是一个用于常识推理的候选句选择数据集。使用 Datasets 库加载其regular配置 from datasets import load_dataset swag load_dataset(swag, regular)查看一个训练样本 swag[train][0] {ending0: passes by walking down the street playing their instruments., ending1: has heard approaching them., ending2: arrives and theyre 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字段ending0~ending3四个可能的句子结尾候选其中只有一个正确label标记正确结尾的索引本例为 0。任务目标即给定sent1 sent2组成的句子开头模型需要从四个ending中选出与label一致的正确答案。数据预处理Preprocess加载 BERT 分词器用于处理句子开头与四个候选结尾 from transformers import AutoTokenizer tokenizer AutoTokenizer.from_pretrained(google-bert/bert-base-uncased)预处理函数需要完成三件事将sent1复制四份并分别与sent2组合还原句子的开头将sent2与四个候选结尾分别拼接将两个列表展平flatten以便批量 tokenize之后再反展平unflatten使每个样本拥有对应的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, truncationTrue) ... return {k: [v[i : i 4] for i in range(0, len(v), 4)] for k, v in tokenized_examples.items()}逐行拆解这段核心逻辑first_sentences [[context] * 4 for context in examples[sent1]]每个上下文复制 4 份形成(batch, 4)的嵌套结构second_sentences对每个样本把sent2句头与ending{i}候选结尾拼成A drum line passes by walking down the street playing their instruments.这样的完整第二句sum(first_sentences, [])利用列表加法将二维列表展平成一维保证first_sentences与second_sentences按序一一对应tokenizer(first_sentences, second_sentences, truncationTrue)以句子对形式批量 tokenize启用截断以适配模型最大长度最后按每 4 个一组切片把结果反展平回(batch, 4, seq_len)的嵌套结构供选择题模型使用。随后用 Datasets 的map方法将预处理函数应用到整个数据集。设置batchedTrue可一次处理多个元素显著加速 tokenized_swag swag.map(preprocess_function, batchedTrue)动态填充DataCollatorForMultipleChoice在组批时更高效的做法是动态填充dynamically pad只把每个 batch 内的句子填充到该 batch 的最长长度而不是把整个数据集统一填充到最大长度。虽然也可以在tokenizer中直接传paddingTrue但动态填充明显更节省显存与算力。DataCollatorForMultipleChoice 专门处理选择题样本的组批。它的核心流程是先取出标签把label/labels从样本中弹出它们不是嵌套结构展平把batch_size个、每个含num_choices个选择的嵌套样本展平成batch_size * num_choices个普通样本源码注释中的示例2个样本各含2个选择展平成4个普通样本统一填充调用tokenizer.pad对所有展平样本按其最长长度填充反展平还原将结果 reshape 回(batch_size, num_choices, seq_len)形状并把标签重新加回 batch。其构造参数与默认值如下来自 data_collator.py参数默认值说明tokenizer必填用于编码数据的PreTrainedTokenizer或PreTrainedTokenizerFastpaddingTrue填充策略True/longest填充到 batch 最长序列max_length填充到max_length指定长度False/do_not_pad不填充max_lengthNone返回列表的最大长度同时也是可选填充长度pad_to_multiple_ofNone将序列填充到该值的整数倍利于在 NVIDIA Volta 及以上计算能力 7.5硬件上启用 Tensor Cores 加速return_tensorspt返回的张量类型可选np或pt实例化非常简单 from transformers import DataCollatorForMultipleChoice collator DataCollatorForMultipleChoice(tokenizertokenizer)评估指标在训练过程中引入评估指标有助于实时监控模型表现。使用 Evaluate 库加载 accuracy 指标 import evaluate accuracy evaluate.load(accuracy)再编写一个把预测与标签传给compute计算准确率的函数。注意模型输出的 logits 形状为(batch_size, num_choices)需要沿axis1取 argmax 得到预测类别 import numpy as np def compute_metrics(eval_pred): ... predictions, labels eval_pred ... predictions np.argmax(predictions, axis1) ... return accuracy.compute(predictionspredictions, referenceslabels)训练Train加载 BERT 的选择题模型 from transformers import AutoModelForMultipleChoice, TrainingArguments, Trainer model AutoModelForMultipleChoice.from_pretrained(google-bert/bert-base-uncased)提示如果你对使用Trainer微调模型还不熟悉可以先阅读本仓库的训练基础教程。接下来只需三步在TrainingArguments中定义训练超参数唯一必填项是output_dir用于指定模型保存位置将训练参数连同模型、数据集、分词器、数据整理器与compute_metrics一起传给Trainer调用trainer.train()启动微调。 training_args TrainingArguments( ... output_dirmy_awesome_swag_model, ... eval_strategyepoch, ... save_strategyepoch, ... load_best_model_at_endTrue, ... learning_rate5e-5, ... per_device_train_batch_size16, ... per_device_eval_batch_size16, ... num_train_epochs3, ... weight_decay0.01, ... push_to_hubTrue, ... ) trainer Trainer( ... modelmodel, ... argstraining_args, ... train_datasettokenized_swag[train], ... eval_datasettokenized_swag[validation], ... processing_classtokenizer, ... data_collatorcollator, ... compute_metricscompute_metrics, ... ) trainer.train()各超参数的作用参数值说明output_dirmy_awesome_swag_model模型与 checkpoint 的保存目录必填eval_strategyepoch每个 epoch 结束时执行一次评估save_strategyepoch每个 epoch 结束时保存一次 checkpointload_best_model_at_endTrue训练结束时自动加载验证集上表现最佳的 checkpointlearning_rate5e-5Adam 优化器的初始学习率BERT 类模型微调的常见取值per_device_train_batch_size16单设备训练 batch 大小per_device_eval_batch_size16单设备评估 batch 大小num_train_epochs3训练轮数weight_decay0.01权重衰减系数用于正则化push_to_hubTrue训练结束后将模型推送至 Hub需已登录训练完成后可通过push_to_hub将模型分享给社区 trainer.push_to_hub()底层原理选择题模型如何计算从 BertForMultipleChoice.forward 的实现可以看到选择题模型的运行机制输入形状为(batch_size, num_choices, sequence_length)模型先把前两个维度合并view(-1, seq_len)得到batch_size * num_choices条独立序列一次性送入 BERT 编码BERT 输出的pooled_output经 dropout 后进入线性分类头产出(batch_size * num_choices, 1)的标量分数分数被 reshape 回(batch_size, num_choices)配合形状为(batch_size,)的labels取值在[0, num_choices-1]计算交叉熵损失。这正是预处理阶段必须把每个样本组织成(batch, 4, seq_len)嵌套结构、并由DataCollatorForMultipleChoice负责展平与还原的原因展平是为了让编码器高效并行计算还原是为了让每个样本的四个候选共享同一个标签并正确计算损失。推理Inference微调完成后即可用训练好的模型做推理。假设我们有一段关于法国面包法律的文本和两个候选答案 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.将每对 prompt 与候选答案一起 tokenize并返回 PyTorch 张量同时构造labels from transformers import AutoTokenizer tokenizer AutoTokenizer.from_pretrained(username/my_awesome_swag_model) inputs tokenizer([[prompt, candidate1], [prompt, candidate2]], return_tensorspt, paddingTrue) 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()}, labelslabels) logits outputs.logits取概率最高的类别 predicted_class logits.argmax().item() predicted_class 0这里logits.argmax().item()返回的正是被模型判定为最合理的候选索引与训练数据的label字段语义一致。进阶仓库中的完整示例脚本如果你想跳过交互式教程直接跑一个可配置的训练脚本仓库在 examples/pytorch/multiple-choice/ 提供了完整的 SWAG 微调实现run_swag.py基于Trainer的完整训练/评估脚本。它通过HfArgumentParser把参数划分为ModelArguments模型与分词器路径、是否启用 fast tokenizer、trust_remote_code等、DataTrainingArgumentsmax_seq_length、pad_to_max_length、max_train_samples、preprocessing_num_workers等和TrainingArguments三组支持从 JSON 配置文件或命令行参数启动run_swag_no_trainer.py不依赖Trainer的版本基于 PyTorch 手写训练循环配合 run_no_trainer.sh 可直接运行更便于深入理解每一步底层逻辑。值得注意的实现细节脚本中max_seq_length默认取tokenizer.model_max_length并封顶 1024run_swag.pypad_to_max_length默认False以启用更高效的动态填充但在 TPU 上建议置为True。预处理逻辑ending_names、context_namesent1、question_header_namesent2与本文教程完全一致当你迁移到自定义数据集时只需替换这几个字段名与候选数量即可。小结本文以 SWAG 数据集为实例完整走通了 Transformers 选择题任务微调的全部环节数据集加载与字段解读、句子对展平-反展平的预处理范式、DataCollatorForMultipleChoice的动态填充原理、基于Trainer的训练与评估、以及部署阶段的推理调用。结合 BertForMultipleChoice 的源码可以看到选择题模型本质上是对编码器输出套一层线性打分头关键在于把每个样本的多个候选组织成嵌套张量并与标签对齐——理解了这一点迁移到其他编码器架构如 RoBERTa、DeBERTa或自定义多选任务都将非常直接。【免费下载链接】transformers Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考