自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Keras+OpenAI強(qiáng)化學(xué)習(xí)實(shí)踐:行為-評判模型

開發(fā) 開發(fā)工具
本文先給出行為-評判模型(actor-critic model)的基本原理,包括鏈?zhǔn)角髮?dǎo)法則等,隨后再從模型的參數(shù)、模型的訓(xùn)練和模型的測試等方面用代碼段解釋行為-評判模型,最后,文章給出了該教程的全部代碼。

像之前的教程一樣,我們首先快速了解一下已取得的驚人成果:在一個(gè)連續(xù)的輸出空間場景下,從完全不明白「勝利」的含義開始,現(xiàn)在我們可以探索環(huán)境并「完成」試驗(yàn)。

將自身置身于模擬環(huán)境中。這就相當(dāng)于要求你在沒有游戲說明書和特定目標(biāo)的場景下玩一場游戲,且不可中斷,直到你贏得整個(gè)游戲(這有些近乎殘忍)。不僅如此:一系列動作可能產(chǎn)生的結(jié)果狀態(tài)是無窮無盡的(即連續(xù)觀測空間)!然而,DQN 通過調(diào)控并緩慢更新各動作內(nèi)部參數(shù)的值可以快速解決這個(gè)看似不可能的任務(wù)。

更復(fù)雜的環(huán)境

從以前的 MountainCar 環(huán)境向 Pendulum 環(huán)境的升級與 CartPole 到 MountainCar 的升級極其相似:我們正在從一個(gè)離散的環(huán)境擴(kuò)展到連續(xù)的環(huán)境。Pendulum 環(huán)境具有無限的輸入空間,這意味著你在任何給定時(shí)間可以進(jìn)行不限次數(shù)的動作。為何 DQN 不再適用此類環(huán)境了?DQN 的實(shí)現(xiàn)不是完全獨(dú)立于環(huán)境動作的結(jié)構(gòu)嗎?

不同于 MountainCar-v0,Pendulum-v0 通過給我們提供了無窮大的輸入空間而構(gòu)成了更大的挑戰(zhàn)。

雖然它與動作無關(guān),但 DQN 的基本原理是擁有有限的輸出空間。畢竟,我們要考慮該如何構(gòu)建代碼:預(yù)測會在每個(gè)時(shí)間步長(給定當(dāng)前環(huán)境狀態(tài))下為每個(gè)可能的動作分配一個(gè)分?jǐn)?shù),并簡單地采用得分最高的動作。我們之前已經(jīng)簡化了強(qiáng)化學(xué)習(xí)的問題,以便高效地為每個(gè)動作分配分?jǐn)?shù)。但是,如果我們輸入空間無限大,這還有可能嗎?我們需要一個(gè)無限大的表格來記錄所有的 Q 值!

無限大的表格來記錄所有的 Q 值

無限大的數(shù)據(jù)表聽起來很不靠譜!

我們該如何著手解決這個(gè)看似不可能的任務(wù)呢?畢竟,我們現(xiàn)在要做比以前更加瘋狂的事:不僅僅只是贏下一場沒有攻略的游戲,現(xiàn)在我們還要應(yīng)對一個(gè)被無數(shù)條指令控制的游戲!讓我們來看看為什么 DQN 只接收有限數(shù)量的動作輸入。

我們從模型的搭建方式來分析。我們必須能夠在每個(gè)時(shí)間步迭代更新特定的動作位置的改變方式。這正是為什么我們讓模型預(yù)測 Q 值,而不是直接預(yù)測下一步的動作。如果選擇了后者,我們不知道如何更新模型以更好地預(yù)測,以及從對未來的預(yù)測中獲利。

因此,本質(zhì)問題源于一個(gè)事實(shí)——類似于模型已經(jīng)輸出與所有可能發(fā)生的行動相關(guān)的獎(jiǎng)勵(lì)的列表運(yùn)算結(jié)果。如果我們把這個(gè)模型拆解開會怎樣?如果我們有兩個(gè)獨(dú)立的模型:一個(gè)輸出期望的動作(在連續(xù)空間中),另一個(gè)以它的輸出作為輸入,以產(chǎn)生 DQN 的 Q 值?這貌似解決了我們的問題,而且這正是行為-評判模型(actor-critic model)的基本原理!

行為-評判模型原理

行為-評判模型原理

不同于 DQN 算法,行為-評判模型(如名字所示)有兩個(gè)獨(dú)立的網(wǎng)絡(luò):一個(gè)基于當(dāng)前的環(huán)境狀態(tài)預(yù)測出即將被采用的動作,另一個(gè)用于計(jì)算狀態(tài)和動作下的價(jià)值。

