基于tensorflow的最簡單的強化學(xué)習(xí)入門-part0:Q-learning和神經(jīng)網(wǎng)絡(luò)

基于tensorflow的最簡單的強化學(xué)習(xí)入門-part0:Q學(xué)習(xí)和神經(jīng)網(wǎng)絡(luò)

本文翻譯自 Simple Reinforcement Learning with Tensorflow Part 0: Q-Learning with Tables and Neural Networks, 作者是 Arthur Juliani, 原文鏈接

在這個增強學(xué)習(xí)系列的教程中,我們打算探索一些列稱為==Q-learning==的增強學(xué)習(xí)算法,它和之前教程介紹過的基于==策略梯度policy-base==的增強算法有所不同。

我們將從實現(xiàn)一個簡單的查找表算法開始,然后展示如何使用tensorflow實現(xiàn)神經(jīng)網(wǎng)絡(luò)算法。考慮到上述安排,我們從基礎(chǔ)開始,所以這篇教程作為整個系列的part-0。希望通過這個系列的教程,我們在理解Q-learning之后,能夠結(jié)合policy gradient和Q-learning方法構(gòu)建更好的增強學(xué)習(xí)網(wǎng)絡(luò)。(如果你對策略網(wǎng)絡(luò)更感興趣或者你已經(jīng)有一些Q-learning的經(jīng)驗,那么你可以從這里開始閱讀)

策略梯度算法(policy gradient)試著學(xué)習(xí)某個函數(shù),該函數(shù)可以直接把==狀態(tài)(state)映射為動作(action)的概率分布==。Q-learning和策略梯度算法不一樣,它試著學(xué)習(xí)在每個狀態(tài)下對應(yīng)的值,并且依賴該狀態(tài)執(zhí)行某一個動作。雖然兩種方法最終都允許我們給定情況下采取特定的行動,但是實現(xiàn)該目的的方法是不相同的。你也許已經(jīng)聽說深度Q-learning可以玩atari游戲,我們將要在這里討論和實現(xiàn)這些更復(fù)雜和強大的Q-learning算法。

譯者注:如果要深入了解基于策略梯度的增強學(xué)習(xí)算法,可以參考Andrej Karpathy的文章,Deep Reinforcement Learning: Pong from Pixels

Tabular Approaches for Tabular Environment(表格算法)

FrozenLake環(huán)境的規(guī)則

在本篇教程中,我們將要試著去解決來自于OpenAI gymFrozenLake問題。OpenAI gym提供了一種簡單的環(huán)境,讓研究者在一些簡單的游戲中試驗他們的方法。比如FrozenLake,該游戲包括一個4*4的網(wǎng)絡(luò)格子,每個格子可以是==起始塊,目標(biāo)塊、凍結(jié)塊或者危險塊==。我們的目標(biāo)是讓agent學(xué)習(xí)從開始塊如何行動到目標(biāo)塊上,而不是移動到危險塊上。agent可以選擇向上、向下、向左或者向右移動,同時游戲中還有可能吹來一陣風(fēng),將agent吹到任意的方塊上。在這種情況下,每個時刻都有完美的策略是不能的,但是如何避免危險洞并且到達(dá)目標(biāo)洞肯定是可行的。

增強學(xué)習(xí)需要我們定義==獎勵函數(shù)(reward function)==,那么定義每一步的獎勵是0,如果進入目標(biāo)快則獎勵為1。因此我們需要一種算法能夠?qū)W習(xí)到長期的期望獎勵,而本教程要講的Q-learning提供了這種機制。

Q-learning最簡單的實現(xiàn)方式是一個基于所有可能的狀態(tài)和執(zhí)行動作的查找表。在表中的每個單元格中,我們學(xué)習(xí)到在給定狀態(tài)下執(zhí)行特定動作的是否有效的值。在FrozenLake游戲中,我們有16種可能的狀態(tài)和4種可能的動作,給出了16*4的Q值表。我們一開始初始化表格中的所有值為0,然后根據(jù)我們觀察到的各種動作獲得的獎勵,相應(yīng)地更新表格。

我們使用稱為貝爾曼方程(bellman equation)的更新來對Q表進行更新。==該方程表明,給定動作的長期預(yù)期獎勵來自于當(dāng)前動作的即時獎勵,以及來自未來最佳動作的預(yù)期獎勵==。公式如下:

Eq 1. Q(s,a)=r+\lambda(maxQ(s'+a'))

這個公式說明,給定動作a和狀態(tài)s的q值,等于當(dāng)前的獎勵r加上未來預(yù)期的q值。$\lambda$可以看作未來期望q值和當(dāng)前獎勵相比的權(quán)重。以這種方式更新,q表就會慢慢的收斂到在給定狀態(tài)下和動作下的期望收益。下面一段python代碼就是基于FrozenLake游戲的Q-table的算法實現(xiàn)。

import gym
import numpy as np
#Load the environment
env = gym.make('FrozenLake-v0')
#Implement Q-Table learning algorithm
#Initialize table with all zeros
Q = np.zeros([env.observation_space.n,env.action_space.n])
# Set learning parameters
lr = .85
y = .99
num_episodes = 2000
#create lists to contain total rewards and steps per episode
#jList = []
rList = []
for i in range(num_episodes):
    #Reset environment and get first new observation
    s = env.reset()
    rAll = 0
    d = False
    j = 0
    #The Q-Table learning algorithm
    while j < 99:
        j+=1
        #Choose an action by greedily (with noise) picking from Q table
        a = np.argmax(Q[s,:] + np.random.randn(1,env.action_space.n)*(1./(i+1)))
        #Get new state and reward from environment
        s1,r,d,_ = env.step(a)
        #Update Q-Table with new knowledge
        Q[s,a] = Q[s,a] + lr*(r + y*np.max(Q[s1,:]) - Q[s,a])
        rAll += r
        s = s1
        if d == True:
            break
    #jList.append(j)
    rList.append(rAll)
