Transformers Trainer 训练器完全指南:从微调工作流到子类化扩展
【免费下载链接】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
Trainer是 🤗 Transformers 内置的完整训练与评估循环,它封装了批处理(batching)、打乱(shuffling)、填充(padding)、前向传播、损失计算、反向传播与权重更新等全部底层细节。本文以仓库文档 docs/source/en/trainer.md 为骨架,结合 training.md 微调教程与 trainer_customize.md 扩展指南,深入讲解如何用Trainer快速完成大模型微调、如何用TrainingArguments精细化配置训练、以及如何通过子类化改写训练循环实现 DPO/GRPO 等进阶玩法。读完本文,你将掌握一套可直接落地的端到端微调方案,并能按需对Trainer做定制化改造。
Trainer 是什么:一条开箱即用的训练/评估循环
Trainer的核心定位非常明确:你只需要一个模型和一份数据集,就能开始训练。文档中把它描述为 "a complete training and evaluation loop for Transformers models",也就是说,它替你处理了以下所有机械化工作:
- 数据管线:将数据集按批次切分、随机打乱、pad 成张量,由 data collator 组装每个 batch;
- 训练循环:执行 forward pass → 计算 loss → 反向传播梯度 → 更新权重;
- 训练配置:通过
TrainingArguments一站式定制批量大小、训练时长、分布式策略、模型编译等一切选项。
从源码看,Trainer.train是主训练入口,它依次处理模型重初始化(model_init)、梯度检查点激活、NEFTune 钩子、断点续训(resume_from_checkpoint),最终把核心工作交给_inner_training_loop完成实际的迭代。整个类在 src/transformers/trainer.py 中实现,包含约 4500 行代码,覆盖数据加载、优化器调度器构建、日志、评估、checkpoint 保存等完整生命周期。
与Trainer配套的关键参考文档(均已存在于当前仓库):
- 微调教程:入门第一个大模型微调项目;
- Trainer 方法子类化:改写法定制训练行为;
- 数据整理器 Data collators:自定义批次组装方式;
- 回调 Callbacks:挂钩训练事件;
- 梯度检查点:内存与速度的权衡细节;
- Trainer 特性配方:自定义损失、内存高效评估等最小可运行示例。
端到端微调实战:以 Qwen3 因果语言模型为例
下面完整走一遍微调流程,这是Trainer最典型的使用场景:在较少的算力、数据和时间预算下,让预训练模型适配某个特定任务或领域(例如用编程语料微调提升代码能力)。微调与预训练的唯一区别是不从头随机初始化权重。
第一步:登录 Hugging Face 账号
要把微调好的模型推送到 Hub,先用用户令牌登录:
from huggingface_hub import login login()第二步:数据准备与分词
加载数据集,并对模型将要训练的文本列(示例数据集中的horoscope列)做分词:
from datasets import load_dataset from transformers import AutoTokenizer, DataCollatorForLanguageModeling model_name = "Qwen/Qwen3-0.6B" tokenizer = AutoTokenizer.from_pretrained(model_name) dataset = load_dataset("karthiksagarn/astro_horoscope", split="train") def tokenize(batch): return tokenizer( batch["horoscope"], truncation=True, max_length=512, ) dataset = dataset.map(tokenize, batched=True, remove_columns=dataset.column_names) dataset = dataset.train_test_split(test_size=0.1)分词器产出模型的输入input_ids和attention_mask。由于模型 forward 方法只接受这两类输入,通过remove_columns在分词后把horoscope等原始列删掉。要点:
- 设置
truncation=True并配合max_length,把过长的序列截断到指定最大长度; - 用 [
datasets.train_test_split] 划分出测试集,供后续评估使用。
接下来用data collator把样本组装成模型可处理的 batch。DataCollatorForLanguageModeling采用动态填充策略:每个 batch 只填充到该 batch 内最长序列的长度,而不是把全数据集所有序列统一 pad 到同一长度,从而避免计算大量无意义的 padding token,节省显存与算力。对因果语言建模,需要设置mlm=False避免随机遮蔽 token:
data_collator = DataCollatorForLanguageModeling(tokenizer, mlm=False)第三步:加载预训练模型
加载待微调的预训练 checkpoint,关键参数是dtype="auto"——它让权重按保存时的原始 dtype 加载。如果不加,PyTorch 会默认以torch.float32加载;当权重原本是torch.bfloat16时,内存占用会翻倍:
from transformers import AutoModelForCausalLM, TrainingArguments, Trainer model_name = "Qwen/Qwen3-0.6B" model = AutoModelForCausalLM.from_pretrained(model_name, dtype="auto")第四步:用 TrainingArguments 配置训练
TrainingArguments提供全部训练选项。文档将其分为四类核心配置:
训练时长类
num_train_epochs:训练轮数;per_device_train_batch_size:单设备 batch 大小;learning_rate:优化器初始学习率。
训练优化类
bf16=True:硬件支持时(Ampere 及更新架构 GPU)启用 BF16 混合精度加速;老硬件退回fp16=True;gradient_accumulation_steps:通过多次前向累加梯度再统一更新权重,模拟更大的有效 batch size;gradient_checkpointing:以计算换显存,反向传播时重算中间激活而非存储。折中方案可参考 partial checkpointing;- 当
gradient_checkpointing=True时,设置gradient_checkpointing_kwargs={"offload": True}可把保存的激活驻留在页锁定主机内存,显著降低长序列下的 GPU 显存占用,代价是速度变慢(详见 offloading the saved activations); train_sampling_strategy="group_by_length":把长度相近的样本分到同一 batch,减少 padding。对基于 processor 的多模态数据集和预计算长度场景,见 trainer_recipes 中的 "group samples by length"。
评估与保存类
eval_strategy与save_strategy:决定训练中何时评估模型、何时保存 checkpoint;load_best_model_at_end:训练结束时加载最优 checkpoint,前提是必须设置eval_strategy。
日志类
logging_steps:控制训练过程中 loss 的更新与输出频率。
从源码实现看,这些参数在 src/transformers/training_args.py 中以 dataclass field 形式定义并附带了详细的help元数据(例如gradient_checkpointing_kwargs在 第 910 行 解释了every_n_layers与offload的行为,train_sampling_strategy在 第 1362 行 定义了random/sequential/group_by_length/batch_rebalance四种取值)。关于gradient_checkpointing_kwargs的更多细节:every_n_layers只对每第 n 个解码器层做 checkpointing(1即全部层都检查点化的常规行为,更大的值用少量显存换回速度);其他键会被透传给torch.utils.checkpoint.checkpoint。这些解释与 trainer.py 中train方法对gradient_checkpointing_kwargs的实际解析逻辑完全一致。
一个完整的训练配置示例:
training_args = TrainingArguments( output_dir="qwen3-finetuned", num_train_epochs=3, per_device_train_batch_size=2, gradient_accumulation_steps=8, gradient_checkpointing=True, gradient_checkpointing_kwargs={"every_n_layers": 4}, bf16=True, learning_rate=2e-5, logging_steps=10, eval_strategy="epoch", save_strategy="epoch", load_best_model_at_end=True, )第五步:创建 Trainer 并启动训练
把所有组件组装进Trainer实例,调用train()即可开始;训练结束后用push_to_hub()把结果上传:
trainer = Trainer( model=model, args=training_args, train_dataset=dataset["train"], eval_dataset=dataset["test"], processing_class=tokenizer, data_collator=DataCollatorForLanguageModeling(tokenizer, mlm=False), ) trainer.train() trainer.push_to_hub()Trainer.push_to_hub会把微调后的权重、generation config、tokenizer 和模型 config 一并上传到 Hub(提交信息默认为 "End of training",可通过commit_message参数修改,也支持blocking、token、revision等参数)。
进阶:子类化 Trainer 方法定制训练行为
当标准Trainer无法满足需求时,不必重写整个训练循环——子类化对应方法即可,它修改的是训练循环中"做了什么"(如 forward pass、loss 计算)。在动手之前先判断需求性质:
- 需要改变何时 / 是否执行某个动作(日志、评估、早停)→ 用 Callback;
- 需要改变计算什么(损失计算、数据加载、优化)→ 子类化
Trainer方法。
[!NOTE] 完整的可子类化方法清单见
TrainerAPI 文档。以下划线开头的私有方法(如_save_checkpoint、_evaluate)也可以覆写,但可能随时变动,不保证向后兼容。
覆写 get_train_dataloader:GRPO 的批量生成优化
标准实现get_train_dataloader(源码见 trainer.py)的逻辑是:加载一个 batch → 训练 → 丢弃 → 加载下一个 batch:
def get_train_dataloader(self): return self._get_dataloader( batch_size=self._train_batch_size, ... )GRPO是一种在线强化学习算法,训练前先要生成完成序列。逐 step 生成非常昂贵:512 token 的完成序列需要约 512 次顺序前向,而一个训练 step 只需要 1 次前向。GRPOTrainer通过子类化get_train_dataloader把多个 step 的生成提示词一次性批量加载:将 batch size 乘以steps_per_generation参数。若train_batch_size=4、steps_per_generation=8,dataloader 产出 batch 大小为 32,生成成本降低 8 倍:
def get_train_dataloader(self): dataloader_params = { "batch_size": self._train_batch_size * self.args.steps_per_generation, # this is the only change ... }覆写 compute_loss:DPO 的自定义损失
标准compute_loss(源码见 trainer.py)返回模型计算的交叉熵损失,并支持return_outputs、num_items_in_batch等可选参数:
def compute_loss(self, model, inputs, return_outputs=False, num_items_in_batch=None): ... outputs = model(**inputs) ... loss = outputs["loss"] # get loss from model return (loss, outputs) if return_outputs else lossDPO(Direct Preference Optimization)衡量策略模型相对参考模型对"选中回答 vs 被拒回答"的偏好强度,其损失计算与标准交叉熵在多个层面不同,因此DPOTrainer需要覆写compute_loss:
- 模型看不到 labels,只返回 logits,由 DPO 自行计算 log-probs;
- chosen 与 rejected 回答被拼接在同一 batch 中;
- 参考模型独立计算自己的 log-probs;
- 损失是
π_chosen、π_rejected、π_ref_chosen、π_ref_rejected的函数。
这些都不符合标准Trainer.compute_loss的形态,覆写后的实现如下:
def compute_loss( self, model: PreTrainedModel | nn.Module, inputs: dict[str, torch.Tensor | Any], return_outputs=False, num_items_in_batch=None, ) -> torch.Tensor | tuple[torch.Tensor, dict[str, float]]: ... outputs = model(**inputs) logits = outputs.logits logps = get_logps(logits, inputs) chosen_logps, rejected_logps = logps.chunk(2, dim=0) # batch is [chosen, rejected] ref_logits = self.ref_model(**inputs).logits ref_logps = get_logps(ref_logits, inputs) ref_chosen_logps, ref_rejected_logps = ref_logps.chunk(2, dim=0) # batch is [chosen, rejected] chosen_scores = chosen_logps - ref_chosen_logps rejected_scores = rejected_logps - ref_rejected_logps per_sequence_loss = -F.logsigmoid(self.beta * chosen_scores - rejected_scores) loss = per_sequence_loss.mean() return (loss, outputs) if return_outputs else loss注意子类化compute_loss时,若自定义损失不使用num_items_in_batch,应把self.model_accepts_loss_kwargs覆写为False,否则梯度累积场景下损失计算可能略微不准(这是compute_lossdocstring 中明确提示的注意事项)。更多真实案例可参考GRPOTrainer、DPOTrainer对Trainer的扩展方式,以及基于它构建自定义 trainer 的开源项目。
下一步学习路径
- 从微调教程开始,掌握用
Trainer训练大语言模型的完整流程; - 阅读子类化 Trainer 方法了解更丰富的覆写示例;
- 参考数据整理器学习自定义 batch 组装;
- 阅读回调学习挂钩训练事件(日志、早停等);
- 浏览 Trainer 特性配方获取自定义损失函数、内存高效评估、checkpointing 等最小可运行示例;
- 仓库中的 examples/pytorch 目录(如 text-generation 下的
run_generation.py)提供了文本、音频、视觉、多模态等不同任务的额外训练示例,可直接对照参考。
【免费下载链接】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),仅供参考