正如上節(jié)所述,整個(gè)行為—評判(AC)方法可行的前提是有兩個(gè)交互模型。多個(gè)神經(jīng)網(wǎng)絡(luò)之間相互關(guān)聯(lián)的主題在強(qiáng)化學(xué)習(xí)和監(jiān)督學(xué)習(xí)(即 GAN、AC、A3C、DDQN(升級版 DQN)等)中越發(fā)凸顯。初次了解這些架構(gòu)可能有些困難,但這絕對值得去做:你將能夠理解和編程實(shí)現(xiàn)一些現(xiàn)代領(lǐng)域研究前沿的算法!

回到主題,AC 模型有兩個(gè)恰如其分的名字:行為和評判。前者接受當(dāng)前的環(huán)境狀態(tài),并決定從哪個(gè)狀態(tài)獲得最佳動作。它以非常類似于人類自身的行為方式來實(shí)現(xiàn) DQN 算法。評判模塊通過從 DQN 中接受環(huán)境狀態(tài)和動作并返回一個(gè)表征動作狀態(tài)的分?jǐn)?shù)來完成評判功能。

把這想象成是一個(gè)孩子(「行為模塊」)與其父母(「評判模塊」)的游樂場。孩子正在環(huán)顧四周,探索周邊環(huán)境中的所有可能選擇,例如滑動幻燈片,蕩秋千,在草地上玩耍。父母會照看孩子并基于其所為,對孩子給出批評或補(bǔ)充。父母的決定依賴于環(huán)境的事實(shí)無可否認(rèn):畢竟,如果孩子試圖在真實(shí)的秋千上玩耍,相比于試圖在幻燈片上這樣做,孩子更值得表揚(yáng)!

簡介:鏈?zhǔn)椒▌t(可選)

你需要理解的主要理論在很大程度上支撐著現(xiàn)代機(jī)器學(xué)習(xí):鏈?zhǔn)椒▌t。毫不夸張的說鏈?zhǔn)椒▌t可能是掌握理解實(shí)用機(jī)器學(xué)習(xí)的最關(guān)鍵的(即使有些簡單)的想法之一。事實(shí)上,如果只是直觀地了解鏈?zhǔn)椒▌t的概念,你并不需要很深厚的數(shù)學(xué)背景。我會非??焖俚刂v解鏈?zhǔn)椒▌t,但如果你已了解,請隨意跳到下一部分,下一部分我們將看到開發(fā) AC 模型的實(shí)際概述,以及鏈條法則如何適用于該規(guī)劃。

一個(gè)看似可能來自你第一節(jié)微積分課堂上的簡單概念,構(gòu)成了實(shí)用機(jī)器學(xué)習(xí)的現(xiàn)代基礎(chǔ),因?yàn)樗诜聪蛲扑愫皖愃扑惴ㄖ杏兄钊穗y以置信的加速運(yùn)算效果。

這個(gè)等式看起來非常直觀:畢竟只是「重寫了分子/分母」。這個(gè)「直觀的解釋」有一個(gè)主要問題:等式中的推導(dǎo)完全是倒退的!關(guān)鍵是要記住,數(shù)學(xué)中引入直觀的符號是為了幫助我們理解概念。因此,由于鏈?zhǔn)椒▌t的計(jì)算方式非常類似于簡化分?jǐn)?shù)的運(yùn)算過程,人們才引入這種「分?jǐn)?shù)」符號。那么試圖通過符號來解釋概念的人正在跳過關(guān)鍵的一步:為什么這些符號可以通用?如同這里,為什么要像這樣進(jìn)行求導(dǎo)?

鏈條規(guī)則

可以借助經(jīng)典的彈簧實(shí)例可視化運(yùn)動中的鏈條規(guī)則。

基本概念實(shí)際上并不比這個(gè)符號更難理解。想象一下,我們把一捆繩子一根根地系在一起,類似于把一堆彈簧串聯(lián)起來。假設(shè)你固定了這個(gè)彈簧系統(tǒng)的一端,你的目標(biāo)是以 10 英尺/秒的速度搖晃另一端,那么你可以用這個(gè)速度搖動你的末端,并把它傳播到另一端?;蛘吣憧梢赃B接一些中間系統(tǒng),以較低的速率搖動中間連接,例如,5 英尺/秒。也就是說,在 5 英尺/秒的情況下,你只需要以 2 英尺/秒的速度搖動末端,因?yàn)槟銖拈_始到終點(diǎn)做的任何運(yùn)動都會被傳遞到終點(diǎn)位置。這是因?yàn)槲锢磉B接迫使一端的運(yùn)動被傳遞到末端。注意:和其它類比一樣,這里有一些不當(dāng)之處,但這主要是為了可視化。