print "Score over time: " +  str(sum(rList)/num_episodes)
print "Final Q-Table Values"
print Q

神經(jīng)網(wǎng)絡(luò)和Q-learning

現(xiàn)在你可能會想,q-table方法效果不錯,但是很難擴展。雖然很容易為一個簡單的游戲建立16*4的表,但是在任何現(xiàn)代游戲或者現(xiàn)實世界環(huán)境中可能的狀態(tài)數(shù)量幾乎都是無限大的。對于大多數(shù)有趣的問題,q-table方法太簡單了。所以我們需要另一種方法能夠描述狀態(tài),并且生成Q值。這就是為什么我們需要神經(jīng)網(wǎng)絡(luò),我們可以將任意數(shù)量的可能狀態(tài)表示為向量,并學(xué)習(xí)將它們映射為Q值。

在FrozenLake例子中,我們將采用單層網(wǎng)絡(luò),該網(wǎng)絡(luò)會將狀態(tài)編碼為獨熱碼(one-hot vector),并且生成一個四維的Q值向量。我們可以使用Tensorflow來選擇網(wǎng)絡(luò)的層數(shù),激活函數(shù)和輸入類型,這都上文中Q表格方法辦不到的。使用神經(jīng)網(wǎng)絡(luò)時,更新的方法和Q表是不同的,我們將使用反向傳播算法更新?lián)p失函數(shù)。

Eq 2. Loss=\sum(Qtarget-Q)^2

如果讀者不熟悉深度學(xué)習(xí)/神經(jīng)網(wǎng)絡(luò),可以從這里開始學(xué)習(xí)。

這里給出基于tensorflow實現(xiàn)的簡單Q網(wǎng)絡(luò):

import gym
import numpy as np
import random
import tensorflow as tf
import matplotlib.pyplot as plt
#Load the environment
env = gym.make('FrozenLake-v0')
#The Q-Network Approach
#Implementing the network itself

tf.reset_default_graph()
These lines establish the feed-forward part of the network used to choose actions
inputs1 = tf.placeholder(shape=[1,16],dtype=tf.float32)
W = tf.Variable(tf.random_uniform([16,4],0,0.01))
Qout = tf.matmul(inputs1,W)
predict = tf.argmax(Qout,1)

#Below we obtain the loss by taking the sum of squares difference between the target and prediction Q values.
nextQ = tf.placeholder(shape=[1,4],dtype=tf.float32)
loss = tf.reduce_sum(tf.square(nextQ - Qout))
trainer = tf.train.GradientDescentOptimizer(learning_rate=0.1)
updateModel = trainer.minimize(loss)

#Training the network
init = tf.initialize_all_variables()

# Set learning parameters
y = .99
e = 0.1
num_episodes = 2000
#create lists to contain total rewards and steps per episode
jList = []
rList = []
with tf.Session() as sess:
    sess.run(init)
    for i in range(num_episodes):
        #Reset environment and get first new observation
        s = env.reset()
        rAll = 0
        d = False
        j = 0
        #The Q-Network
        while j < 99:
            j+=1
            #Choose an action by greedily (with e chance of random action) from the Q-network
            a,allQ = sess.run([predict,Qout],feed_dict={inputs1:np.identity(16)[s:s+1]})
            if np.random.rand(1) < e:
                a[0] = env.action_space.sample()
            #Get new state and reward from environment
            s1,r,d,_ = env.step(a[0])
            #Obtain the Q' values by feeding the new state through our network
            Q1 = sess.run(Qout,feed_dict={inputs1:np.identity(16)[s1:s1+1]})
            #Obtain maxQ' and set our target value for chosen action.
            maxQ1 = np.max(Q1)
            targetQ = allQ
            targetQ[0,a[0]] = r + y*maxQ1
            #Train our network using target and predicted Q values
            _,W1 = sess.run([updateModel,W],feed_dict={inputs1:np.identity(16)[s:s+1],nextQ:targetQ})
            rAll += r
            s = s1
            if d == True:
                #Reduce chance of random action as we train the model.
                e = 1./((i/50) + 10)
                break
        jList.append(j)
        rList.append(rAll)
print "Percent of succesful episodes: " + str(sum(rList)/num_episodes) + "%"

當(dāng)神經(jīng)網(wǎng)絡(luò)學(xué)習(xí)解決FrozenLake問題時,結(jié)果證明它并不像Q-table方法一樣有效。==雖然神經(jīng)網(wǎng)絡(luò)允許更大的靈活性,但是它們以Q-learning的穩(wěn)定性為代價==。我們簡單的Q網(wǎng)絡(luò)還可以有很多的期繳來達(dá)到更好的效果,==一個稱為經(jīng)驗回放(Experience Replay)另一個稱為目標(biāo)網(wǎng)絡(luò)凍結(jié)(Freezing Target Networks)==。這些改進方法和其他的調(diào)整方法是深度增強學(xué)習(xí)能夠起作用的關(guān)鍵,我們回來后續(xù)的章節(jié)中更詳細(xì)的探討有關(guān)理論。

如果你覺得這篇文章對你有幫助,可以關(guān)注原作者,或者打賞作者。

如果你想要繼續(xù)看到我翻譯的文章,也可以專注專欄。第一次翻譯,希望能和大家一起交流。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容