深度强化学习(6)Actor-Critic与DDPG:从理论到实践

张开发
2026/4/21 19:52:54 15 分钟阅读

分享文章

深度强化学习(6)Actor-Critic与DDPG:从理论到实践
1. Actor-Critic算法当策略梯度遇上价值函数我第一次接触Actor-Critic算法时感觉它就像是一个精妙的双人舞——Actor负责选择动作Critic负责评价动作的好坏。这种分工协作的模式让它在连续动作空间任务中表现尤为出色。你可能已经知道DQN擅长价值估计但只能处理离散动作而策略梯度方法直接优化策略却面临高方差问题。Actor-Critic的聪明之处就在于把两者优势结合了起来。让我们用自动驾驶来打个比方。Actor就像驾驶员根据当前路况决定方向盘转多少度连续动作Critic则像坐在副驾驶的教练实时评价这个转向幅度是否合适。这种即时反馈机制比单纯靠最终是否到达目的地来评判驾驶行为如REINFORCE算法要高效得多。数学上Actor-Critic的核心是优势函数A(s,a)Q(s,a)-V(s)。这个公式看似简单却解决了两个关键问题一是用V(s)作为基线降低了方差二是通过Q(s,a)保持了策略更新的方向性。我在实现时发现如果直接用原始策略梯度训练曲线就像过山车一样波动剧烈而引入Critic后学习过程明显稳定多了。class ActorCritic: def update(self, transition_dict): # 计算时序差分目标 td_target rewards self.gamma * self.critic(next_states) * (1 - dones) td_delta td_target - self.critic(states) # 优势函数估计 # Actor损失策略梯度 log_probs torch.log(self.actor(states).gather(1, actions)) actor_loss -torch.mean(log_probs * td_delta.detach()) # Critic损失值函数拟合 critic_loss torch.mean(F.mse_loss(self.critic(states), td_target.detach()))实际训练CartPole环境时有几个参数特别敏感。首先是折扣因子gamma我试过设为0.9时智能体只关注短期平衡设为0.99后才学会长期稳定。其次是学习率Critic的网络通常需要比Actor更大的学习率比如1e-2 vs 1e-3因为价值估计是策略优化的基础。下面是训练200轮后的典型学习曲线训练轮次平均回报关键观察0-5050随机探索阶段50-10050-150开始掌握基本平衡100-150150-190出现稳定控制策略150-200195接近完美表现2. 从A2C到A3C并行化带来的突破在基础Actor-Critic之上研究者们提出了异步优势Actor-CriticA3C算法。这个异步二字可大有玄机。记得我第一次在8核CPU上跑A3C时训练速度比单线程快了近6倍它的妙处在于创建多个worker线程并行与环境交互就像组团开黑打游戏——每个worker积累的经验都会定期汇总到主网络。A2C则是A3C的同步版本虽然少了异步的复杂度但实现起来更简单。我建议新手可以从A2C入手它的核心是在同一批轨迹数据上计算所有时间步的优势估计然后用这些估计同时更新策略和价值函数。对比实验显示在CartPole环境中A2C通常能在100轮内达到最大回报而原始AC需要150轮左右。实现时有个细节容易踩坑优势归一化。我曾在HalfCheetah环境中忘记对优势做归一化结果策略更新直接崩盘。正确做法是在每批数据中减去均值、除以标准差advantages (advantages - advantages.mean()) / (advantages.std() 1e-5)3. DDPG当Actor-Critic遇见DQNDeep Deterministic Policy GradientDDPG堪称是强化学习中的混血王子。它继承了Actor-Critic的双网络结构又吸收了DQN的经验回放和目标网络特别适合像机械臂控制这类连续动作空间任务。第一次看到DDPG的四大网络结构Actor、Critic及其目标网络时我也觉得头大但拆解后就会发现它的精妙设计。经验回放是DDPG的记忆宫殿。在我的机械臂抓取实验中设置100万容量的回放缓冲区后样本效率提升了3倍。目标网络则是稳定训练的定海神针通过软更新通常τ0.005平滑跟踪主网络的变化。下面是DDPG与原始AC在Pendulum环境中的对比算法收敛速度最终表现样本效率AC慢中等低DDPG快优高噪声策略是DDPG探索环境的探路杖。早期我执着于使用复杂的OU噪声后来发现简单的高斯噪声配合线性衰减同样有效def take_action(self, state): action self.actor(state) # 训练阶段添加噪声测试阶段去掉 if self.training: noise self.sigma * np.random.randn(self.action_dim) action np.clip(action noise, -self.action_bound, self.action_bound) return action4. 实战技巧与避坑指南调试强化学习算法就像中医把脉需要观察多个信号。我总结了几条实用经验值函数膨胀当Critic输出持续大于真实回报时说明出现了过估计。这时可以尝试减小Critic的学习率或者像TD3那样引入双重Critic。探索不足如果Actor的动作品种单一可以尝试在训练初期增大噪声强度如设置sigma从0.2线性衰减到0.01。训练波动大这通常是目标网络更新太频繁导致的。除了调小τ值还可以增加批次大小如从64调到256。在机械臂控制项目中我发现DDPG对超参数特别敏感。下面这组参数经过多次调优适合大多数连续控制任务{ actor_lr: 1e-4, # 策略网络学习率 critic_lr: 1e-3, # 价值网络学习率 gamma: 0.99, # 折扣因子 tau: 0.005, # 软更新系数 buffer_size: 1e6, # 回放缓冲区大小 sigma: 0.1, # 初始噪声强度 batch_size: 128 # 训练批次大小 }对于更复杂的任务如四足机器人行走可以考虑进阶技巧使用优先级经验回放Prioritized Experience Replay添加层标准化Layer Normalization实现N-step TD回报这些年在工业场景中应用DDPG最大的体会是理论上的完美算法在实际中可能处处碰壁而一些工程trick反而能带来突破性提升。比如在物流仓库AGV调度项目中给奖励函数加上精心设计的形状奖励shaped reward比单纯用最终到达奖励训练快10倍。

更多文章