學習筆記TF037:實現強化學習策略網路

強化學習(Reinforcement Learing),機器學習重要分支,解決連續決策問題。強化學習問題三概念,環境狀態(Environment State)、行動(Action)、獎勵(Reward),目標獲得最多累計獎勵。強化學習模型根據環境狀態、行動和獎勵,學習出最佳策略,以最終結果為目標,不能只看某個行動當下帶來的利益,還要看行動未來帶來的價值。

AutoEncoder屬於無監督學習,MLP、CNN、RNN屬於監督學習,強化學習目標變化、不明確,或不存絕對正確標籤。

Google DeepMind結合強化學習和深度學習,提出DQN(Deep Q-Network,深度Q網路)。AlphaGo結合策略網路(Policy Network)、估值網路(Value Network,DQN)、蒙特卡洛搜索樹(Monte Carlo Tree Search)。

無人駕駛是非常複雜、困難強化學習任務。無人駕駛汽車通過攝像頭、雷達、激光測距儀、感測器觀測環境,獲取豐富環境信息,深度強化學習模型CNN、RNN處理、抽象、轉化環境信息,結合強化學習演算法框架預測最應執行動作(加速、減速、轉換方向),實現自動駕駛。每次執行動作,到目的地路程更短,作為每次行動獎勵。最終目標是安全順利到達目的地,得到獎勵最多。

強化學習兩大類,Policy-Based(Policy Gradients)和Value-Based(Q-Learning)。Policy-Based直接預測環境狀態下應採取Action,Value-Based預測環境狀態下所有Action期望價值(Q值),選擇Q值最高Action執行。Value-Based適合少量離散取值Action,Policy-Based適合Aciton種類多或連續取值Action環境。Policy Network、Value Network。

根據環境狀態和採取行動預測後續環境狀態,利用信息訓練強化學習模型,是Model-Based RL。Model-Free RL直接對策略或Action期望價值預測,計算效率高。複雜環境,主要用Model-Free RL,供給更多樣本訓練,彌補沒有Model預測環境狀態問題。

環境中,強化學習模型載體Agent,負責執行模型行動。環境,Agent無法控制,可以觀察。根據觀察結果,模型給出行動,Agent執行。Reward,環境狀態下執行Action獲得,模型爭取目標。Reward延遲獲到Delayed。Action即時獲得Reward,和未來獲得Reward有很大關係。

策略網路,建立神經網路模型,通過觀察環境狀態,直接預測目前最應該執行策略(Policy),執行策略獲得最大期望收益(包括現在、未來Reward)。沒有絕對正確學習目標,樣本feature不再和label對應。特定環境狀態,不知道對應最好Action,只知道當前Action獲得Reward,試驗後獲得未來Reward,強化學習模型通過試驗樣本學習環境狀態下比較好的Action。樣本沒有絕對正確label,只有估算label。策略網路,不只用當前Reward作label,用Discounted Future Reward,所有未來獎勵依次乘以衰減係數y。衰減係數,略小於但接近1,防止沒有損耗積累導致Reward目標發散,代表未來獎勵不確定性估計。

Policy Gradients方法訓練策略網路。模型通過學習Action在Environment獲得反饋,用梯度更新模型參數。訓練過程,模型接觸到好Action及高期價值,和差Action及低期望價值。通過樣本學習,模型逐漸增加選擇好Action概率,降低選擇壞Action概率,完成策略學習。直接學習當前環境應該採取策略,如選擇Actionc概率,或Action具體數值。策略網路是End-to-End(端對端)方法,直接產生最終策略。

Policy-Based比Value-Based,收斂性更好,通常可以保證收斂到局部最優,且不會發散。對高維、連續值Action,訓練、輸出結果都更高效。能學習出帶有隨機性的策略。

