簡體   English   中英

Deep Q Network無法學習

[英]Deep Q Network is not learning

我嘗試編寫一個Deep Q Network,以使用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. 即使在訓練了1000集之后,我仍在Breakout環境中測試網絡時,動作似乎仍然是隨機的,很少碰到球。

我已經嘗試使用其他損失函數(softmax交叉熵和均方誤差),使用另一個優化器(Adam)並提高了學習率,但沒有任何變化。

有人可以告訴我如何解決此問題嗎?

您可以研究以下一些突出的問題(在這種情況下,很難准確地分辨出哪些是最重要的問題,這很難確定):

  • 100集似乎並不多。 在下圖中,您可以在Breakout( )上看到Double DQN(比DQN稍先進)的一些變體的學習曲線。 x軸上的訓練時間以那里的數百萬幀而不是情節來衡量。 我不確切知道在x軸上會出現100集,但是我認為這不會太遙遠。在100集之后再期望有任何類型的表現可能根本不合理。

OpenAI基線DQN學習曲線突破
(來源: openai.com

  • 看來您正在網絡中使用輟學。 我建議擺脫輟學。 我不確定100%肯定會在深度強化學習中使用輟學很不好,但是1)這當然不常見,並且2)直觀上似乎沒有必要。 輟學被用來與監督學習中的過度擬合作斗爭,但是過度擬合在強化學習中並沒有太大的風險(至少,如果您只是想像在這里那樣只是一次嘗試訓練單個游戲,則不會如此)。

  • discount_factor = 0.5似乎非常低,這將使得不可能將長期獎勵傳播給少數行動。 Discount_factor discount_factor = 0.99會更常見。

  • if (episode+1)/num_episodes > np.random.uniform():此代碼看起來1.0 - 1 / num_episodes是將第一集中的epsilon1.0 - num_episodes / num_episodes = 0.01.0 - num_episodes / num_episodes = 0.0在最后一集中。 當前num_episodes = 100 ,這意味着它在100情節中從0.99衰減為0.0 在我看來,它的衰減速度太快了。 作為參考,在原始DQN論文中epsilon100萬幀中1.0緩慢線性衰減到0.1 ,並在此后永久保持不變。

  • 您沒有使用“體驗重播”,也沒有使用單獨的目標網絡,如原始DQN文件所述 上面的所有要點都非常容易檢查和修復,因此我建議首先這樣做。 在學習之后,這可能已經足以開始實際看到比隨機性能更好的性能,但仍可能會比添加這兩個性能差。

首先,讓我們詳細描述現象。 神經網絡的誤差函數的值可以在1.0(最大誤差)和0.0(目標)之間。 學習算法的思想是將誤差函數降低到零,這意味着代理可以完美地玩游戲。 一開始學習效果很好,誤差值減小了,但是曲線在一定水平上是平行的。 這意味着CPU正在計算大量數據,CPU消耗了能量,但錯誤值不再減小。

好消息是,它與您的源代碼無關。 我什至可以假設,您對Deep Q網絡的實現很棒,您的源代碼看起來比普通程序員的代碼更好。 問題與OpenAI體育館的環境困難有關。 這意味着,在諸如“將玩家帶到目標位置”之類的簡單游戲中,網絡學習良好,而在諸如“蒙特祖瑪的復仇”之類的困難問題上,上述具有恆定誤差功能的問題正在發生。 克服問題並不像看起來那樣容易。 這不是微調神經網絡的問題,而是發明一種處理復雜游戲的新方法。 在諸如分層問題解決,自然語言基礎和領域特定本體之類的文獻策略中,都使用了策略來解決該問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM