N_TRIALS =100# Maximum number of trialsN_JOBS = 1 # Number of jobs to run in parallelN_STARTUP_TRIALS = 5 # Stop random sampling after N_STARTUP_TRIALSN_EVALUATIONS = 2 # Number of evaluations during the trainingN_TIMESTEPS = 100000 # Training budgetEVAL_FREQ = int(N_TIMESTEPS / N_EVALUATIONS)N_EVAL_ENVS = 5N_EVAL_EPISODES = 10TIMEOUT = int(60 * 15) # 15 minutesENV_ID = "MountainCarContinuous-v0"DEFAULT_HYPERPARAMS = { "policy": "MlpPolicy", "env": ENV_ID,}技术支持
我们定义了一个回调函数 TrialEvalCallback(),用于返回优化任务的周期性评估结果。请查看 Google Colab 笔记本了解该回调的实现。
defobjective(trial: optuna.Trial)->float:""" This will be used by Optuna to evaluate one set of hyperparameters at a time.Given a trial object, it will sample hyperparameters, evaluate it and report the result. :param trial: Optuna trial object :return: Mean episodic reward after training """ kwargs = DEFAULT_HYPERPARAMS.copy()# 1. Sample hyperparameters and update the keyword arguments kwargs.update(a2c_hyper_params(trial)) # 2. Create the RL model model = A2C(**kwargs) # 3. Create envs used for evaluation using make_vec_env, ENV_ID and N_EVAL_ENVS eval_envs = make_vec_env(ENV_ID, n_envs=N_EVAL_ENVS) # 4. Create the TrialEvalCallback callback eval_callback = TrialEvalCallback( eval_envs, trial, n_eval_episodes=N_EVAL_EPISODES, eval_freq=EVAL_FREQ, deterministic=True, verbose=0, ) nan_encountered = False try: # Train the model model.learn(N_TIMESTEPS, callback=eval_callback) except AssertionError as e: # Sometimes, random hyperparams can generate NaN print(e) nan_encountered = True finally: # Free memory model.env.close() eval_envs.close() # Tell the optimizer that the trial failed if nan_encountered: return float("nan") if eval_callback.is_pruned: raise optuna.exceptions.TrialPruned() return eval_callback.last_mean_reward技术支持
高效的采样与剪枝机制
剪枝是指在给定预算后,削减那些不太可能产生最优结果的参数或搜索空间区域。在 Optuna 中,剪枝会在训练早期淘汰表现较差的试验,从而缩小参数集合并缩短到达最优搜索空间的时间。Optuna 提供多种剪枝器,包括采用中位数停止准则的 Median Pruner。您可在Optuna 文档中了解更多剪枝器信息。
实现 Optuna 的 MedianPruner
Median Pruner 算法会在当前最佳结果劣于以往结果中位数时进行剪枝。这里除以 3 是因为我们仅希望在使用了 1/3 的最大预算后才开始剪枝。
study = optuna.create_study(sampler=sampler, pruner=pruner, direction="maximize")try:study.optimize(objective, n_trials=N_TRIALS, n_jobs=N_JOBS, timeout=TIMEOUT)except KeyboardInterrupt: passprint("Number of finished trials: ",len(study.trials))print("Best trial:")trial = study.best_trialprint(f" Value: {trial.value}")print(" Params: ")for key, value in trial.params.items():print(f" {key}: {value}")print(" User attrs:")for key, value in trial.user_attrs.items():print(f" {key}: {value}")技术支持
机器学习模型存在对性能影响重大的超参数。这些参数就像烤蛋糕时的合适温度或翻煎饼时的合适角度。在强化学习中,超参数会影响策略与奖励的近似;若调优得当,超参数优化能显著提升结果表现。
本文将介绍 Optuna,这是一款强大的开源超参数优化框架。若您刚接触该主题,可先阅读 Understanding Machine Learning,这是一门零代码入门课程。想用 Python 边学边练,可尝试我们的 Machine Learning Fundamentals with Python 课程(使用 scikit-learn)。随后,MLOps Concepts 将帮助您了解如何将机器学习模型从本地笔记本迁移到生产环境。最后,尝试 Preprocessing for Machine Learning in Python,这门课程与本文高度相关,将教您为机器学习模型清洗和准备数据。
什么是 Optuna?
Optuna 是一个开源的超参数优化框架,用于自动化超参数搜索。它可与任意机器学习或深度学习框架配合使用。Optuna 的一些关键能力包括:
什么是强化学习(RL)?
寻找最优路径。来源:作者制图
强化学习(RL)融合了 机器学习 与 最优控制。它关注智能体应如何在动态环境中采取行动以最大化其累积奖励。简单来说,强化学习是教会智能体在环境中做出最优决策,以最大化其奖励。智能体每一步的奖励在接近目标时可能为正或负。
与传统机器学习不同,强化学习算法通过做出决策以达到最优结果,类似我们为达成目标所采用的试错学习过程。深度强化学习与强化学习的区别在于前者使用深度神经网络来逼近复杂函数。也可以说,常规强化学习更偏向确定性方法,而深度强化学习则采用随机性方法。
在强化学习模型中使用 Optuna
在同一环境中,通往目标的路径可能有很多。与监督学习相比,深度强化学习对学习率、gamma、步数等超参数的选择更加敏感。
不佳的超参数选择会导致收敛效果差或不稳定。使用不同随机种子(用于初始化网络权重与环境)带来的性能差异会进一步加剧这一挑战。
本节将演示如何设置 Optuna 及相关依赖、定义搜索空间,并针对 MountainCarContinuous-v0 算法运行优化。MountainCarContinuous-v0 是 RL-Zoo(一个提供评估与绘图脚本的训练框架)中的强化学习算法之一。MountainCarContinuous-v0 建模了一个环境,其中智能体(一辆小车)尝试实现其目标(到达旗帜)。
调优后的 MountainCarContinuous-v0 算法演示。作者制图。
如何开始使用 Optuna
开始之前,您需要:
设置 Optuna 和 StableBaseline 3
创建新虚拟环境后,安装所需的包。注意,Optuna 支持 Python 3.7 或更新版本。若您想回顾如何创建虚拟环境,请阅读我们的 Virtual Environment in Python 教程。
导入必要的包
我们将使用
gym包来创建智能体执行动作的环境。本项目将使用 Advantage Actor-Critic(A2C)中的 MountainCarContinuous-v0 算法。Advantage Actor-Critic(A2C) 是一种 Actor-Critic 算法,结合了基于价值(衡量采取某动作的奖励)与基于策略(控制智能体动作)的方法,通过降低方差来稳定训练。
定义超参数
我们先设定本任务将使用的配置。
我们将为这些超参数建议一个取值范围。
定义目标函数
我们定义了一个回调函数
TrialEvalCallback(),用于返回优化任务的周期性评估结果。请查看 Google Colab 笔记本了解该回调的实现。高效的采样与剪枝机制
剪枝是指在给定预算后,削减那些不太可能产生最优结果的参数或搜索空间区域。在 Optuna 中,剪枝会在训练早期淘汰表现较差的试验,从而缩小参数集合并缩短到达最优搜索空间的时间。Optuna 提供多种剪枝器,包括采用中位数停止准则的 Median Pruner。您可在Optuna 文档中了解更多剪枝器信息。
实现 Optuna 的 MedianPruner
Median Pruner 算法会在当前最佳结果劣于以往结果中位数时进行剪枝。这里除以 3 是因为我们仅希望在使用了 1/3 的最大预算后才开始剪枝。
实现 Optuna 的 TPESampler
选择采样器,可选随机、TPESampler、CMAES 等。
创建 study 并开始优化任务
现在我们可以创建一个 Optuna study 了。
Optuna 的高级功能
我们来看看 Optuna 的一些高级功能。
Optuna 的可视化工具
Optuna 提供 Dashboard,可用于可视化、跟踪和分析以往与当前的运行。在过去,您可能需要连接 MLFlow 等跟踪工具来管理结果。
Optuna Dashboard。来源:Optuna
与分布式系统集成以开展大规模实验
Optuna 对分布式训练的支持允许您连接 Kubernetes 或 Dask 等分布式后端,在大规模实验中利用更多计算资源。您还可以连接存储后端来存储与管理会话结果。云端可用 Dask 存储,本地运行可用 SQLite。
在深度强化学习中使用 Optuna 的建议
以下是避免超参数调优常见陷阱的一些建议: