1. 项目概述
在强化学习领域,登月器着陆(Lunar Lander)是一个经典的基准任务。这个项目使用Stable Baselines3库中的DQN算法,训练一个智能体控制登月器在月球表面安全着陆。通过这个实战案例,我们将深入探讨DQN算法的实现细节和调优技巧。
1.1 环境介绍
Gymnasium的LunarLander-v3环境模拟了登月器在月球重力作用下的运动状态。环境提供了以下关键信息:
-
观测空间:8维向量,包含:
- x/y坐标(着陆器位置)
- x/y速度(线速度)
- 角度(姿态)
- 角速度
- 两个布尔值(表示腿部是否接触地面)
-
动作空间:4个离散动作:
- 0:无操作
- 1:点燃左侧引擎
- 2:点燃主引擎
- 3:点燃右侧引擎
-
奖励机制:
- 正奖励:靠近着陆点、低速、水平姿态、腿部接触地面
- 负奖励:引擎点火消耗、坠毁
- 成功着陆额外+100分,坠毁-100分
- 总分≥200视为任务成功
2. DQN算法实现
2.1 DQN核心组件
DQN(Deep Q-Network)是Q-Learning的深度学习版本,主要解决了传统Q-Learning在高维状态空间下的局限性。我们的实现包含以下关键组件:
-
经验回放(Experience Replay):
- 存储状态转移元组(s, a, r, s')
- 训练时随机采样,打破数据相关性
- 缓冲区大小设置为100,000
-
目标网络(Target Network):
- 定期从主网络同步参数(每10,000步)
- 提供稳定的Q值目标,减少训练波动
-
网络架构:
python复制QNetwork( (features_extractor): FlattenExtractor() (q_net): Sequential( (0): Linear(in_features=8, out_features=256) (1): ReLU() (2): Linear(in_features=256, out_features=256) (3): ReLU() (4): Linear(in_features=256, out_features=4) ) )
2.2 训练参数配置
python复制model = DQN(
"MlpPolicy",
env,
learning_rate=5e-4,
buffer_size=100000,
batch_size=128,
gamma=0.99,
target_update_interval=10000,
exploration_fraction=0.1,
exploration_final_eps=0.01,
policy_kwargs={'net_arch': [256, 256]},
tensorboard_log="./logs"
)
关键参数说明:
learning_rate:Adam优化器的学习率gamma:未来奖励的折扣因子exploration_final_eps:最终探索率(ε-greedy)
3. 训练过程与调优
3.1 初始训练结果
首次训练200,000步后,平均奖励仅达到-64分。分析发现:
- 智能体倾向于保持悬空而非着陆
- 奖励曲线呈现双峰结构,表明学习不稳定
- 损失值波动较大(100-1000范围)
3.2 网络结构调整
将网络架构从默认的[64,64]调整为[256,256]后:
- 训练1,000,000步时最高奖励达到230分
- 平均步数从1000+降至200左右,表明学会了主动着陆
- 损失值稳定在50-200范围
3.3 学习率优化
对比实验发现:
- 学习率7e-4:训练速度快但后期不稳定(奖励突降)
- 学习率4e-4:训练稳定,最终奖励达260+
- 学习率1e-4:收敛速度过慢
最终采用5e-4的学习率取得了最佳平衡。
4. 评估与可视化
4.1 评估指标
使用10次测试episode的平均奖励作为评估标准:
python复制mean_reward, std_reward = evaluate_policy(
model,
model.get_env(),
n_eval_episodes=10,
deterministic=True
)
优化后的模型平均奖励达到250±20分,远超200分的成功阈值。
4.2 TensorBoard监控
关键训练曲线:
- episode_reward:奖励随训练步数的变化
- episode_length:episode长度变化(反映着陆策略)
- loss:TD误差损失值
- exploration_rate:ε-greedy探索率衰减

5. 实战经验与技巧
5.1 关键发现
-
训练步数阈值:
- 前200,000步:智能体学习悬停
- 200,000-500,000步:开始尝试着陆
-
1,000,000步:掌握精确着陆
-
奖励与步数的关系:
- 初期:高步数对应随机奖励
- 后期:低步数(快速着陆)对应高奖励
5.2 调优建议
-
网络容量:
- 简单任务:[64,64]可能足够
- 复杂控制:[256,256]或更大网络效果更好
-
训练时长:
- 至少500,000步才能看到明显进步
- 理想训练步数1,000,000-2,000,000
-
学习率选择:
- 建议范围:3e-4到7e-4
- 太大导致不稳定,太小收敛慢
5.3 常见问题解决
-
奖励不增长:
- 检查网络容量是否足够
- 尝试增大探索率(exploration_final_eps)
- 确保batch_size足够大(≥64)
-
训练波动大:
- 降低学习率
- 增大target_update_interval
- 尝试增加buffer_size
-
过拟合问题:
- 添加dropout层
- 使用更小的网络
- 增加L2正则化
6. 完整实现代码
python复制import gymnasium as gym
from stable_baselines3 import DQN
from stable_baselines3.common.evaluation import evaluate_policy
# 创建环境
env = gym.make("LunarLander-v3")
# 初始化模型
model = DQN(
"MlpPolicy",
env,
learning_rate=5e-4,
buffer_size=100000,
batch_size=128,
gamma=0.99,
target_update_interval=10000,
exploration_fraction=0.1,
exploration_final_eps=0.01,
policy_kwargs={'net_arch': [256, 256]},
tensorboard_log="./logs",
verbose=1
)
# 训练模型
model.learn(total_timesteps=2000000, progress_bar=True)
# 评估模型
mean_reward, _ = evaluate_policy(model, model.get_env(), n_eval_episodes=10)
print(f"Average reward: {mean_reward:.2f}")
# 保存模型
model.save("dqn_lunar_lander")
7. 扩展与改进方向
-
高级技巧:
- 优先经验回放(Prioritized Experience Replay)
- Dueling DQN架构
- Noisy Nets探索策略
-
环境修改:
- 连续动作空间(LunarLanderContinuous-v3)
- 添加风速扰动(enable_wind=True)
- 自定义奖励函数
-
算法比较:
- 尝试PPO、A2C等策略梯度方法
- SAC对于连续控制任务的效果
- Rainbow DQN的集成改进
在实际项目中,我发现DQN对超参数相当敏感。经过多次实验,确定以下最佳实践:
- 训练初期保持较高探索率(ε=0.2→0.01)
- 使用Adam优化器比RMSProp更稳定
- 每100,000步保存一次模型检查点
- 在奖励平台期适当提高学习率
登月器任务的成功关键在于平衡"探索"和"利用"。太早降低探索率会导致局部最优(如永远悬停),而探索太多则难以收敛。建议采用分段衰减策略,在奖励突破100分后再降低探索率。