演员评论家政策损失为零(没有改善)
Posted
技术标签:
【中文标题】演员评论家政策损失为零(没有改善)【英文标题】:actor critic policy loss going to zero (with no improvement) 【发布时间】:2019-01-15 23:35:39 【问题描述】:我创建了一个演员评论模型来测试一些 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
【问题讨论】:
如果有任何信息缺失,请告诉我,我会更新问题。 你能测试它是否进行了足够的探索吗?也许epsilon
-greedy 可以表现得更好,iirc 博尔兹曼探索有时会变得“过于极端”并且过早地表现得太贪婪?不幸的是,我没有足够的策略梯度方法经验来确定问题所在。您可能会在 ai.stackexchange.com 或 stats.stackexchange.com 上找到更多领域专家,但不幸的是,您将无法继续那里的赏金:(
还有;你训练多长时间?您是否与其他人/其他算法的结果进行了比较,您确定成功的训练在您运行它的时间内应该是可行的吗?
【参考方案1】:
我不确定我是否可以完全回答你的问题,但我会提供我的 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公式是
Loss = - log(policy) * Advantage
哪里有否定句,比如 i https://math.stackexchange.com/questions/2730874/cross-entropy-loss-in-reinforcement-learning。在你的表述中,我不确定你是否将这个负数包含在你的损失函数中。我在构建 Policy Gradient 时亲自编写了自己的损失函数,但您的 Tensorflow 函数可能会考虑到这一点。
至于值,一开始预计会有很高的损失,因为它本质上是在猜测最优值是多少。
一些额外的提示和技巧是使用回放记忆来记录您的状态、动作、奖励和 s2。通过这种方式,您可以对轨迹进行去关联,并允许“均匀”学习。如果你的状态是相关的,它往往会过度拟合你最近的事件。
您目前也在在线学习,这对于更困难的 RL 任务来说非常不稳定。解决此问题的一种方法是通过上述重放内存。另一种方法是小批量学习。我相信这就是 David Silver 在他的论文中使用的方法。基本上,您想要运行许多轨迹。在每个轨迹之后,通过 TensorFlow 中的 tf.gradients 方法执行反向传播以计算策略梯度的损失。存储这些梯度,并在接下来的几个轨迹中再次执行此操作。在“小批量”数量的轨迹之后,您然后平均所有运行中的所有梯度,然后执行梯度下降以更新您的参数。梯度下降与您在代码中使用 tf.apply_gradients 方法所做的相同。你这样做是因为环境有很多噪音,通过模拟许多轨迹,这个想法是小批量的平均轨迹是一种更有概率的表示,而不是一个轨迹。我个人使用 64 个的 mini-batch。
为了增强您在状态空间中的探索,我建议您使用 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 次迭代,将目标网络更新为真实网络。但这需要更长的时间来实现。我会先推荐以上两个。
【讨论】:
softmax_crossentropy_with_logits() 直接添加负号,这就是我跳过它的原因。关于 minibatch 的考虑,我还尝试在应用之前累积多个 epoch 的梯度,结果相似。主要问题是剧集很短,我无法生成任何奖励高于最小值的剧集(因为在进行随机探索时购物车永远不会到达顶部)。但是,我会尝试您的最后一个建议。非常感谢!以上是关于演员评论家政策损失为零(没有改善)的主要内容,如果未能解决你的问题,请参考以下文章