DDPG算法在Pendulum环境中的实现与优化

DDPG算法在Pendulum环境中的实现与优化 1. DDPG算法与Pendulum环境概述深度确定性策略梯度DDPG是强化学习领域处理连续动作空间的经典算法它巧妙结合了确定性策略梯度DPG和深度Q网络DQN的技术优势。在Pendulum-v1这个经典控制问题中我们需要让倒立摆保持竖直平衡状态其动作空间是连续的力矩值-2到2之间这与离散动作空间的问题有本质区别。Pendulum环境的观测空间包含3个维度摆杆的cosθ、sinθ和角速度。与离散动作的CartPole不同Pendulum要求智能体输出精确的扭矩值这使得传统Q-learning方法难以直接应用。DDPG通过Actor-Critic架构解决了这一难题——Actor网络负责输出连续动作Critic网络则评估该动作的价值。关键点DDPG属于model-free、off-policy算法意味着它不依赖环境模型且可以从历史经验中学习。这在Pendulum这类物理仿真环境中尤为重要因为真实的动力学模型往往难以精确建立。2. DDPG核心架构实现细节2.1 双网络结构与目标网络DDPG维护四组神经网络Actor/Critic及其对应的目标网络。Actor网络结构通常比Critic简单在我们的实现中def get_actor(): inputs layers.Input(shape(3,)) # 对应Pendulum的3维状态 out layers.Dense(256, activationrelu)(inputs) out layers.Dense(256, activationrelu)(out) # 最后一层使用tanh激活输出范围[-1,1]再乘以动作上限 outputs layers.Dense(1, activationtanh)(out) * upper_bound return keras.Model(inputs, outputs)Critic网络则需要同时处理状态和动作输入def get_critic(): state_input layers.Input(shape(3,)) state_out layers.Dense(32, activationrelu)(state_input) action_input layers.Input(shape(1,)) action_out layers.Dense(32, activationrelu)(action_input) concat layers.Concatenate()([state_out, action_out]) out layers.Dense(256, activationrelu)(concat) outputs layers.Dense(1)(out) # 输出Q值 return keras.Model([state_input, action_input], outputs)目标网络通过软更新参数τ0.005保持稳定性def update_target(target, original, tau): # 渐进式更新目标网络参数 for t, o in zip(target.get_weights(), original.get_weights()): t.assign(t * (1 - tau) o * tau)2.2 经验回放机制我们设计了一个容量为50,000的循环缓冲区存储(s,a,r,s)四元组。采样时采用均匀随机采样而非优先回放因为Pendulum问题相对简单class Buffer: def __init__(self, capacity50000, batch_size64): self.state_buffer np.zeros((capacity, 3)) self.action_buffer np.zeros((capacity, 1)) self.reward_buffer np.zeros((capacity, 1)) self.next_state_buffer np.zeros((capacity, 3)) def record(self, obs_tuple): index self.buffer_counter % self.capacity self.state_buffer[index] obs_tuple[0] # 存储动作、奖励和下一状态... def sample(self): indices np.random.choice(min(self.counter, self.capacity), self.batch_size) return ( tf.convert_to_tensor(self.state_buffer[indices]), # 转换其他缓冲区数据... )3. 探索策略与训练技巧3.1 Ornstein-Uhlenbeck噪声为在连续动作空间中实现有效探索我们采用OU噪声而非简单高斯噪声。这种时间相关的噪声更适合物理系统的惯性特性class OUActionNoise: def __call__(self): dx self.theta * (self.mean - self.x_prev) * self.dt dx self.std_dev * np.sqrt(self.dt) * np.random.normal(sizeself.mean.shape) self.x_prev dx return self.x_prev参数设置经验θ0.15回归均值速度σ0.2噪声标准差dt0.01时间步长3.2 关键训练参数gamma 0.99 # 折扣因子 actor_lr 1e-3 # Actor学习率通常比Critic小 critic_lr 2e-3 batch_size 64 # 从经验池采样批次大小实际训练中发现Critic网络需要更激进的学习率以快速收敛Q值估计而Actor网络则需要更保守的更新以防止策略震荡。4. 训练过程与性能优化4.1 训练循环实现每个episode包含完整的轨迹采样和参数更新for ep in range(100): state, _ env.reset() episodic_reward 0 while True: action policy(state, ou_noise) # 带探索的动作选择 next_state, reward, done, _ env.step(action) buffer.record((state, action, reward, next_state)) episodic_reward reward if buffer.counter batch_size: buffer.learn() # 执行梯度更新 update_target(target_actor, actor, tau) update_target(target_critic, critic, tau) if done: break state next_state4.2 奖励曲线分析在Pendulum环境中典型训练过程呈现三个阶段探索期前20episode奖励在-1500到-800间波动快速提升期20-50episode奖励从-800提升到-200收敛期50episode后奖励稳定在-150左右注意Pendulum的奖励函数设计是角度偏离越大惩罚越高最高奖励0完全垂直。实际中很难达到完美平衡-150已表明成功控制。4.3 调优经验网络宽度比深度更重要256节点的单隐层比128节点的双隐层表现更好批量归一化在本问题中效果不明显适当减小τ值如0.001可以提高稳定性但会减慢学习速度在训练后期逐步减小OU噪声的σ值有助于策略收敛5. 部署与效果验证5.1 模型保存与加载训练完成后保存权重actor.save_weights(pendulum_actor.h5) target_critic.save_weights(pendulum_critic.h5)测试时直接加载Actor网络trained_actor get_actor() trained_actor.load_weights(pendulum_actor.h5) state env.reset()[0] while True: action trained_actor(tf.expand_dims(state, 0))[0] state, _, done, _ env.step(action) env.render() if done: break5.2 实际运行观察成功训练后的Agent会表现出初始摆动阶段施加较大力矩快速减小角度偏差稳定阶段微调力矩抵消重力作用抗干扰能力受到随机扰动后能快速恢复平衡常见失败模式包括持续振荡Critic低估了长期惩罚力矩饱和总是输出±2的极限值突然失控目标网络更新过快导致发散6. 扩展与改进方向6.1 针对Pendulum的改进奖励函数重塑原始奖励r-(θ² 0.1ω² 0.001a²)可调整系数课程学习从较短摆杆开始训练逐步增加长度集成学习并行训练多个Agent提高稳定性6.2 迁移到其他环境DDPG可应用于更复杂场景如LunarLanderContinuous需要控制主引擎和侧向喷射BipedalWalker高维连续动作空间机械臂控制多关节协同操作关键调整点网络容量需要扩大经验回放缓冲区容量需增加探索噪声参数需重新调优我在实际项目中发现DDPG对超参数相当敏感建议先在小规模环境如Pendulum验证算法实现正确性再迁移到复杂场景。一个实用的技巧是记录训练过程中的权重快照当出现性能下降时可回退到之前的版本。