深Q网络不是在学习

Kay*_*sch 3 artificial-intelligence reinforcement-learning neural-network q-learning tensorflow

我尝试使用Tensorflow和OpenAI的Gym来编写Deep Q网络来玩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')
Run Code Online (Sandbox Code Playgroud)

问题是:

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

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

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

Den*_*ers 7

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

  • 100集似乎不是很多.在下图中,您可以看到Breakout()上Double DQN的某些变体(略高于DQN)的学习曲线.-axis上的训练时间x以数百万帧为单位进行测量,而不是在剧集中进行测量.我不确切知道哪些100集会出现在x-axis上,但我认为它不会很远.在100集之后,期待任何一种不错的表现可能是不合理的.

OpenAI基线DQN学习曲线突破

  • 看起来你在你的网络中使用了辍学.我建议摆脱辍学.我不确定100%肯定在深度强化学习中使用辍学是不好的,但1)它肯定不常见,2)直觉上似乎没有必要.辍学用于在监督学习中对抗过度拟合,但过度拟合在强化学习中并不是一个很大的风险(至少,如果你只是试图像你在这里一样训练单个游戏).

  • discount_factor = 0.5看起来非常低,这使得不可能将长期奖励传播回到少数几个行动之上.一些事情discount_factor = 0.99会更加普遍.

  • if (episode+1)/num_episodes > np.random.uniform():,这段代码看起来好像epsilon1.0 - 1 / num_episodes第一集到1.0 - num_episodes / num_episodes = 0.0最后一集都在衰退.根据您当前的num_episodes = 100,这意味着它从腐烂0.990.0100发作.在我看来,它似乎太快了.作为参考,在原DQN纸,epsilon慢慢地从线性衰减1.00.1超过百万帧,并且永远保持固定后.

  • 您没有使用体验重播,也没有使用单独的目标网络,如原始DQN文件中所述.所有点以上是显著更容易寻找到并解决,所以我建议,第一.这可能已经足以在学习之后真正开始看到一些优于随机的性能,但可能仍然会比这两个添加更糟糕.