演员批评家政策损失将为零(无改善)

时间:2018-08-08 16:06:14

标签: python tensorflow keras reinforcement-learning

我创建了一个演员评论家模型来测试一些OpenAI体育馆环境。但是,在某些环境中我遇到了问题。

CartPole:模型最终收敛并获得最大奖励。但是,由于某些原因,如果我仅使用策略梯度方法而不使用值函数/优势,则收敛速度更快。

MountainCar,Acrobot:这两个模型都有负面奖励。如果您的经纪人需要10秒才能完成任务,您的奖励将是-10。出于某种原因,当我尝试解决带有负奖励的环境时,我的策略从负值开始,然后逐渐收敛到0。价值损失开始高得离谱,并开始减少,尽管它在某个时刻处于平稳状态(当策略崩溃时)。谁能帮助我诊断问题?我添加了一些日志记录语句以及相关的情景值。

from scipy.signal import lfilter
import numpy as np
import gym
import tensorflow as tf

layers = tf.keras.layers

tf.enable_eager_execution()


def discount(x, gamma):
    return lfilter([1], [1, -gamma], x[::-1], axis=0)[::-1]


def boltzmann(probs):
    return tf.multinomial(tf.log(probs), 1)


def greedy(probs):
    return tf.argmax(probs)


def gae(bval, vals, rews):
    vboot = np.hstack((vals, bval))
    return rews * vboot[1:] - vals


class PG(tf.keras.Model):

    def __init__(self, n_actions, selection_strategy=boltzmann, lr=0.001):
        super(PG, self).__init__()
        self.fc1 = layers.Dense(64, activation='relu', kernel_initializer=tf.initializers.orthogonal(1))
        self.fc2 = layers.Dense(64, activation='relu', kernel_initializer=tf.initializers.orthogonal(1))
        self.pol = layers.Dense(n_actions, kernel_initializer=tf.initializers.orthogonal(0.01))
        self.val = layers.Dense(1, kernel_initializer=tf.initializers.orthogonal(1))
        self.optimizer = tf.train.AdamOptimizer(learning_rate=lr)
        self.selection_strategy = selection_strategy


    def call(self, input):
        x = tf.constant(input, dtype=tf.float32)
        x = self.fc1(x)
        x = self.fc2(x)
        return self.pol(x), self.val(x)


    def select_action(self, logits):
        probs = tf.nn.softmax(logits)
        a = self.selection_strategy(probs)
        return tf.squeeze(a, axis=[0, 1]).numpy()


def sample(env, model):
    obs, act, rews, vals = [], [], [], []
    ob = env.reset()
    done = False

    while not done:
        # env.render()
        logits, value = model([ob])
        a = model.select_action(logits)
        value = tf.squeeze(value, axis=[0, 1])

        next_ob, r, done, _ = env.step(a)
        obs.append(ob)
        act.append(a)
        rews.append(r)
        vals.append(value.numpy())

        ob = next_ob

    return np.array(obs), np.array(act), np.array(rews), np.array(vals)


# Hyperparameters
GAMMA = 0.99
SAMPLES = 10000000
MAX_GRAD_NORM = 20
UPDATE_INTERVAL = 20


env = gym.make('MountainCar-v0')
model = PG(env.action_space.n)


for t in range(1, SAMPLES + 1):
    obs, act, rews, vals = sample(env, model)
    d_rew = discount(rews, GAMMA)
    d_rew = (d_rew - np.mean(d_rew)) / np.std(d_rew)

    advs = d_rew - vals


    with tf.GradientTape() as tape:

        logits, values = model(obs)
        values = tf.squeeze(values)
        one_hot = tf.one_hot(act, env.action_space.n, dtype=tf.float32)
        xentropy = tf.nn.softmax_cross_entropy_with_logits_v2(labels=one_hot, logits=logits)
        policy_loss = tf.reduce_mean(xentropy * advs)

        diff = d_rew - values

        value_loss = tf.reduce_mean(tf.square(diff))

        policy = tf.nn.softmax(logits)
        entropy = tf.reduce_mean(policy * tf.log(policy + 1e-20))

        total_loss = policy_loss + 0.5 * value_loss - 0.01 * entropy


    grads = tape.gradient(total_loss, model.trainable_weights)
    grads, gl_norm = tf.clip_by_global_norm(grads, MAX_GRAD_NORM)
    model.optimizer.apply_gradients(zip(grads, model.trainable_weights))


    if t % UPDATE_INTERVAL == 0 and not t is 0:
        print("BR: {0}, Len: {1}, Pol: {2:.4f}, Val: {3:.4f}, Ent: {4:.4f}"
              .format(np.sum(rews), len(rews), policy_loss, value_loss, entropy))

ER =总奖励,Len =情节持续时间,Pol =政策损失,Val =价值损失,Ent =熵,Grad Norm = Gradient Norm