Gym輔助策略網路訓練。Gym,OpenAI開源強化學習環境生成工具。OpenAI,Tesla、Space X CEO Elon Musk發起非營利人工智慧研究機構。研究安全、開放人工智慧技術,確保人工智慧技術廣泛、公平普及服務社會。Gym,提供方便強化學習任務環境,強化學習演算法效率、性能比較。Gym提供大量標準化環境,用來公平橫向對比強化學習模型性能。Gym用戶上傳模型效果、訓練日誌到OpenAI Gym Service介面,參與任務排名,比較模型效果,分享演算法思路。

OpenAI Gym,對用戶開發模型方式無限制,和其他機器學習庫完全兼容(TensorFlow、Theano)。可以用Python語言、任何Python Library編寫強化學習模型Agent。如創建簡單經驗規則,使用State-Action一一對應策略表,深度神經網路模型訓練。

Gym,兩個核心概念。Environment,任務、問題。Agent,策略、演算法。Agent將執行Action傳給Environment,Environment接受Action,結果Observation(環境狀態)和Reward返回Agent。Gym提供完整Environment介面,Agent完全由用戶編寫。Gym包含環境,Algorithmic(演算法)、Atari遊戲(Arcade Learning Environment)、Board Games(棋牌類遊戲 Pachi)、Box2D(二維物理引擎)、Classic Control(經典控制)、MuJoCo(高效處理引擎)、Toy Text(文本類型)任務。執行full install安裝全部環境依賴程序。

Gym環境介面,Env類。env=gym.make(Copy-v0)創建任務環境。env.reset()初始化環境,返回初始observation state。evn.step(action)當前狀態執行一步Action,返回observation、reward、done(完成標記)、info(調試信息)。env.render()渲染一幀任務圖像,Agent直接從圖像像素學習信息策略。

Gym CartPole環境,《Neuronlike Adaptive Elements That Can Solve Difficult Learning Control Problem》,經典可用強化學習解決控制問題。CartPole環境有小車,一維無阻力軌道,行動。車上綁連接不太結實桿,左右搖晃。環境信息observation 是有4個值數組,包含小車位置、速度,桿角度、速度。不需要知道數值物理含義。設計策略網路,從數值學習環境信息,制定最佳策略。Action,小車施加正向力、負向力。Action Space,Action離散數值空間。CartPole Action Space,Discrete(2),只有0?1。只要模型學習到採取Action後帶來的影響。Action只是編碼。CartPole任務,儘可能保持桿豎直不傾倒,小車偏離中心超過2.4個單位距離,桿傾角超過15度,任務失敗,自動結束。每堅持一步,reward+1。Reward恆定。模型要考慮到長遠利益,不只是學習當前Reward。

env.reset()方法初始化環境,獲取環境第一個Observation。根據Observation預測應該採取Action,用env.step(action),在環境中執行Action,返回Observation(CartPole 4維抽象特徵)、reward(當前Action即時獎勵)、done(任務是否結束標記,True,reset任務)、info(額外診斷信息)。進入Action-Observation循環,期望任務結束時儘可能高獎勵。Action在CartPole離散數值空間,有限幾種可能。別的任務可能是連續數值空間。環境名稱後帶版本號,環境發生更新或變化,不修改之前環境,創建新版本,Agent性能公平比較。調用env.monitor方法,監控、記錄模型訓練過程。gym.upload,訓練日誌上傳到gym service展示,與他人演算法比較。簡單問題評測標準,需要多少步訓練可以穩定達到理想分數。複雜問題評測標準,獲得分數越高越好。

TensorFlow創建基於策略網路Agent,解決CartPole問題。先安裝OpenAI Gym。pip install gym 。載入Numpy、TensorFlow、gym。gym.make(CartPole-v0)創建CartPole問題環境env。

先測試CartPole環境隨機Action表現,作對比baseline。env.reset()初始化環境,10次隨機試驗,env.render()渲染CartPole問題圖像。np.random.randint(0,2)產生隨機Action。env.step()執行隨機Action,獲取返回observation、reward、done。如done標記為True,一次試驗結束,傾角超過15度或偏離中心過遠,任務失敗。展示試驗累計獎勵reward_sum,重啟環境。

隨機策略獎勵總值在10~40,均值在20~30。任務完成目標設定200 Reward,通過盡量少次數試驗完成。