類似地,如果我們有兩個(gè)系統(tǒng),其中一個(gè)系統(tǒng)的輸出是另一個(gè)系統(tǒng)的輸入,微調(diào)「反饋網(wǎng)絡(luò)」的參數(shù)將會影響其輸出,該輸出會被傳播下去并乘以任何進(jìn)一步的變化值并貫穿整個(gè)網(wǎng)絡(luò)。

AC 模型概述

因此,我們必須制定一個(gè) ActorCritic 類,它包含一些之前實(shí)現(xiàn)過的 DQN,但是其訓(xùn)練過程更復(fù)雜。因?yàn)槲覀冃枰恍└呒壍墓δ?,我們必須使用包含了基礎(chǔ)庫 Keras 的開源框架:Tensorflow。注意:你也可以在 Theano 中實(shí)現(xiàn)這一點(diǎn),但是我以前沒有使用過它,所以沒有包含其代碼。如果你選擇這么做,請隨時(shí)向 Theano 提交此代碼的擴(kuò)展。

模型實(shí)現(xiàn)包含四個(gè)主要部分,其直接并行如何實(shí)現(xiàn) DQN 代理:

  • 模型參數(shù)/配置
  • 訓(xùn)練代碼
  • 預(yù)測代碼

1. AC 參數(shù)

第一步,導(dǎo)入需要的庫

  1. import gym 
  2. import numpy as np  
  3. from keras.models import Sequential, Model 
  4. from keras.layers import Dense, Dropout, Input 
  5. from keras.layers.merge import Add, Multiply 
  6. from keras.optimizers import Adam 
  7. import keras.backend as K 
  8. import tensorflow as tf 
  9. import random 
  10. from collections import deque 

參數(shù)與 DQN 中的參數(shù)非常類似。畢竟,這個(gè)行為-評判模型除了兩個(gè)獨(dú)立的模塊之外,還要做與 DQN 相同的任務(wù)。我們還繼續(xù)使用我們在 DQN 報(bào)告中討論的「目標(biāo)網(wǎng)絡(luò)攻擊」,以確保網(wǎng)絡(luò)成功收斂。唯一的新參數(shù)是「tau」,并且涉及在這種情況下如何進(jìn)行目標(biāo)網(wǎng)絡(luò)學(xué)習(xí)的細(xì)微變化:

  1. class ActorCritic: 
  2.     def __init__(self, env, sess): 
  3.         self.env  = env 
  4.         self.sess = sess 
  5.         self.learning_rate = 0.001 
  6.         self.epsilon = 1.0 
  7.         self.epsilon_decay = .995 
  8.         self.gamma = .95 
  9.         self.tau   = .125 
  10.         self.memory = deque(maxlen=2000

在以下的訓(xùn)練部分中,詳細(xì)解釋了 tau 參數(shù)的準(zhǔn)確用法,它的作用其實(shí)就是推動預(yù)測模型向目標(biāo)模型逐步轉(zhuǎn)換。現(xiàn)在,我們找到了主要的關(guān)注點(diǎn):定義模型。正如我們所描述的,我們有兩個(gè)獨(dú)立的模型,每個(gè)模型都與它自己的目標(biāo)網(wǎng)絡(luò)相關(guān)聯(lián)。

我們從定義行為模型開始。行為模型的目的是根據(jù)當(dāng)前環(huán)境狀態(tài),得出應(yīng)當(dāng)采取的最佳動作。再次,這個(gè)模型需要處理我們提供的數(shù)字?jǐn)?shù)據(jù),這意味著沒有空間也沒有必要在網(wǎng)絡(luò)中添加任何比我們迄今為止使用的密集/完全連接層更復(fù)雜的層。因此,行為模型只是一系列全連接層,將環(huán)境觀察的狀態(tài)映射到環(huán)境空間上的一個(gè)點(diǎn):

  1. def create_actor_model(self): 
  2.         state_input = Input(shape=self.env.observation_space.shape) 
  3.         h1 = Dense(24, activation='relu')(state_input) 
  4.         h2 = Dense(48, activation='relu')(h1) 
  5.         h3 = Dense(24, activation='relu')(h2) 
  6.         output = Dense(self.env.action_space.shape[0],   
  7.             activation='relu')(h3) 
  8.          
  9.         model = Model(input=state_inputoutputoutput=output) 
  10.         adam  = Adam(lr=0.001) 
  11.         model.compile(loss="mse"optimizer=adam
  12.         return state_input, model 

主要的區(qū)別是我們返回了一個(gè)對輸入層的引用。本節(jié)結(jié)尾對此原因的解釋十分清楚,但簡而言之,這解釋了我們?yōu)槭裁磳π袨槟P偷挠?xùn)練過程采取不同的處理。

