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

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

AutoEncoder屬于無監(jiān)督學習,MLP、CNN、RNN屬于監(jiān)督學習,強化學習目標變化、不明確,或不存絕對正確標簽。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

TensorFlow創(chuàng)建基于策略網絡Agent,解決CartPole問題。先安裝OpenAI Gym。pip install gym 。載入Numpy、TensorFlow、gym。gym.make('CartPole-v0')創(chuàng)建CartPole問題環(huán)境env。

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

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

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

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

模型優(yōu)化器用Adam算法。設置兩層神經網絡參數梯度placeholder,W1Grad、W2Grad。adam.apply_gradients定義更新模型參數操作updateGrads。計算參數梯度,積累一定樣本量梯度,傳入W1Grad和W2Grad,執(zhí)行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相乘,取負數作損失,優(yōu)化目標。優(yōu)化器優(yōu)化,能獲得較多advantages Action概率變大,能獲得較少advantages Action概率變小,損失變小。不斷訓練,持續(xù)加大能獲得較多advantages Action概率,學習到一個能獲得更多潛在價值策略。tf.trainable_variables()獲取策略網絡全部可訓練參數tvars,tf.gradients求解模型參數 loss梯度。

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

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

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

輸入環(huán)境信息添加到列表xs,制造虛擬label——y,取值與Action相反,y=1-Action,添加到列表ys。env.step執(zhí)行一次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,策略網絡完成任務終止循環(huán)。如沒達目標,清空reward_sum,重新累計下一batch總reward。每次試驗結束,任務環(huán)境env重置。

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

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 didn't 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 don't 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 let's 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實戰(zhàn)》

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

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

推薦閱讀更多精彩內容