策略網路用簡帶一個隱含層MLP。設置網路超參數,隱含節點數H設50,bactch_size設25,學習速率learning_rate 0.1,環境信息observation維度D 4,gamma Reward discount比例0.99。估算Action期望價值(估算樣本學習目標),考慮Delayed Reward,Action之後獲得所有Reward做discount累加,讓模型學習未來可能出現的潛在Reward。discount比例小於1,防止Reward無損耗累加導致發散,可以區分當前Reward和未來Reward價值,Action直接帶來的Reward不需要discount,未來Reward存在不確定性需要discount。

定義策略網路結構,網路接受observation 輸入信息,輸出概率值,用以選擇Action,向左施加力,向右施加力。創建輸入信息observation placeholder,維度D。tf.contrib.layers.xavier_initializer初始化演算法創建隱含層權重W1,維度[D,H]。tf.matmul,環境信息observation乘W1,用ReLU激活函數處理得到隱含層輸出layer1,不加偏置。xavier_initializer演算法創建最後Sigmoid輸出層權重W2,隱含層輸出layer1乘W2,Sigmoid激活函數處理得到最後輸出概率。

模型優化器用Adam演算法。設置兩層神經網路參數梯度placeholder,W1Grad、W2Grad。adam.apply_gradients定義更新模型參數操作updateGrads。計算參數梯度,積累一定樣本量梯度,傳入W1Grad和W2Grad,執行updateGrads更新模型參數。深度強化學習訓練用batch training。不逐個樣本更新參數,累計一個batch_size樣本梯度再更新參數,防止單一樣本隨機擾動雜訊對模型帶來不良影響。

定義函數discount_rewards,估算每個Action對就潛在價值discount_r。CartPole問題每次獲得Reward和前面Action有關,屬於delayed reward。需要比較精準衡量每個Action實際帶來價值,不能只看當前這步Reward,要考慮後面Delayed Reward。讓Pole長時間保持在空中豎直Action,應該有較大期望價值。最終導致Pole傾例Action,有較小期望價值。越靠後Acion期望價值越小,越靠前Acion期望價值越大。倒推過程,最後Action開始計算所有Action應該對應期望價值。輸入數據r ,每個Action實際獲得Reward,CartPole,最後結束時Action 0,其餘 1。定義每個Action除直接獲得Reward外,潛在價值running_add。running_add,從後向前累計,經過discount衰減。每個Action潛在坐,後一Action潛在價值乘以衰減係數gamma,加直接獲得reward,running_add*gamma+r[t]。從最後Action,向前累計計算,得到全部Action潛在價值。

定義人工設置虛擬label placeholder input_y。每個Action潛在價值placeholder advangtages。loglik,Action取值 1概率probability(策略網路輸出概率),Action取值 0概率 1-probability。label取值,label=1-Action。Action 1,label 0,loglik=tf.log(probability),Action取值為1的概率對數。Action 0,label 1,loglik=tf.log(1-probability),Action取值為0的概率對數。loglik,當前Action對應概率對數。loglik與潛在坐advantages相乘,取負數作損失,優化目標。優化器優化,能獲得較多advantages Action概率變大,能獲得較少advantages Action概率變小,損失變小。不斷訓練,持續加大能獲得較多advantages Action概率,學習到一個能獲得更多潛在價值策略。tf.trainable_variables()獲取策略網路全部可訓練參數tvars,tf.gradients求解模型參數 loss梯度。

定義參數,xs環境信息observation列表,ys label列表,drs記錄每個Action Reward,reward_sum累計Reward,總試驗次數total_episodes10000。達到200 Reward停止訓練。

創建默認Session,初始化全部參數,一開始render標誌關閉。render較大延遲,一開始不太成熟模型沒必要觀察。初始化CartPole環境,獲得初始狀態。sess.run執行tvars獲取所有模型參數,創建儲存參數梯度緩衝器gradBuffer,gardBuffer全部初始化零。每次試驗收集參數梯度存儲到gradBuffer,直到完成一個batch_size試驗,匯總梯度更新模型參數。

