如何配置trainer.hyperparameter_search以运行网格搜索?
如何用Trainer.hyperparameter_search实现网格搜索
Hugging Face的Trainer.hyperparameter_search本身没内置网格搜索的选项,但可以通过自定义逻辑实现,核心就是生成所有超参数的网格组合,逐个训练评估找最优解。
方法一:自定义搜索函数适配hyperparameter_search
你可以写一个网格搜索的函数,然后传给hyperparameter_search的search_function参数,让它按你的逻辑执行搜索。
示例代码
from transformers import Trainer, TrainingArguments import itertools # 定义要搜索的超参数网格 param_grid = { "learning_rate": [1e-5, 2e-5, 5e-5], "per_device_train_batch_size": [8, 16], "num_train_epochs": [3, 5] } def grid_search_runner(trainer, n_trials): # 生成所有参数组合 param_combinations = list(itertools.product(*param_grid.values())) param_names = list(param_grid.keys()) best_score = float("-inf") best_params = None for params in param_combinations: current_params = dict(zip(param_names, params)) # 更新训练参数 trainer.args.set_training_args(**current_params) # 训练+评估 trainer.train() eval_result = trainer.evaluate() # 用负的eval_loss作为评分(search默认找最大评分,而loss越小越好) current_score = -eval_result["eval_loss"] if current_score > best_score: best_score = current_score best_params = current_params return {"best_trial": {"score": best_score, "hyperparameters": best_params}} # 初始化训练参数和Trainer training_args = TrainingArguments( output_dir="./grid_search_results", evaluation_strategy="epoch", # 补充你的其他基础训练参数 ) trainer = Trainer( model=你的模型实例, args=training_args, train_dataset=训练数据集, eval_dataset=验证数据集, # 补充你的其他训练配置参数 ) # 启动网格搜索 search_result = trainer.hyperparameter_search( search_function=grid_search_runner, n_trials=len(list(itertools.product(*param_grid.values()))) # 传入网格组合的总数量 ) # 应用最佳参数重新训练 trainer.args.set_training_args(**search_result.hyperparameters) trainer.train()
方法二:手动遍历网格参数(更直观)
如果不想依赖hyperparameter_search的封装,直接手动循环所有参数组合也可以,逻辑更简单:
from transformers import Trainer, TrainingArguments import itertools param_grid = { "learning_rate": [1e-5, 2e-5, 5e-5], "per_device_train_batch_size": [8, 16], "num_train_epochs": [3, 5] } best_score = float("-inf") best_params = None best_model_dir = None # 遍历所有参数组合 for lr, batch_size, epochs in itertools.product( param_grid["learning_rate"], param_grid["per_device_train_batch_size"], param_grid["num_train_epochs"] ): training_args = TrainingArguments( output_dir=f"./tmp_run_{lr}_{batch_size}_{epochs}", learning_rate=lr, per_device_train_batch_size=batch_size, num_train_epochs=epochs, evaluation_strategy="epoch", save_strategy="epoch", # 补充你的其他基础训练参数 ) trainer = Trainer( model=你的模型实例, args=training_args, train_dataset=训练数据集, eval_dataset=验证数据集, # 补充你的其他训练配置参数 ) trainer.train() eval_result = trainer.evaluate() current_score = -eval_result["eval_loss"] # 按loss最小化优化 if current_score > best_score: best_score = current_score best_params = {"learning_rate": lr, "per_device_train_batch_size": batch_size, "num_train_epochs": epochs} best_model_dir = training_args.output_dir print("最佳超参数:", best_params) print("最佳模型所在目录:", best_model_dir)
注意事项
- 网格搜索的计算量会随超参数的数量和取值数爆炸式增长,优先挑对任务影响大的超参数(比如学习率、批量大小)来搜索。
- 优化目标可以根据任务调整,比如分类任务用
eval_accuracy作为评分,直接取eval_result["eval_accuracy"]即可,不需要加负号。 - 若想加快搜索速度,可以结合多进程或分布式训练,并行运行不同的参数组合。
内容的提问来源于stack exchange,提问作者user3668129
相关产品推荐
相关产品推荐