ER: -200.0, Len: 200, Pol: 0.0656, Val: 1.0032, Ent: -0.3661, Grad Norm: 0.0901
ER: -200.0, Len: 200, Pol: -0.0384, Val: 1.0006, Ent: -0.3640, Grad Norm: 0.1186
ER: -200.0, Len: 200, Pol: -0.0585, Val: 1.0034, Ent: -0.3605, Grad Norm: 0.0963
ER: -200.0, Len: 200, Pol: -0.0650, Val: 1.0021, Ent: -0.3595, Grad Norm: 0.1149
ER: -200.0, Len: 200, Pol: 0.0007, Val: 1.0011, Ent: -0.3581, Grad Norm: 0.0893
ER: -200.0, Len: 200, Pol: 0.0024, Val: 1.0007, Ent: -0.3556, Grad Norm: 0.0951
ER: -200.0, Len: 200, Pol: 0.0114, Val: 1.0006, Ent: -0.3529, Grad Norm: 0.0954
ER: -200.0, Len: 200, Pol: 0.0310, Val: 1.0006, Ent: -0.3493, Grad Norm: 0.1060
ER: -200.0, Len: 200, Pol: -0.0187, Val: 0.9997, Ent: -0.3449, Grad Norm: 0.1111
ER: -200.0, Len: 200, Pol: -0.0367, Val: 0.9975, Ent: -0.3348, Grad Norm: 0.1302
ER: -200.0, Len: 200, Pol: -0.0349, Val: 0.9988, Ent: -0.3250, Grad Norm: 0.0884

1 个答案:

答案 0 :(得分:0)

我不确定是否可以完全回答您的问题,但是我会提供2美分,希望其他人来填写其余的内容!

  

模型最终收敛并获得最大奖励。但是,由于某些原因,如果我仅使用策略梯度方法而不使用值函数/优势,则收敛速度更快。

这是因为CartPole具有非常简单的动作空间,可以左右移动。该问题的解决方案非常简单,添加到系统中的非常基本的噪声足以使系统探索其状态空间。在演员评论家方法中,需要调整更多的权重和偏见。并且由于有更多参数需要调整,因此训练时间更长。

  

由于某种原因,当我尝试用负奖励解决环境时,我的策略从负值开始,然后逐渐收敛到0。

xentropy = tf.nn.softmax_cross_entropy_with_logits_v2(labels=one_hot, logits=logits)
    policy_loss = tf.reduce_mean(xentropy * advs)

对于这一部分,我认为实际的损失公式是

Loss = - log(policy) * Advantage

存在负数的地方,例如i https://math.stackexchange.com/questions/2730874/cross-entropy-loss-in-reinforcement-learning。在您的公式中,我不确定您是否将此负数包括在损失函数中。我在构建“策略梯度”时亲自编写了自己的损失函数,但也许您的Tensorflow函数会考虑到这一点。

对于该值,由于其本质上是在猜测最佳值,因此预期在开始时会有很高的损失。

一些其他提示和技巧是为状态,动作,奖励和s2使用重播记忆。这样,您就可以取消轨迹轨迹的关联,并可以进行“偶数”学习。如果您的状态是相关的,则可能会过度适合您的最新事件。

您现在也正在在线学习,对于更困难的RL任务来说,这是非常不稳定的。一种解决此问题的方法是通过上面的重播内存。另一种方法是小批量学习。我相信这是David Silver在论文中使用的方法。基本上,您想运行许多轨迹。在每条轨迹之后,通过TensorFlow中的tf.gradients方法执行反向传播以计算策略梯度的损失。存储这些渐变,然后针对接下来的几条轨迹再次执行此操作。经过“小批量”轨迹后,您可以平均所有运行中的所有梯度,然后执行梯度下降以更新参数。梯度下降与使用tf.apply_gradients方法在代码中所做的相同。您之所以这样做是因为环境通过模拟许多轨迹而产生了很多噪声,因此想法是,小批量的平均轨迹是概率性更高的表示,而不是一个轨迹。我个人使用的是64的迷你批次。

为了增强您在状态空间中的探索力,我建议您使用Ornstein Ulhenbeck随机过程。基本上,这是一个稳定的相关噪声系统。由于它是相关噪声,因此与使用去相关噪声(即高斯噪声)相比,它可使您离初始状态更远。因为如果使用去相关的噪声,则长期平均值将是0,因为它是0平均值,单位方差。因此,从本质上讲,如果使用与去相关的噪声,则最终将精确到开始的位置。在这里可以找到很好的解释:https://www.quora.com/Why-do-we-use-the-Ornstein-Uhlenbeck-Process-in-the-exploration-of-DDPG Python的代码可以在这里找到:https://github.com/openai/baselines/blob/master/baselines/ddpg/noise.py在代码的最底部。只需将这种噪音添加到您的动作中即可改善探索。

摘要

您的保单丢失功能的标志可能不正确。 为了改善学习,在线学习困难的问题非常困难。两种易于实现的解决方法是:

  • 重播记忆
  • 小批量梯度下降,而不是当前代码中的随机梯度下降

要增加稳定性,还可以使用目标网络。目标网络的想法是因为在初始阶段,您的权重将很快更新。目标网络将位于系统中,以使该问题成为“非移动目标”问题。目标网络的权重被冻结,因此问题不会发生,并且在每个情节之后,“真实”网络都会更新。在x次迭代之后,将目标网络更新为真实网络。但这需要更长的时间来实施。我建议先以上两个。