試驗循環,最大循環次數total_episodes。batch 平均Reward達到100以上,Agent表現良好,調用env.render()展示試驗環境。tf.reshape將observation變形策略網路輸入格式,傳入網路,sess.run執行probability獲得網路輸出概率tfprob,Action取值1的概率。(0,1)間隨機抽樣,隨機值小於tfprob,令Action取1,否則取0,Action取值 1概率為tfprob。

輸入環境信息添加到列表xs,製造虛擬label——y,取值與Action相反,y=1-Action,添加到列表ys。env.step執行一次Action,獲取observation、reward、done、info,reward 累加到reward_sum,reward添加到列表drs。

done為True,一次試驗結束,episode_number加1。np.vstack 將列表xs、ys、drs元素縱向堆疊,得到epx、epy、epr,將xs、ys、drs清空,下次試驗用。epx、epy、epr,一次試驗中獲得的所有observation、label、reward列表。discount_rewards函數計算每步Action潛在價值,標準化(減去均值再除以標準差),得零均值標準差1分布。dicount_reward參與模型損失計算。

epx、epy、discounted_epr輸入神經網路,newGrads求解梯度。獲得梯度累加gradBuffer。

試驗次數達到batch_size整倍數,gradBuffer累計足夠梯度,用updateGrads將gradBuffer中梯度更新到策略網路模型參數,清空gradBuffer,計算下一batch梯度準備。一個batch梯度更新參數,每個梯度是使用一次試驗全部樣本(一個Action一個樣本)計算,一個batch樣本數 25(batch_size)次試驗樣本數和。展示當前試驗次數episode_number,batch內每次試驗平均reward。batch內每次試驗平均reward大於200,策略網路完成任務終止循環。如沒達目標,清空reward_sum,重新累計下一batch總reward。每次試驗結束,任務環境env重置。

模型訓練日誌,策略網路200次試驗,8個batch訓練和參數更新,實現目標,batch內平均230 reward。可以嘗試修改策略網路結構、隱含節點數、batch_size、學習速率參數優化訓練,加快學習速度。

import numpy as np

import tensorflow as tf

import gym

env = gym.make(CartPole-v0)

env.reset()

random_episodes = 0

reward_sum = 0

while random_episodes < 10:

env.render()

observation, reward, done, _ = env.step(np.random.randint(0,2))

reward_sum += reward

if done:

random_episodes += 1

print("Reward for this episode was:",reward_sum)

reward_sum = 0

env.reset()

# hyperparameters

H = 50 # number of hidden layer neurons

batch_size = 25 # every how many episodes to do a param update?

learning_rate = 1e-1 # feel free to play with this to train faster or more stably.

gamma = 0.99 # discount factor for reward

D = 4 # input dimensionality

tf.reset_default_graph()

#This defines the network as it goes from taking an observation of the environment to

#giving a probability of chosing to the action of moving left or right.

observations = tf.placeholder(tf.float32, [None,D] , name="input_x")

W1 = tf.get_variable("W1", shape=[D, H],

initializer=tf.contrib.layers.xavier_initializer())

layer1 = tf.nn.relu(tf.matmul(observations,W1))

W2 = tf.get_variable("W2", shape=[H, 1],

initializer=tf.contrib.layers.xavier_initializer())

score = tf.matmul(layer1,W2)

probability = tf.nn.sigmoid(score)

#From here we define the parts of the network needed for learning a good policy.

tvars = tf.trainable_variables()

input_y = tf.placeholder(tf.float32,[None,1], name="input_y")

advantages = tf.placeholder(tf.float32,name="reward_signal")

# The loss function. This sends the weights in the direction of making actions

# that gave good advantage (reward over time) more likely, and actions that didnt less likely.

loglik = tf.log(input_y*(input_y - probability) + (1 - input_y)*(input_y + probability))

loss = -tf.reduce_mean(loglik * advantages)

newGrads = tf.gradients(loss,tvars)

# Once we have collected a series of gradients from multiple episodes, we apply them.

