Performance Study of Double DQN, PPO, and Decision Transformer with RTG Predictor on the OpenAI Gym CartPole Environment — Ling Huang and Sijia Chen — 仓库地址:https://github.com/xiumudeouni/SUSTech_AIB_Project_2025_Fall
在 agents/ 文件夹中,有不同模型的实现:
cartpole_dqn.py 提供的 DQN 实现。cartpole_double_dqn.py 在 cartpole_dqn.py 基础之上的 DDQN 实现。cartpole_ppo.py PPO的实现cartpole_dt.py Desicion Transformer 的实现。rtg_predictor.py RTG Predictor 的实现。在 models/ 文件夹中,训练的模型分别被命名为:
cartpole_dqn_sovled.torch 使用 DQN 训练的,平均得分500分的模型。double_dqn.torch 使用 DDQN 训练的,平均得分500分的模型。cartpole_ppo_solved_5.torch 使用PPO 训练的,平均得分500分的模型。cartpole_dt_*.torch 使用 Desicion Transformer 在不同数据集上训练的 RTG=500 的最优模型。rtg_predictor.torch MLP 加 Bellman 迭代,训练的用于预测Value的模型。必须搭配 cartpole_dt_random.torch 使用(你也可以用 rtg_predictor_poor.torch 搭配 cartpole_dt_poor.torch 使用)。train.py 这是提供的初始脚本。提交的脚本进行了一些修改,包括
score.loggertrain_ddqn_comparison.py 这个脚本集成了
train_ppo.py 这个脚本集成了
train_offline_advanced.py 这个脚本集成了
train_with_rtg_predictor.py 这个脚本集成了
run_DT.py 这个脚本可以评价训练好的 DT 模型在环境中的表现。visualize_datasets.py 这个脚本用来可视化训练 DT 前生成的数据集。Benchmark采用 线上评估
修改 train.py 的运行
if __name__ == "__main__":
# Example: quick training then a short evaluation
#agent = train(num_episodes=1000, terminal_penalty=True)
evaluate(model_path="models/cartpole_dqn_solved.torch", algorithm="dqn", episodes=100, render=False, fps=60)
修改 train.py 的运行
if __name__ == "__main__":
# Example: quick training then a short evaluation
#agent = train(num_episodes=1000, terminal_penalty=True)
evaluate(model_path="models/double_dqn.torch", algorithm="dqn", episodes=100, render=False, fps=60)
修改 train.py 的运行
if __name__ == "__main__":
# Example: quick training then a short evaluation
#agent = train(num_episodes=1000, terminal_penalty=True)
evaluate(model_path="models/cartpole_ppo_solved_5.torch", algorithm="ppo", episodes=100, render=False, fps=60)
加载某一个训练好的 DT 模型,并且在线评估。使用 run_DT 脚本。对于在 expert,good,medium 和 poor 数据集上训练的模型,建议使用 --rtg 500 以达到接近500分的结果。对于 random 数据集训练的模型,推荐的值是 --rtg 200 以达到最优表现。
# --model_path:输入DT的模型路径
# --rtg:你需要的RTG(例如100,500)
# --episodes:评估多少轮
python run_DT.py --model_path models/cartpole_dt_good.torch --rtg 500 --episodes 100
加载某一个训练好的 DT 模型和 RTG_Predictor 模型,并且在线评估。请注意,你选择的两个模型务必是在同一个数据集上训练的。
使用 train_with_rtg_predictor.py 脚本进行评估。
# 评估 DT 模型 (使用预测 RTG)
# --mode: 运行模式 (eval_predicted)
# --dt_model: DT 模型的路径,默认 `models/cartpole_random.torch`
# --rtg_model: RTG Predictor路径,默认 `models/rtg_predictor.torch`. Predictor不带后缀的命名指的是在 random 数据集上训练的结果
# --episodes: 评估次数
python train_with_rtg_predictor.py --mode eval_predicted --episodes 1000
直接运行 train_ddqn_comparison.py。会在 models/ 路径下生成 double_dqn.torch 和 standard_dqn.torch。并在 visualization_ddqn/ 文件夹下生成可视化训练图像。
修改 train_ppo.py 的运行。分别训练PPO和DQN并且分别可视化。
if __name__ == "__main__":
# 示例:训练 PPO 并绘图
train(num_episodes=850, algorithm="ppo")
#evaluate(model_path="models/cartpole_ppo_solved_5.torch", algorithm="ppo", episodes=10, render=True, fps=60)
# 示例:训练 DQN 并绘图
#train(num_episodes=1000, algorithm="dqn")
#evaluate(model_path="models/cartpole_dqn.torch", algorithm="dqn", episodes=10, render=True, fps=60)
使用 train_offline_advanced.py 脚本。
# 首先收集不同质量的数据集,会自动保存在 `offline_data`文件夹下。如果这个文件夹中已经有离线数据文件,会跳过收集阶段。数据收集是通过将训练好的DQN模型`models/cartpole_dqn_solved.torch`,通过调整epsilon_greedy进行的。
python train_offline_advanced.py --mode collect_all
# 直接运行下面的命令进行训练和比较。默认参数训练100轮。每5轮对模型进行一次在线评估(每次评估10次)。储存RTG=500得分最高的模型(所以训练结束时候的模型并不是存储的模型)。训练好的模型会存储在`models/`文件夹下。图片会生成在`visualizations/`文件夹下。
python train_offline_advanced.py --mode compare
使用 train_with_rtg_predictor.py 脚本。默认在 random 数据集上训练。
# 自动开始训练500轮。loss会先显著下降,然后上升,然后稳定在4e-9左右。训练过程较慢,可以将epoch改为200。训练结束后,脚本自动评估DT+rtg_Predictor和固定RTG的DT的表现。1000轮评估使得对模型的评估随机性更小。
# eopch: 训练轮数(建议大于200,我训练时使用了500)
# episodes: 评估轮数(100轮随机性很强,1000轮较为合适)
python train_with_rtg_predictor.py --mode full_pipeline --epoch 500 --episodes 1000
一共有三个可视化图像的文件夹,分别是
visualizations/用于存储
cartpole_dt_*_curves.png DT在不同数据集上的训练曲线。dt_dataset_comparison.png DT训练曲线对比图。final_score_comparison.png 数据集分布对比图。rtg_predictor_training.png RTG Predictor 训练曲线图。rtg_comparison.png 使用 RTG Predictor 和使用 fixed RTG 在线评估的对比图。visualizations_ddqn/dqn_vs_double_dqn.png 用于存储 DDQN 和 DQN 的训练对比图。
visualization_ppo/用于存储 PPO 不同参数训练对比和与 DQN 的训练对比图。
ppo_dqn_comparison/ PPO 和 DQN 训练曲线。ppo_parameter_comparison/ 不同参数 PPO 训练曲线对比。offline_data/ 这个文件夹存储用于训练 Decision Transformer 的离线轨迹数据。
每个 .pkl 文件包含一个轨迹列表。有200条轨迹。每条轨迹是一个字典:
{
'states': np.ndarray, # shape: [T, obs_dim]
'actions': np.ndarray, # shape: [T], dtype: int64
'rewards': np.ndarray, # shape: [T], dtype: float32
'dones': np.ndarray, # shape: [T], dtype: bool
}
使用已训练的 DQN 模型收集专家数据:
python train_offline_advanced.py --mode collect_all
这将生成五个 .pkl 文件。轨迹数量是硬编码的,但是可以在脚本中修改。
Decision Transformer (DT) 是一种将强化学习问题转化为序列建模(Sequence Modeling)问题的算法。 在本项目中,DT 的主要作用是作为离线强化学习(Offline RL)智能体。它不通过传统的贝尔曼方程(如 DQN)迭代价值,而是直接根据过去的状态(State)、动作(Action)和预期回报(Return-to-Go, RTG)序列,来预测下一个最优动作。 这使得它能够从固定的离线数据集中学习策略,并在推理时通过指定目标回报 (Target Return) 来控制智能体的表现。
DT 是一个基于 Transformer (GPT 架构) 的神经网络模型,定义在 agents/cartpole_dt.py 的 DecisionTransformer 类中。
embed_return: 将标量 RTG 映射到 embed_dim。embed_state: 将状态向量映射到 embed_dim。embed_action: 将动作(One-hot 编码)映射到 embed_dim。embed_timestep: 位置编码,将时间步 t 映射到 embed_dim。(R, s, a) 三元组交错堆叠,形成序列 [R_0, s_0, a_0, R_1, s_1, a_1, ...]。n_layers): 3n_heads): 4embed_dim): 128context_len): 20DT 的训练采用监督学习(Supervised Learning)的方式,由 DTSolver 类管理。
OfflineDataset):
context_len (20) 的片段。returns_to_go, states, actions, timesteps。lr=1e-4, weight_decay=1e-4)。target_return (如 500)。DT 的脚本通常包含以下模式:
target_return(例如 500),观察实际得分。训练脚本名为 train_offline_advanced.py。这个脚本集成了数据集收集,模型训练,训练可视化。以下是典型的运行命令:
# 训练 DT 模型 (带可视化)
# --mode: 运行模式 (train_viz)
# --data: 离线数据路径
# --epochs: 训练轮数
# 不要用这个命令,这只是我自己测试使用的
python train_offline_advanced.py --mode train_viz --data offline_data/expert_data.pkl --epochs 100
# 收集不同质量的数据集 (用于训练 DT)
python train_offline_advanced.py --mode collect_all
# 比较 DT 在不同数据集上的表现
python train_offline_advanced.py --mode compare
# 首先收集不同质量的数据集,会自动保存在 `offline_data`文件夹下。如果这个文件夹中已经有离线数据文件,会跳过收集阶段。数据收集是通过将训练好的DQN模型`models/cartpole_dqn_solved.torch`,通过调整epsilon_greedy进行的。
python train_offline_advanced.py --mode collect_all
# 直接运行下面的命令进行训练和比较。默认参数训练100轮。每5轮对模型进行一次在线评估。储存RTG=500,得分最高的模型(所以训练结束时候的模型并不是存储的模型)。训练好的模型会存储在`models`文件夹下。图片会生成在`visualizations`文件夹下。
python train_offline_advanced.py --mode compare
run_DT.py脚本的使用这个脚本只是用来评价使用DT训练好的模型在环境中的表现。可以在控制台中看到模型具体的表现结果。复现不需要,只是供我测试的脚本。 命令行示例如下
# --model_path:输入DT的模型路径
# --rtg:你需要的RTG(例如100,500)
# --episodes:评估多少轮
python run_DT.py --model_path models/cartpole_dt_good.torch --rtg 200 --episodes 100
这是本项目的创新点,是为了提升DT在差数据集上的表现。我们主要使用了carpole_dt_random.torch模型,并且只主要关注random_data.pkl数据集。
RTG Predictor(回报预测器)在本项目中充当 价值函数 (Value Function, $V(s)$) 的角色。
它的主要作用是在 Decision Transformer (DT) 的推理阶段,动态预测当前状态下的预期回报,并将其作为 DT 的输入 target_return。
这解决了标准 DT 需要手动指定固定 target_return 的局限性,特别是在以下情况中:
RTG Predictor 是一个基于 多层感知机 (MLP) 的神经网络,定义在 agents/rtg_predictor.py 的 RTGPredictor 类中。
Linear(state_dim, hidden_dim) + ReLU + DropoutLinear + ReLU + DropoutLinear(hidden_dim, 1)s_t (CartPole 中维度为 4)。与 DT 的监督学习不同,RTG Predictor 使用 时序差分学习 (TD Learning) 进行训练,类似于 DQN 或 Actor-Critic 中的 Critic 网络。实现位于 RTGPredictorSolver 类中。
(state, reward, next_state, done)。TransitionDataset 类进行批次采样。100.0。models/rtg_predictor.torchvisualizations/rtg_predictor_training.png脚本 train_with_rtg_predictor.py 提供了多种运行模式:
train_rtg: 训练模式。加载离线数据,训练 RTG Predictor。eval_fixed: 基准评估。使用固定的 target_return (如 500) 运行 DT。eval_predicted: 动态评估。使用 RTG Predictor 实时预测的值作为 DT 的 target_return。compare: 对比模式。同时运行上述两种评估并绘制对比图。full_pipeline: 全流程。先训练 RTG Predictor,然后进行对比评估。相关的实现包含在 train_with_rtg_predictor.py 中:
# 训练 RTG 预测器
# --mode: 运行模式 (train_rtg)
# --data: 离线数据路径
# --epochs: 训练轮数
python train_with_rtg_predictor.py --mode train_rtg --data offline_data/random_data.pkl --epochs 200
# 评估 DT 模型 (使用固定 RTG)
# --mode: 运行模式 (eval_fixed)
# --dt_model: DT 模型路径
# --target_rtg: 目标回报
python train_with_rtg_predictor.py --mode eval_fixed --dt_model models/cartpole_dt_random.torch --target_rtg 500
# 评估 DT 模型 (使用预测 RTG)
# --mode: 运行模式 (eval_predicted)
# --episodes: 评估次数
python train_with_rtg_predictor.py --mode eval_predicted --episodes 1000
# 完整流程:训练 RTG 预测器并比较
python train_with_rtg_predictor.py --mode full_pipeline --epoch 500 --episodes 1000
直接运行命令行
# 自动开始训练500轮。loss会先显著下降,然后上升,然后稳定在4e-9左右。训练过程较慢,可以将epoch改为200。训练结束后,脚本自动评估DT+rtg_Predictor和固定RTG的DT的表现。1000轮评估使得对模型的评估随机性更小。
# eopch: 训练轮数(建议大于200,我训练时使用了500)
# episodes: 评估轮数(100轮随机性很强,1000轮较为合适)
python train_with_rtg_predictor.py --mode full_pipeline --epoch 500 --episodes 1000