求助:无法通过Optuna最优参数复现最优试验结果
Optuna调参后最优结果无法复现的排查方案
我使用Optuna进行深度学习模型自动调参,目标函数返回5折交叉验证的平均AUC。但将最优试验的参数保存后重新运行完整模型,结果与Optuna给出的最优值存在近3%的差异。已固定数据划分、CUDA训练、Optuna采样器等所有可固定的随机数,仍无法解决。相关代码如下:
study = optuna.create_study(direction="maximize", sampler=optuna.samplers.TPESampler(seed=2024)) study.optimize(objective, n_trials=1) print("Best trial:") trial = study.best_trial print(f" Cindex: {trial.value}") print(" Best hyperparameters:") for key, value in trial.params.items(): print(f" {key}: {value}") importance = get_param_importances(study) print("参数重要性:") for param, score in importance.items(): print(f"{param}: {score:.4f}") best_params = trial.params with open(json_results, "w") as f: json.dump({"C-index": trial.value, "Params": best_params}, f, indent=4)
排查方向
交叉验证逻辑一致性
检查目标函数内的5折划分逻辑与重跑代码是否完全一致:比如是否使用了相同的随机种子、是否启用分层抽样、折数是否一致。例如用sklearn.model_selection.KFold时,确保random_state和shuffle参数在两次运行中完全相同,甚至可以将划分的索引保存下来,重跑时直接加载复用。模型初始化随机性遗漏
除了全局的CUDA/Optuna种子,还要确保模型初始化的种子完全固定:- 目标函数和重跑代码中都要显式设置
torch.manual_seed()、torch.cuda.manual_seed_all(); - 检查模型层的初始化逻辑,比如自定义初始化是否依赖随机数,是否固定了种子;
- 确保目标函数内每次trial都重新初始化模型并设置种子,重跑时严格遵循相同的初始化流程。
- 目标函数和重跑代码中都要显式设置
训练过程随机性差异
- 数据加载环节:如果用多线程
DataLoader,必须设置worker_init_fn固定每个worker的随机种子,否则即使全局种子固定,worker的随机操作(如数据增强)仍会导致差异; - 正则化层行为:训练时启用Dropout/BatchNorm,验证时必须切换到
model.eval()模式,两次运行的模式切换逻辑要完全一致; - 混合精度训练:如果使用AMP,确保目标函数和重跑代码的AMP配置完全相同(包括梯度缩放、是否启用等)。
- 数据加载环节:如果用多线程
指标计算逻辑一致性
确认目标函数返回的平均AUC与重跑时的计算逻辑完全一致:- 使用相同的AUC计算函数(如
sklearn.metrics.roc_auc_score),且参数(如multi_class、average)完全相同; - 检查是否在每折验证时使用了相同的预处理、后处理逻辑,比如阈值设置、标签格式等。
- 使用相同的AUC计算函数(如
环境依赖一致性
- 检查两次运行的库版本是否完全一致:包括PyTorch、Optuna、scikit-learn、CUDA驱动等,不同版本的库可能在随机数生成或算法实现上存在差异;
- 确保运行环境的硬件一致,避免因CPU/GPU架构差异导致的计算结果不同。
内容的提问来源于stack exchange,提问作者Qin Liang
相关产品推荐
相关产品推荐

