基于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(表格算法)
在本篇教程中,我們將要試著去解決來自于OpenAI gym的FrozenLake問題。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ù)看到我翻譯的文章,也可以專注專欄。第一次翻譯,希望能和大家一起交流。