基於tensorflow的最簡單的強化學習入門-part0:Q-learning和神經網路

基於tensorflow的最簡單的強化學習入門-part0:Q學習和神經網路

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

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

我們將從實現一個簡單的查找表演算法開始,然後展示如何使用tensorflow實現神經網路演算法。考慮到上述安排,我們從基礎開始,所以這篇教程作為整個系列的part-0。希望通過這個系列的教程,我們在理解Q-learning之後,能夠結合policy gradient和Q-learning方法構建更好的增強學習網路。(如果你對策略網路更感興趣或者你已經有一些Q-learning的經驗,那麼你可以從這裡開始閱讀)

策略梯度演算法(policy gradient)試著學習某個函數,該函數可以直接把狀態(state)映射為動作(action)的概率分布。Q-learning和策略梯度演算法不一樣,它試著學習在每個狀態下對應的值,並且依賴該狀態執行某一個動作。雖然兩種方法最終都允許我們給定情況下採取特定的行動,但是實現該目的的方法是不相同的。你也許已經聽說深度Q-learning可以玩atari遊戲,我們將要在這裡討論和實現這些更複雜和強大的Q-learning演算法。

譯者註:如果要深入了解基於策略梯度的增強學習演算法,可以參考Andrej Karpathy的文章,Deep Reinforcement Learning: Pong from Pixels

Tabular Approaches for Tabular Environment(表格演算法)

在本篇教程中,我們將要試著去解決來自於OpenAI gym的FrozenLake問題。OpenAI gym提供了一種簡單的環境,讓研究者在一些簡單的遊戲中試驗他們的方法。比如FrozenLake,該遊戲包括一個4*4的網路格子,每個格子可以是起始塊,目標塊、凍結塊或者危險塊。我們的目標是讓agent學習從開始塊如何行動到目標塊上,而不是移動到危險塊上。agent可以選擇向上、向下、向左或者向右移動,同時遊戲中還有可能吹來一陣風,將agent吹到任意的方塊上。在這種情況下,每個時刻都有完美的策略是不能的,但是如何避免危險洞並且到達目標洞肯定是可行的。

增強學習需要我們定義獎勵函數(reward function),那麼定義每一步的獎勵是0,如果進入目標快則獎勵為1。因此我們需要一種演算法能夠學習到長期的期望獎勵,而本教程要講的Q-learning提供了這種機制。

Q-learning最簡單的實現方式是一個基於所有可能的狀態和執行動作的查找表。在表中的每個單元格中,我們學習到在給定狀態下執行特定動作的是否有效的值。在FrozenLake遊戲中,我們有16種可能的狀態和4種可能的動作,給出了16*4的Q值表。我們一開始初始化表格中的所有值為0,然後根據我們觀察到的各種動作獲得的獎勵,相應地更新表格。

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

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

這個公式說明,給定動作a和狀態s的q值,等於當前的獎勵r加上未來預期的q值。lambda可以看作未來期望Q值和當前獎勵相比的權重。以這種方式更新,Q表就會慢慢的收斂到在給定狀態下和動作下的期望收益。下面一段python代碼就是基於FrozenLake遊戲的Q-table的演算法實現。

import gymimport numpy as np# Load the environmentenv = gym.make("FrozenLake-v0")#Implement Q-Table learning algorithm#Initialize table with all zerosQ = np.zeros([env.observation_space.n,env.action_space.n])# Set learning parameterslr = .85y = .99num_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

神經網路和Q-learning

現在你可能會想,q-table方法效果不錯,但是很難擴展。雖然很容易為一個簡單的遊戲建立16*4的表,但是在任何現代遊戲或者現實世界環境中可能的狀態數量幾乎都是無限大的。對於大多數有趣的問題,q-table方法太簡單了。所以我們需要另一種方法能夠描述狀態,並且生成Q值。這就是為什麼我們需要神經網路,我們可以將任意數量的可能狀態表示為向量,並學習將它們映射為Q值。

在FrozenLake例子中,我們將採用單層網路,該網路會將狀態編碼為獨熱碼(one-hot vector),並且生成一個四維的Q值向量。我們可以使用Tensorflow來選擇網路的層數,激活函數和輸入類型,這都上文中Q表格方法辦不到的。使用神經網路時,更新的方法和Q表是不同的,我們將使用反向傳播演算法更新損失函數。

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

如果讀者不熟悉深度學習/神經網路,可以從這裡開始學習。

這裡給出基於tensorflow實現的簡單Q網路:

import gymimport numpy as npimport randomimport tensorflow as tfimport matplotlib.pyplot as plt#Load the environmentenv = gym.make("FrozenLake-v0")#The Q-Network Approach#Implementing the network itselftf.reset_default_graph()These lines establish the feed-forward part of the network used to choose actionsinputs1 = 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 networkinit = tf.initialize_all_variables()# Set learning parametersy = .99e = 0.1num_episodes = 2000#create lists to contain total rewards and steps per episodejList = []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) + "%"

當神經網路學習解決FrozenLake問題時,結果證明它並不像Q-table方法一樣有效。雖然神經網路允許更大的靈活性,但是它們以Q-learning的穩定性為代價。我們簡單的Q網路還可以有很多的期繳來達到更好的效果,一個稱為經驗回放(Experience Replay)另一個稱為目標網路凍結(Freezing Target Networks)。這些改進方法和其他的調整方法是深度增強學習能夠起作用的關鍵,我們回來後續的章節中更詳細的探討有關理論。

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

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


推薦閱讀:

阿爾法狗走出電腦,它們現在控制著機器人,自己學會了開門!
Dimensionality Reduction——LDA線性判別分析實現篇
Facebook 能主動監測出自殺傾向的用戶,並及時提供援助
令人拍案叫絕的Wasserstein GAN
人工智慧&家裝行業:可以賦能設計師的AI才是好AI

TAG:深度学习DeepLearning | 强化学习ReinforcementLearning | 人工智能 |