前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >强化学习系列(七)--DDPG

强化学习系列(七)--DDPG

原创
作者头像
languageX
发布2022-04-01 10:06:47
1.7K0
发布2022-04-01 10:06:47
举报
文章被收录于专栏:计算机视觉CV计算机视觉CV

DDPG(deep deterministic policy gradient),深度确定性策略梯度算法。

PPO(Proximal Policy Optimization),近端策略优化算法。

DDPG和PPO都是AC框架。

本文主要介绍DDPG。

DDPG

从名字我们也可以看出DDPG就是DPG和DQN的结合。

这篇文章很详细的介绍了三者关系:https://zhuanlan.zhihu.com/p/337976595

我们先先回顾一些算法

DPG--deterministic policy gradient

PG之前已经介绍过,就是通过参数化概率分布来表示策略,选择一个动作,目的是让累计价值最高。其中动作a是根据概率的随机选取,也就是Stochastic Policy Gradient。

DPG就是不用概率分布表示policy,而是用一个确定的函数表示。也就是给定了s,选取的a是确定的,也就是deterministic Policy Gradient。

相对于Stochastic Policy,deterministic Policy 计算上更高效,缺点也很明显就是缺少了探索性。为了解决探索问题,DPG采用off-policy方法,也就是采样的policy和待优化目标policy是不同策略;采样的policy是随机的,而待优化的策略是确定的。

DQN--deep Q-network

DQN也有Actor和Critic网络,其中Actor网络输出一个动作A,动作和状态都要输出到Critic网络,目标是获取的Q值最大化。

在DQN之前,用神经网络拟合Q函数,但是训练会非常不稳定,主要原因是:

  1. Q函数(待优化的对象)和r+\gamma maxQ(s',a') 优化的target都是来自于同一个Q函数,也就是data和label是来自一个模型,会导致模型很难学习;
  2. Q函数的一小点改动会很大影响策略,从而改变观测数据的分布;
  3. 观测序列数据,后面的状态,动作和reward强烈依赖前面的数据。

QDN提出改进来解决以上问题:

  1. 数据只存储四元组(s_t,a_t,r_t,s_{t+1}),让四元组和四元组之间没有关联性
  2. 把待优化的Q函数和target的Q函数分为不同策略,待优化的Q函数更新一段时间参数后,才将参数赋值给目标Q函数。训练数据的target都是target的Q函数生成的,而待优化的Q函数参数更新对训练数据不会有改变。所以data(待优化的Q生成)和label(target的Q函数生成)之间没有相关性。

DDPG--deep deterministic policy gradient

DDPG是结合了DPG和DQN。

先看下DQN的流程:

DQN流程图
DQN流程图

在选择Q值最大的A_{t+1}时,用到了max,所以DQN不能解决连续控制问题。而DPG没有采用随机policy,而是采用的确定policy,不用寻找最大化操作,所以DDPG就将DQN中神经网络拟合Q函数的两个优化点用到DPG中,将DPG中的Q函数用一个神经网络预测,但是其中使用了off-policy。

所以DDPG和DPG一样,更新网络和目标网络也是不同的策略,所以属于off_policy。

借鉴https://blog.csdn.net/kenneth_yu/article/details/78478356中流程图,可以比较清晰的了解DDPG的算法。

总结步骤:

代码参考:https://github.com/louisnino/RLcode/blob/master/tutorial_DDPG.py

  1. 迭代探索,每次探索time-steps,每个step,actor网络选取动作,环境执行动作得到新的状态和reward,进行存储。一次探索后可以存储序列数据,对序列数据进行采样。注意这里choose_action和存储数据的来源是online策略网络

核心代码:

代码语言:javascript
复制
for i in range(MAX_EPISODES):
    t1 = time.time()
    s = env.reset()
    ep_reward = 0
    for j in range(MAX_EP_STEPS):
        # Add exploration noise
        a = ddpg.choose_action(s)
        # 增加探索性
        a = np.clip(np.random.normal(a, VAR), -2, 2)
        # 与环境进行互动
        s_, r, done, info = env.step(a)
        # 保存s,a,r,s_
        ddpg.store_transition(s, a, r / 10, s_)
        if ddpg.pointer > MEMORY_CAPACITY:
            ddpg.learn()

  1. 保存了一定量数据后,就可以进行learn了。

采样数据N含有(s,a,r,s_{-}), 将s_{-}给到target策略网络actor_target得到s_{-}(a_{-},s_{-})给到target-Q网络critic_target得到q_{-}(a, s)给到待优化online-Q网络critic得到q

所以td-error= r + \gamma * q_{-}。以此更新critic网络。

s给到actor得到a,(s,a)给到critic得到q。Actor的目标就是让q最大化,以此更新Actor网络。

核心代码:

代码语言:javascript
复制
def learn(self):
    indices = np.random.choice(MEMORY_CAPACITY, size=BATCH_SIZE)  
    bt = self.memory[indices, :]  # 根据indices,选取数据bt,相当于随机
    bs = bt[:, :self.s_dim]  # 从bt获得数据s
    ba = bt[:, self.s_dim:self.s_dim + self.a_dim]  # 从bt获得数据a
    br = bt[:, -self.s_dim - 1:-self.s_dim]  # 从bt获得数据r
    bs_ = bt[:, -self.s_dim:]  # 从bt获得数据s'

    # Critic:td_error = br + gamma * q_ - q
    with tf.GradientTape() as tape:
        # q_由critic_target预测,critic的a_由actor_target预测
        a_ = self.actor_target(bs_)
        q_ = self.critic_target([bs_, a_])
        y = br + GAMMA * q_
        # q由critic预测
        q = self.critic([bs, ba])
        td_error = tf.losses.mean_squared_error(y, q)
    c_grads = tape.gradient(td_error, self.critic.trainable_weights)
    self.critic_opt.apply_gradients(zip(c_grads, self.critic.trainable_weights))

    # Actor:最大化Q值
    with tf.GradientTape() as tape:
        # 待优化actor,输入是s
        a = self.actor(bs)
        # q值由critic得到
        q = self.critic([bs, a])
        # 最大化q,等价最小化-q
        a_loss = -tf.reduce_mean(q)
    a_grads = tape.gradient(a_loss, self.actor.trainable_weights)
    self.actor_opt.apply_gradients(zip(a_grads, self.actor.trainable_weights))

3. 一次探索学习后,将online网络的critic和actor参数更新到target网络中。

核心代码:

代码语言:javascript
复制
def ema_update(self):
    """
    滑动平均更新
    """
    # 其实和之前的硬更新类似,不过在更新赋值之前,用一个ema.average。
    paras = self.actor.trainable_weights + self.critic.trainable_weights  # 获取要更新的参数包括actor和critic的
    self.ema.apply(paras)  # 主要是建立影子参数
    for i, j in zip(self.actor_target.trainable_weights + self.critic_target.trainable_weights, paras):
        i.assign(self.ema.average(j))  # 用滑动平均赋值

参考:

https://zhuanlan.zhihu.com/p/111257402

https://blog.csdn.net/kenneth_yu/article/details/78478356

http://speech.ee.ntu.edu.tw/~tlkagk/courses_MLDS18.html

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • DDPG
    • DPG--deterministic policy gradient
      • DQN--deep Q-network
        • DDPG--deep deterministic policy gradient
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档