行為模型中的棘手部分是決定如何訓(xùn)練它,這就是鏈?zhǔn)椒▌t發(fā)揮作用的地方。但在討論之前,讓我們考慮一下為什么它與標(biāo)準(zhǔn)評論/ DQN 網(wǎng)絡(luò)的訓(xùn)練不同。畢竟,我們不是簡單地去適應(yīng)在 DQN(根據(jù)當(dāng)前狀態(tài)擬合模型)的情況下,基于當(dāng)前的和打折的未來獎(jiǎng)勵(lì)得出接下來采用的最佳動作是哪一個(gè)?問題在于:如果我們能夠按照要求去做,那么這個(gè)問題將會解決。問題在于我們?nèi)绾未_定「最佳動作」是什么,因?yàn)? Q 值現(xiàn)在是在評判網(wǎng)絡(luò)中單獨(dú)計(jì)算出來的。

所以,為了解決這個(gè)問題,我們選擇了一種替代方法。不同于找到「最佳選擇」和擬合,我們實(shí)際上選擇了爬山算法(梯度上升)。對于不熟悉這個(gè)算法的人來說,登山是一個(gè)形象的比喻:從你當(dāng)?shù)氐? POV,找到斜率最大的傾斜方向,并沿著該方向逐步移動。換句話說,爬山正試圖通過原始的沖動并沿著局部斜率最大的方向來達(dá)到全局最大值??梢韵胂笤谀承┣闆r下,該方法大錯(cuò)特錯(cuò),但通常情況下,它具備很好的實(shí)用性。

因此,我們想使用該算法來更新我們的行為模型:我們想確定(行為模型中的)參數(shù)的什么變化會導(dǎo)致 Q 值最大幅度的增加(由評判模型預(yù)測得出)。由于行為模型的輸出是動作,評判模型通過環(huán)境狀態(tài)+動作對來評估,我們在此可以看到鏈?zhǔn)椒▌t如何發(fā)揮作用。我們想看看如何改變行為模型的參數(shù)才會改變最終的 Q 值,使用行為網(wǎng)絡(luò)的輸出作為我們的「中間鏈接」(下面的代碼全部在「__init __(self)」方法中):

  1. self.actor_state_input, self.actor_model = \ 
  2.            self.create_actor_model() 
  3.        _, selfself.target_actor_model = self.create_actor_model() 
  1. self.actor_critic_grad = tf.placeholder(tf.float32,  
  2.             [None, self.env.action_space.shape[0]])  
  3.          
  4.         actor_model_weights = self.actor_model.trainable_weights 
  5.         self.actor_grads = tf.gradients(self.actor_model.output,  
  6.             actor_model_weights, -self.actor_critic_grad) 
  7.         grads = zip(self.actor_grads, actor_model_weights) 
  8.         self.optimize =  tf.train.AdamOptimizer( 
  9.             self.learning_rate).apply_gradients(grads) 

我們看到在這里我們持有模型權(quán)重和輸出(動作)之間的梯度。我們還通過負(fù)的 self.actor_critic_grad(因?yàn)槲覀兿朐谶@種情況下使用梯度上升)來放縮它,梯度由占位符持有。對于那些不熟悉 Tensorflow 或首次接觸的讀者,你只需要知道運(yùn)行 Tensorflow 會話時(shí),占位符將扮演「輸入數(shù)據(jù)」的角色。我不會詳細(xì)介紹它的工作原理,因?yàn)?tensorflow.org 教程的材料相當(dāng)全面。

