【问题标题】:Deep Q Network is not learning深度 Q 网络不学习
【发布时间】:2018-09-25 05:22:37
【问题描述】:

我尝试编写一个 Deep Q 网络来使用 Tensorflow 和 OpenAI 的 Gym 玩 Atari 游戏。 这是我的代码:

import tensorflow as tf
import gym
import numpy as np
import os

env_name = 'Breakout-v0'
env = gym.make(env_name)
num_episodes = 100
input_data = tf.placeholder(tf.float32,(None,)+env.observation_space.shape)
output_labels = tf.placeholder(tf.float32,(None,env.action_space.n))

def convnet(data):
    layer1 = tf.layers.conv2d(data,32,5,activation=tf.nn.relu)
    layer1_dropout = tf.nn.dropout(layer1,0.8)
    layer2 = tf.layers.conv2d(layer1_dropout,64,5,activation=tf.nn.relu)
    layer2_dropout = tf.nn.dropout(layer2,0.8)
    layer3 = tf.layers.conv2d(layer2_dropout,128,5,activation=tf.nn.relu)
    layer3_dropout = tf.nn.dropout(layer3,0.8)
    layer4 = tf.layers.dense(layer3_dropout,units=128,activation=tf.nn.softmax,kernel_initializer=tf.zeros_initializer)
    layer5 = tf.layers.flatten(layer4)
    layer5_dropout = tf.nn.dropout(layer5,0.8)
    layer6 = tf.layers.dense(layer5_dropout,units=env.action_space.n,activation=tf.nn.softmax,kernel_initializer=tf.zeros_initializer)
    return layer6

logits = convnet(input_data)
loss = tf.losses.sigmoid_cross_entropy(output_labels,logits)
train = tf.train.GradientDescentOptimizer(0.001).minimize(loss)
saver = tf.train.Saver()
init = tf.global_variables_initializer()
discount_factor = 0.5

with tf.Session() as sess:
    sess.run(init)
    for episode in range(num_episodes):
        x = []
        y = []
        state = env.reset()
        feed = {input_data:np.array([state])}
        print('episode:', episode+1)
        while True:
            x.append(state)
            if (episode+1)/num_episodes > np.random.uniform():
                Q = sess.run(logits,feed_dict=feed)[0]
                action = np.argmax(Q)
            else:
                action = env.action_space.sample()
            state,reward,done,info = env.step(action)
            Q = sess.run(logits,feed_dict=feed)[0]
            new_Q = np.zeros(Q.shape)
            new_Q[action] = reward+np.amax(Q)*discount_factor
            y.append(new_Q)
            if done:
                break

        for sample in range(len(x)):
            _,l = sess.run([train,loss],feed_dict={input_data:[x[sample]],output_labels:[y[sample]]})
            print('training loss on sample '+str(sample+1)+': '+str(l))
    saver.save(sess,os.getcwd()+'/'+env_name+'-DQN.ckpt')

问题是:

  1. 训练时损失没有减少,始终在 0.7 或 0.8 左右
  2. 当我在 Breakout 环境中测试网络时,即使在我训练了 1000 集之后,这些动作仍然看起来有点随机,而且它很少击中球。

我已经尝试使用不同的损失函数(softmax 交叉熵和均方误差),使用另一个优化器 (Adam) 并提高学习率,但没有任何改变。

谁能告诉我如何解决这个问题?