# We dont just apply gradeients after every episode in order to account for noise in the reward signal.

adam = tf.train.AdamOptimizer(learning_rate=learning_rate) # Our optimizer

W1Grad = tf.placeholder(tf.float32,name="batch_grad1") # Placeholders to send the final gradients through when we update.

W2Grad = tf.placeholder(tf.float32,name="batch_grad2")

batchGrad = [W1Grad,W2Grad]

updateGrads = adam.apply_gradients(zip(batchGrad,tvars))

def discount_rewards(r):

""" take 1D float array of rewards and compute discounted reward """

discounted_r = np.zeros_like(r)

running_add = 0

for t in reversed(range(r.size)):

running_add = running_add * gamma + r[t]

discounted_r[t] = running_add

return discounted_r

xs,ys,drs = [],[],[]

#running_reward = None

reward_sum = 0

episode_number = 1

total_episodes = 10000

init = tf.global_variables_initializer()

# Launch the graph

with tf.Session() as sess:

rendering = False

sess.run(init)

observation = env.reset() # Obtain an initial observation of the environment

# Reset the gradient placeholder. We will collect gradients in

# gradBuffer until we are ready to update our policy network.

gradBuffer = sess.run(tvars)

for ix,grad in enumerate(gradBuffer):

gradBuffer[ix] = grad * 0

while episode_number <= total_episodes:

# Rendering the environment slows things down,

# so lets only look at it once our agent is doing a good job.

if reward_sum/batch_size > 100 or rendering == True :

env.render()

rendering = True

# Make sure the observation is in a shape the network can handle.

x = np.reshape(observation,[1,D])

# Run the policy network and get an action to take.

tfprob = sess.run(probability,feed_dict={observations: x})

action = 1 if np.random.uniform() < tfprob else 0

xs.append(x) # observation

y = 1 if action == 0 else 0 # a "fake label"

ys.append(y)

# step the environment and get new measurements

observation, reward, done, info = env.step(action)

reward_sum += reward

drs.append(reward) # record reward (has to be done after we call step() to get reward for previous action)

if done:

episode_number += 1

# stack together all inputs, hidden states, action gradients, and rewards for this episode

epx = np.vstack(xs)

epy = np.vstack(ys)

epr = np.vstack(drs)

xs,ys,drs = [],[],[] # reset array memory

# compute the discounted reward backwards through time

discounted_epr = discount_rewards(epr)

# size the rewards to be unit normal (helps control the gradient estimator variance)

discounted_epr -= np.mean(discounted_epr)

discounted_epr /= np.std(discounted_epr)

# Get the gradient for this episode, and save it in the gradBuffer

tGrad = sess.run(newGrads,feed_dict={observations: epx, input_y: epy, advantages: discounted_epr})

for ix,grad in enumerate(tGrad):

gradBuffer[ix] += grad

# If we have completed enough episodes, then update the policy network with our gradients.

if episode_number % batch_size == 0:

sess.run(updateGrads,feed_dict={W1Grad: gradBuffer[0],W2Grad:gradBuffer[1]})

for ix,grad in enumerate(gradBuffer):

gradBuffer[ix] = grad * 0

# Give a summary of how well our network is doing for each batch of episodes.

#running_reward = reward_sum if running_reward is None else running_reward * 0.99 + reward_sum * 0.01

print(Average reward for episode %d : %f. % (episode_number,reward_sum/batch_size))

if reward_sum/batch_size > 200:

print("Task solved in",episode_number,episodes!)

break

reward_sum = 0

observation = env.reset()

參考資料:

《TensorFlow實戰》

歡迎付費諮詢(150元每小時),我的微信:qingxingfengzi


推薦閱讀:

用Tensorflow自動化構建海洋生物系統,利用上萬的圖片訓練,找到瀕臨物種「海牛」是什麼原理?
如何看待Theano宣布終止開發 ?
tensorflow的自動求導具體是在哪部分代碼里實現的?

TAG:TensorFlow | 机器学习 | 深度学习DeepLearning |