再來看看評判網(wǎng)絡(luò),基本上我們面臨著相反的問題。即,網(wǎng)絡(luò)定義稍微復(fù)雜一些,但是訓(xùn)練比較簡單。評判網(wǎng)絡(luò)旨在將環(huán)境狀態(tài)和動作作為輸入,并計(jì)算出相應(yīng)的估值。我們通過合并一系列全連接層以及得出最終的 Q 值預(yù)測之前的中間層來實(shí)現(xiàn)這一點(diǎn):

  1. def create_critic_model(self): 
  2.         state_input = Input(shape=self.env.observation_space.shape) 
  3.         state_h1 = Dense(24, activation='relu')(state_input) 
  4.         state_h2 = Dense(48)(state_h1) 
  5.          
  6.         action_input = Input(shape=self.env.action_space.shape) 
  7.         action_h1    = Dense(48)(action_input) 
  8.          
  9.         merged    = Add()([state_h2, action_h1]) 
  10.         merged_h1 = Dense(24, activation='relu')(merged) 
  11.         output = Dense(1, activation='relu')(merged_h1) 
  12.         model  = Model(input=[state_input,action_input],  
  13.             outputoutput=output) 
  14.          
  15.         adam  = Adam(lr=0.001) 
  16.         model.compile(loss="mse"optimizer=adam
  17.         return state_input, action_input, model 

需要注意的是如何處理輸入和返回的不對稱性。對于第一點(diǎn),我們在環(huán)境狀態(tài)輸入中有一個(gè)額外的 FC(全連接)層。我這樣做是因?yàn)檫@是推薦 AC 網(wǎng)絡(luò)使用的結(jié)構(gòu),但它可能與處理兩個(gè)輸入的 FC 層效果差不多(或稍差)。至于后面一點(diǎn)(我們正在返回的值),我們需要保留輸入狀態(tài)和動作的引用,因?yàn)槲覀冃枰褂盟鼈兏滦袨榫W(wǎng)絡(luò):

  1. self.critic_state_input, self.critic_action_input, \ 
  2.             selfself.critic_model = self.create_critic_model() 
  3.         _, _, selfself.target_critic_model = self.create_critic_model() 
  1. self.critic_grads = tf.gradients(self.critic_model.output,  
  2.            self.critic_action_input) 
  3.         
  4.        # Initialize for later gradient calculations 
  5.        self.sess.run(tf.initialize_all_variables()) 

我們在這里設(shè)置要計(jì)算的缺失梯度:關(guān)于動作權(quán)重的輸出 Q。這是訓(xùn)練代碼中直接調(diào)用的,我們現(xiàn)在來深入探討。

2. AC 模型訓(xùn)練

該代碼的最后一個(gè)主要與 DQN 不同的部分是實(shí)際的訓(xùn)練代碼。然而,我們使用了從記憶(LSTM 結(jié)構(gòu))中吸取教訓(xùn)和學(xué)習(xí)的基本結(jié)構(gòu)。由于我們有兩種訓(xùn)練方法,我們將代碼分成不同的訓(xùn)練函數(shù),并將它們稱為:

  1. def train(self): 
  2.         batch_size = 32 
  3.         if len(self.memory) < batch_size: 
  4.             return 
  5.         rewards = [] 
  6.         samples = random.sample(self.memory, batch_size) 
  7.         self._train_critic(samples) 
  8.         self._train_actor(samples) 