【问题讨论】:

    标签: tensorflow neural-network artificial-intelligence reinforcement-learning q-learning


    【解决方案1】:

    以下是您可以研究的一些突出的事情(在这类情况下,如果不确切尝试哪些问题是最重要的问题,总是很难确定):

    • 100 集似乎并不多。在下图中,您可以在 Breakout (source) 上看到 Double DQN 的一些变体(比 DQN 稍微先进一点)的学习曲线。 x 轴上的训练时间以百万帧为单位,而不是以剧集为单位。我不知道 x 轴上 100 集的确切位置,但我认为不会太远。在 100 集之后期待任何体面的表现可能根本不合理。


    (来源:openai.com

    • 您的网络中似乎正在使用 dropout。我建议摆脱辍学。我不能 100% 确定在深度强化学习中使用 dropout 是不好的,但是 1)它肯定不常见,并且 2)直觉上它似乎没有必要。 Dropout 用于对抗监督学习中的过拟合,但在强化学习中过拟合并没有太大的风险(至少,如果你只是想像现在这样一次训练一个游戏,则不会)。

    • discount_factor = 0.5 似乎非常低,这将导致无法将长期奖励传播回多个操作。类似于discount_factor = 0.99 的东西会更常见。

    • if (episode+1)/num_episodes > np.random.uniform():,这段代码看起来基本上是从第一集中的1.0 - 1 / num_episodes 衰减到最后一集中的1.0 - num_episodes / num_episodes = 0.0epsilon。对于您当前的num_episodes = 100,这意味着它在100 剧集中从0.99 衰减到0.0。在我看来,它的衰变太快了。作为参考,在original DQN paper中,epsilon1.0慢慢线性衰减到0.1超过100万帧,之后永远保持不变。

    • 您没有使用体验回放,也没有使用单独的目标网络,如 the original DQN paper 中所述。以上所有要点都明显更容易查看和修复,所以我建议先这样做。这可能已经足以在学习后实际开始看到一些优于随机的性能,但可能仍会比这两个添加后的性能更差。

    【讨论】:

    • 抱歉这么久没有回复。我将折扣因子提高到 0.99,移除了 dropout 层,添加了样本大小为 64 的体验回放,并让它运行了 5000 集(120 万帧),但它的性能仍然与随机播放没有区别。知道我能做什么吗?
    • 如果我在回答中查看这些情节,似乎该情节中的所有算法(都比 vanilla DQN 稍微先进一点)只是开始增加超过平均剧集奖励@987654342 @ 在第一个“块”的大约 10% 处。图中的第一个“块”是代理看到的 5000 万帧,所以 10% 的点大约是 500 万帧。基于此,看起来你确实可能需要超过 500 万帧而不是 120 万帧才能开始看到比随机更好的东西
    • 除此之外,如果经验回放的样本大小为 64,您的意思是经验回放缓冲区的大小,这似乎相当低。我相信像... 100K 或 100 万这样的值更常见,不是 100% 肯定在我的脑海中,请参阅 DQN 论文。您是否也已经研究过我回答中的第三点(epsilon 的衰减)?
    • 我认为随着 epsilon 的衰减,您的意思是仅训练 100 集的网络所产生的步长。请再给我解释一下好吗?
    • @KayJersch 是的,你是对的,在你的代码中,通过改变你训练的集数,你也会增加epsilon。不过,您可能仍希望确保它不会低于某个值(如0.1)。例如,通过将 if 语句更改为:if max(0.1, (episode+1)/num_episodes) > np.random.uniform():
    【解决方案2】:

    首先让我们详细描述一下这些现象。神经网络的误差函数的值可以在 1.0(最大误差)和 0.0(目标)之间。学习算法背后的想法是将误差函数降低到零,这意味着代理可以完美地玩游戏。一开始学习效果很好,误差值在减小,但曲线在一定水平上是平行的。这意味着 CPU 正在计算大量数据,CPU 消耗能量,但误差值并没有减少。

    好消息是,它与您的源代码无关。你的 Deep Q 网络实现很棒,我什至认为你的源代码看起来比普通程序员的代码更好。这个问题与 OpenAI 健身房的环境难度有关。这意味着,在像“将玩家带到目标位置”这样的简单游戏中,网络学习得很好,而在像“蒙特祖玛的复仇”这样的困难问题上,上面描述的具有恒定误差函数的问题正在发生。克服问题并不像看起来那么容易。这不是微调神经网络的问题,而是发明一种处理复杂游戏的新方法。在分层问题解决等文献策略中,使用自然语言基础和特定领域本体来解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-15
      • 1970-01-01
      • 2021-08-18
      相关资源
      最近更新 更多