美文网首页
DDPG实战

DDPG实战

作者: CristianoC | 来源:发表于2019-08-01 10:43 被阅读0次

    1.前言

    这次的内容主要是针对上一下讲解的DDPG理论部分进行实战,实战效果如下:


    image

    2.代码

    2.1 主结构

    我们先看一下tensorboard输出的图:

    image
    乍一看有点复杂,但是我们拆开看就容易了。我们来看看ActorCritic中各有什么结构把。
    image
    搭建的代码如下:
    class Actor(object):
        def __init__(self):
            ...
            with tf.variable_scope('Actor'):
                # 这个网络用于及时更新参数
                self.a = self._build_net(S, scope='eval_net', trainable=True)
                # 这个网络不及时更新参数, 用于预测 Critic 的 Q_target 中的 action
                self.a_ = self._build_net(S_, scope='target_net', trainable=False)
            ...
    
    class Critic(object):
        def __init__(self):
            with tf.variable_scope('Critic'):
                # 这个网络是用于及时更新参数
                self.a = a  # 这个 a 是来自 Actor 的, 但是 self.a 在更新 Critic 的时候是之前选择的 a 而不是来自 Actor 的 a.
                self.q = self._build_net(S, self.a, 'eval_net', trainable=True)
                # 这个网络不及时更新参数, 用于给出 Actor 更新参数时的 Gradient ascent 强度
                self.q_ = self._build_net(S_, a_, 'target_net', trainable=False)
    

    2.2 Actor Critic

    有了对Actor Critic每个里面各两个神经网络结构的了解,我们再来具体看看他们是如何进行交流,传递信息的。我们从Actor的学习更新方式开始说起。

    image
    这张图我们就能一眼看穿Actor的更新到底基于什么东西。可以看出,它使用了两个eval_net,所以Actorclass中用于train的代码我们这样写:
    with tf.variable_scope('policy_grads'):
        # 这是在计算 (dQ/da) * (da/dparams)
        self.policy_grads = tf.gradients(
            ys=self.a, xs=self.e_params, # 计算 ys 对于 xs 的梯度
            grad_ys=a_grads # 这是从 Critic 来的 dQ/da
        )
    with tf.variable_scope('A_train'):
        opt = tf.train.AdamOptimizer(-self.lr)  # 负的学习率为了使我们计算的梯度往上升, 和 Policy Gradient 中的方式一个性质
        self.train_op = opt.apply_gradients(zip(self.policy_grads, self.e_params)) # 对 eval_net 的参数更新
    

    同时下面也提到的传送给Actora_grad应该用Tensorflow怎么计算。这个a_gradCriticclass里面的。这个a是来自Actor根据s计算而来的:

    with tf.variable_scope('a_grad'):
        self.a_grads = tf.gradients(self.q, a)[0]   # dQ/da
    

    而在Critic中,我们用的东西简单一点

    image
    下面就是Critic更新时的代码
    # 计算 target Q
    with tf.variable_scope('target_q'):
        self.target_q = R + self.gamma * self.q_    # self.q_ 根据 Actor 的 target_net 来的
    # 计算误差并反向传递误差
    with tf.variable_scope('TD_error'):
        self.loss = tf.reduce_mean(tf.squared_difference(self.target_q, self.q))  # self.q 又基于 Actor 的 target_net
    with tf.variable_scope('C_train'):
        self.train_op = tf.train.AdamOptimizer(self.lr).minimize(self.loss)
    

    最后我们建立并把ActorCritic融合在一起的时候是这样写的。

    actor = Actor(...)
    critic = Critic(..., actor.a, actor.a_)  # 将 actor 同它的 eval_net/target_net 产生的 a/a_ 传给 Critic
    actor.add_grad_to_graph(critic.a_grads) # 将 critic 产出的 dQ/da 加入到 Actor 的 Graph 中去
    

    2.3 经验池

    以下是类似于DQN中的记忆库代码,我们用一个class来建立。

    class Memory(object):
        def __init__(self, capacity, dims):
            #用numpy初始化记忆库
            self.capacity = capacity
            self.data = np.zeros((capacity, dims))
            self.pointer = 0
    
        def store_transition(self, s, a, r, s_):
            #保存每次记忆在numpy array里
            transition = np.hstack((s, a, [r], s_))
            index = self.pointer % self.capacity  # replace the old memory with new memory
            self.data[index, :] = transition
            self.pointer += 1
    
        def sample(self, n):
            #随即从记忆库中抽取n个记忆进行学习
            assert self.pointer >= self.capacity, 'Memory has not been fulfilled'
            indices = np.random.choice(self.capacity, size=n)
            return self.data[indices, :]
    

    2.4 每回合算法

    这里的回合算法只提到最重要的部分,省掉了一些没必要的,完整代码我在最后会附上我的github链接

    var = 3  # 这里初始化一个方差用于增强 actor 的探索性
    
    for i in range(MAX_EPISODES):
        ...
        for j in range(MAX_EP_STEPS):
            ...
    
            a = actor.choose_action(s)
            a = np.clip(np.random.normal(a, var), -2, 2) # 增强探索性
            s_, r, done, info = env.step(a)
    
            M.store_transition(s, a, r / 10, s_)   # 记忆库
    
            if M.pointer > MEMORY_CAPACITY: # 记忆库头一次满了以后
                var *= .9998    # 逐渐降低探索性
                b_M = M.sample(BATCH_SIZE)
                ...   # 将 b_M 拆分成下面的输入信息
                critic.learn(b_s, b_a, b_r, b_s_)
                actor.learn(b_s)
    
            s = s_
    
            if j == MAX_EP_STEPS-1:
                break
    

    完整代码:https://github.com/cristianoc20/RL_learning/tree/master/DDPG
    参考:https://github.com/MorvanZhou/Reinforcement-learning-with-tensorflow

    相关文章

      网友评论

          本文标题:DDPG实战

          本文链接:https://www.haomeiwen.com/subject/vrxqdctx.html