現(xiàn)在我們定義兩種訓(xùn)練方法。不過,與 DQN 非常相似:我們只是簡單地找到未來打折的獎(jiǎng)勵(lì)和訓(xùn)練方法。唯一的區(qū)別是,我們正在對狀態(tài)/動作對進(jìn)行訓(xùn)練,并使用 target_critic_model 來預(yù)測未來的獎(jiǎng)勵(lì),而不是僅使用行為來預(yù)測:

  1. def _train_critic(self, samples): 
  2.         for sample in samples: 
  3.             cur_state, action, reward, new_state, done = sample 
  4.             if not done: 
  5.                 target_action =  
  6.                     self.target_actor_model.predict(new_state) 
  7.                 future_reward = self.target_critic_model.predict( 
  8.                     [new_state, target_action])[0][0] 
  9.                 reward += self.gamma * future_reward 
  10.             self.critic_model.fit([cur_state, action],  
  11.                 reward, verbose=0

對于行為模型,我們幸運(yùn)地解決了所有難題!我們已經(jīng)設(shè)置了梯度如何在網(wǎng)絡(luò)中運(yùn)作,現(xiàn)在只需傳入當(dāng)前的動作和狀態(tài)并調(diào)用該函數(shù):

  1. def _train_actor(self, samples): 
  2.         for sample in samples: 
  3.             cur_state, action, reward, new_state, _ = sample 
  4.             predicted_action = self.actor_model.predict(cur_state) 
  5.             grads = self.sess.run(self.critic_grads, feed_dict={ 
  6.                 self.critic_state_input:  cur_state, 
  7.                 self.critic_action_input: predicted_action 
  8.             })[0] 
  1. self.sess.run(self.optimize, feed_dict={ 
  2.                self.actor_state_input: cur_state, 
  3.                self.actor_critic_grad: grads 
  4.            }) 

如上所述,我們利用了目標(biāo)模型。所以我們必須在每個(gè)時(shí)間步更新其權(quán)重。但是,更新過程太慢了。具體說,我們將目標(biāo)模型的估值保持在一個(gè)分?jǐn)?shù) self.tau 上,并將其更新為余數(shù)(1-self.tau)分?jǐn)?shù)的相應(yīng)模型權(quán)重。行為/評判模型均如此處理,但下面只給出行為模型的代碼(你可以在文章底部的完整代碼中看到評判模型代碼):

  1. def _update_actor_target(self): 
  2.         actor_model_weights  = self.actor_model.get_weights() 
  3.         actor_target_weights =self.target_critic_model.get_weights() 
  4.          
  5.         for i in range(len(actor_target_weights)): 
  6.             actor_target_weights[i] = actor_model_weights[i] 
  7.         self.target_critic_model.set_weights(actor_target_weights 

3. AC 模型預(yù)測

這與我們在 DQN 中的做法一樣,所以沒有什么好說的:

  1. def act(self, cur_state): 
  2.   self.epsilon *= self.epsilon_decay 
  3.   if np.random.random() < self.epsilon: 
  4.    return self.env.action_space.sample() 
  5.   return self.actor_model.predict(cur_state) 

4. 預(yù)測代碼

預(yù)測代碼也與之前的強(qiáng)化學(xué)習(xí)算法相同。也就是說,我們只需反復(fù)試驗(yàn),并對代理進(jìn)行預(yù)測、記憶和訓(xùn)練:

  1. def main(): 
  2.     sess = tf.Session() 
  3.     K.set_session(sess) 
  4.     env = gym.make("Pendulum-v0") 
  5.     actor_critic = ActorCritic(env, sess) 
  6.      
  7.     num_trials = 10000 
  8.     trial_len  = 500 
  9.      
  10.     cur_state = env.reset() 
  11.     action = env.action_space.sample() 
  12.     while True: 
  13.         env.render() 
  14.         cur_statecur_state = cur_state.reshape((1,  
  15.             env.observation_space.shape[0])) 
  16.         action = actor_critic.act(cur_state) 
  17.         actionaction = action.reshape((1, env.action_space.shape[0])) 
  18.          
  19.         new_state, reward, done, _ = env.step(action) 
  20.         new_statenew_state = new_state.reshape((1,  
  21.             env.observation_space.shape[0])) 
  22.          
  23.         actor_critic.remember(cur_state, action, reward,  
  24.             new_state, done) 
  25.         actor_critic.train() 
  26.          
  27.         cur_state = new_state 

完整代碼

這是使用 AC(Actor-Critic)對「Pendulum-v0」環(huán)境進(jìn)行訓(xùn)練的完整代碼!

  1. """ 
  2. solving pendulum using actor-critic model 
  3. """ 
  4.  
  5. import gym 
  6. import numpy as np  
  7. from keras.models import Sequential, Model 
  8. from keras.layers import Dense, Dropout, Input 
  9. from keras.layers.merge import Add, Multiply 
  10. from keras.optimizers import Adam 
  11. import keras.backend as K 
  12.  
  13. import tensorflow as tf 
  14.  
  15. import random 
  16. from collections import deque 
  17.  
  18. # determines how to assign values to each state, i.e. takes the state 
  19. # and action (two-input model) and determines the corresponding value 
  20. class ActorCritic: 
  21.     def __init__(self, env, sess): 
  22.         self.env  = env 
  23.         self.sess = sess 
  24.  
  25.         self.learning_rate = 0.001 
  26.         self.epsilon = 1.0 
  27.         self.epsilon_decay = .995 
  28.         self.gamma = .95 
  29.         self.tau   = .125 
  30.  
  31.         # ===================================================================== # 
  32.         #                               Actor Model                             # 
  33.         # Chain rule: find the gradient of chaging the actor network params in  # 
  34.         # getting closest to the final value network predictions, i.e. de/dA    # 
  35.         # Calculate de/dA as = de/dC * dC/dA, where e is error, C critic, A act # 
  36.         # ===================================================================== # 
  37.  
  38.         self.memory = deque(maxlen=2000
  39.         self.actor_state_input, selfself.actor_model = self.create_actor_model() 
  40.         _, selfself.target_actor_model = self.create_actor_model() 
  41.  
  42.         self.actor_critic_grad = tf.placeholder(tf.float32,  
  43.             [None, self.env.action_space.shape[0]]) # where we will feed de/dC (from critic) 
  44.          
  45.         actor_model_weights = self.actor_model.trainable_weights 
  46.         self.actor_grads = tf.gradients(self.actor_model.output,  
  47.             actor_model_weights, -self.actor_critic_grad) # dC/dA (from actor) 
  48.         grads = zip(self.actor_grads, actor_model_weights) 
  49.         self.optimize = tf.train.AdamOptimizer(self.learning_rate).apply_gradients(grads) 
  50.  
  51.         # ===================================================================== # 
  52.         #                              Critic Model                             # 
  53.         # ===================================================================== #        
  54.  
  55.         self.critic_state_input, self.critic_action_input, \ 
  56.             selfself.critic_model = self.create_critic_model() 
  57.         _, _, selfself.target_critic_model = self.create_critic_model() 
  58.  
  59.         self.critic_grads = tf.gradients(self.critic_model.output,  
  60.             self.critic_action_input) # where we calcaulte de/dC for feeding above 
  61.          
  62.         # Initialize for later gradient calculations 
  63.         self.sess.run(tf.initialize_all_variables()) 
  64.  
  65.     # ========================================================================= # 
  66.     #                              Model Definitions                            # 
  67.     # ========================================================================= # 
  68.  
  69.     def create_actor_model(self): 
  70.         state_input = Input(shape=self.env.observation_space.shape) 
  71.         h1 = Dense(24, activation='relu')(state_input) 
  72.         h2 = Dense(48, activation='relu')(h1) 
  73.         h3 = Dense(24, activation='relu')(h2) 
  74.         output = Dense(self.env.action_space.shape[0], activation='relu')(h3) 
  75.          
  76.         model = Model(input=state_inputoutputoutput=output) 
  77.         adam  = Adam(lr=0.001) 
  78.         model.compile(loss="mse"optimizer=adam
  79.         return state_input, model 
  80.  
  81.     def create_critic_model(self): 
  82.         state_input = Input(shape=self.env.observation_space.shape) 
  83.         state_h1 = Dense(24, activation='relu')(state_input) 
  84.         state_h2 = Dense(48)(state_h1) 
  85.          
  86.         action_input = Input(shape=self.env.action_space.shape) 
  87.         action_h1    = Dense(48)(action_input) 
  88.          
  89.         merged    = Add()([state_h2, action_h1]) 
  90.         merged_h1 = Dense(24, activation='relu')(merged) 
  91.         output = Dense(1, activation='relu')(merged_h1) 
  92.         model  = Model(input=[state_input,action_input], outputoutput=output) 
  93.          
  94.         adam  = Adam(lr=0.001) 
  95.         model.compile(loss="mse"optimizer=adam
  96.         return state_input, action_input, model 
  97.  
  98.     # ========================================================================= # 
  99.     #                               Model Training                              # 
  100.     # ========================================================================= # 
  101.  
  102.     def remember(self, cur_state, action, reward, new_state, done): 
  103.         self.memory.append([cur_state, action, reward, new_state, done]) 
  104.  
  105.     def _train_actor(self, samples): 
  106.         for sample in samples: 
  107.             cur_state, action, reward, new_state, _ = sample 
  108.             predicted_action = self.actor_model.predict(cur_state) 
  109.             grads = self.sess.run(self.critic_grads, feed_dict={ 
  110.                 self.critic_state_input:  cur_state, 
  111.                 self.critic_action_input: predicted_action 
  112.             })[0] 
  113.  
  114.             self.sess.run(self.optimize, feed_dict={ 
  115.                 self.actor_state_input: cur_state, 
  116.                 self.actor_critic_grad: grads 
  117.             }) 
  118.              
  119.     def _train_critic(self, samples): 
  120.         for sample in samples: 
  121.             cur_state, action, reward, new_state, done = sample 
  122.             if not done: 
  123.                 target_action = self.target_actor_model.predict(new_state) 
  124.                 future_reward = self.target_critic_model.predict( 
  125.                     [new_state, target_action])[0][0] 
  126.                 reward += self.gamma * future_reward 
  127.             self.critic_model.fit([cur_state, action], reward, verbose=0
  128.          
  129.     def train(self): 
  130.         batch_size = 32 
  131.         if len(self.memory) < batch_size: 
  132.             return 
  133.  
  134.         rewards = [] 
  135.         samples = random.sample(self.memory, batch_size) 
  136.         self._train_critic(samples) 
  137.         self._train_actor(samples) 
  138.  
  139.     # ========================================================================= # 
  140.     #                         Target Model Updating                             # 
  141.     # ========================================================================= # 
  142.  
  143.     def _update_actor_target(self): 
  144.         actor_model_weights  = self.actor_model.get_weights() 
  145.         actor_target_weights = self.target_critic_model.get_weights() 
  146.          
  147.         for i in range(len(actor_target_weights)): 
  148.             actor_target_weights[i] = actor_model_weights[i] 
  149.         self.target_critic_model.set_weights(actor_target_weights) 
  150.  
  151.     def _update_critic_target(self): 
  152.         critic_model_weights  = self.critic_model.get_weights() 
  153.         critic_target_weights = self.critic_target_model.get_weights() 
  154.          
  155.         for i in range(len(critic_target_weights)): 
  156.             critic_target_weights[i] = critic_model_weights[i] 
  157.         self.critic_target_model.set_weights(critic_target_weights)      
  158.  
  159.     def update_target(self): 
  160.         self._update_actor_target() 
  161.         self._update_critic_target() 
  162.  
  163.     # ========================================================================= # 
  164.     #                              Model Predictions                            # 
  165.     # ========================================================================= # 
  166.  
  167.     def act(self, cur_state): 
  168.         self.epsilon *= self.epsilon_decay 
  169.         if np.random.random() < self.epsilon: 
  170.             return self.env.action_space.sample() 
  171.         return self.actor_model.predict(cur_state) 
  172.  
  173. def main(): 
  174.     sess = tf.Session() 
  175.     K.set_session(sess) 
  176.     env = gym.make("Pendulum-v0") 
  177.     actor_critic = ActorCritic(env, sess) 
  178.  
  179.     num_trials = 10000 
  180.     trial_len  = 500 
  181.  
  182.     cur_state = env.reset() 
  183.     action = env.action_space.sample() 
  184.     while True: 
  185.         env.render() 
  186.         cur_statecur_state = cur_state.reshape((1, env.observation_space.shape[0])) 
  187.         action = actor_critic.act(cur_state) 
  188.         actionaction = action.reshape((1, env.action_space.shape[0])) 
  189.  
  190.         new_state, reward, done, _ = env.step(action) 
  191.         new_statenew_state = new_state.reshape((1, env.observation_space.shape[0])) 
  192.  
  193.         actor_critic.remember(cur_state, action, reward, new_state, done) 
  194.         actor_critic.train() 
  195.  
  196.         cur_state = new_state 
  197.  
  198. if __name__ == "__main__": 
  199.     main() 

原文地址:

https://medium.com/towards-data-science/reinforcement-learning-w-keras-openai-actor-critic-models-f084612cfd69

【本文是51CTO專欄機(jī)構(gòu)“機(jī)器之心”的原創(chuàng)譯文,微信公眾號“機(jī)器之心( id: almosthuman2014)”】

戳這里,看該作者更多好文

 

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2017-08-22 15:56:49

神經(jīng)網(wǎng)絡(luò)強(qiáng)化學(xué)習(xí)DQN

2017-03-28 10:15:07

2024-09-13 06:32:25

2023-08-28 06:52:29

2018-11-14 10:28:38

AI數(shù)據(jù)科技

2024-01-30 09:00:28

框架BMRL模型

2022-09-04 14:38:00

世界模型建模IRIS

2023-04-06 16:29:18

模型AI

2024-01-26 08:31:49

2020-08-10 06:36:21

強(qiáng)化學(xué)習(xí)代碼深度學(xué)習(xí)

2023-03-09 08:00:00

強(qiáng)化學(xué)習(xí)機(jī)器學(xué)習(xí)圍棋

2024-04-12 08:59:02

強(qiáng)化學(xué)習(xí)系統(tǒng)人工智能擴(kuò)散模型

2022-12-01 08:00:00

2023-11-07 07:13:31

推薦系統(tǒng)多任務(wù)學(xué)習(xí)

2017-06-10 16:19:22

人工智能智能體強(qiáng)化學(xué)習(xí)

2023-01-31 10:13:29

AI模型

2025-03-05 10:21:04

DeepSeekLVLM

2023-05-05 13:11:16

2022-11-02 14:02:02

強(qiáng)化學(xué)習(xí)訓(xùn)練

2020-11-12 19:31:41

強(qiáng)化學(xué)習(xí)人工智能機(jī)器學(xué)習(xí)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號