使用Huggingface Trainer训练时如何动态采样eval_dataset子集?
实现Trainer训练时每次评估随机选取不同的验证子集
可以通过自定义TrainerCallback回调函数,在每次评估触发前动态替换验证数据集的方式实现。具体步骤如下:
- 定义自定义回调类
这个类会在每次评估前,从完整验证集中随机采样指定大小的子集,替换Trainer当前的验证数据集:
from transformers.trainer_callback import TrainerCallback import random class RandomEvalSubsetCallback(TrainerCallback): def __init__(self, full_eval_dataset, subset_size=3000): self.full_eval_dataset = full_eval_dataset self.subset_size = subset_size def on_evaluate(self, args, state, control, **kwargs): # 用当前训练步数作为随机种子,保证可复现且每次采样结果不同 random.seed(state.global_step) # 随机采样指定数量的样本索引 random_indices = random.sample(range(len(self.full_eval_dataset)), self.subset_size) # 替换为采样后的子集(保持torch格式) trainer.eval_dataset = self.full_eval_dataset.select(random_indices).with_format("torch")
- 修改Trainer初始化逻辑
无需预先处理验证集,直接传入完整的验证数据集,并将自定义回调加入Trainer的回调列表:
from transformers import Seq2SeqTrainer, Seq2SeqTrainingArguments # 假设full_eval_data是你的完整验证数据集 full_eval_data = eval_data # 初始化自定义回调,指定子集大小 random_eval_callback = RandomEvalSubsetCallback(full_eval_data, subset_size=3000) # 训练参数保持原配置 training_args = Seq2SeqTrainingArguments( output_dir="./", evaluation_strategy="steps", per_device_train_batch_size=50, per_device_eval_batch_size=10, predict_with_generate=True, logging_steps=2, save_steps=16, eval_steps=4, warmup_steps=1, max_steps=16, save_total_limit=1, ) # 实例化Trainer时传入完整验证集和自定义回调 trainer = Seq2SeqTrainer( model=multibert, tokenizer=tokenizer, args=training_args, train_dataset=train_data.with_format("torch"), eval_dataset=full_eval_data.with_format("torch"), callbacks=[random_eval_callback] )
关键说明
- 回调会在每经过
eval_steps步触发评估时自动执行,每次评估都会使用全新的随机采样子集。 - 通过
state.global_step作为随机种子,既能保证每次采样结果不同,又能在固定全局种子的前提下复现训练过程。 - 如果不需要可复现性,可以去掉
random.seed(state.global_step)这一行,直接随机采样。
内容的提问来源于stack exchange,提问作者alvas
相关产品推荐
相关产品推荐

