官术网_书友最值得收藏!

2.3 OpenAI Gym API

OpenAI(www.openai.com)開發(fā)并維護(hù)了名為Gym的Python庫。Gym的主要目的是使用統(tǒng)一的接口來提供豐富的RL環(huán)境。所以這個庫的核心類是稱為Env的環(huán)境也就不足為奇了。此類的實(shí)例暴露了幾個方法和字段,以提供和其功能相關(guān)的必要信息。在較高層次上,每個環(huán)境都提供了下列信息和功能:

  • 在環(huán)境中允許執(zhí)行的一系列動作。Gym同時支持離散動作和連續(xù)動作,以及它們的組合。
  • 環(huán)境給智能體提供的觀察的形狀[1]和邊界。
  • 用來執(zhí)行動作的step方法,它會返回當(dāng)前的觀察、獎勵以及片段是否結(jié)束的指示。
  • reset方法會將環(huán)境初始化成最初狀態(tài)并返回第一個觀察。

是時候詳細(xì)討論一下環(huán)境的各個組件了。

2.3.1 動作空間

如前所述,智能體執(zhí)行的動作可以是離散的、連續(xù)的,或兩者的組合。離散動作是智能體可以執(zhí)行的一組固定的操作,比如,網(wǎng)格中的方向移動:向左、向右、向上或向下。另一個例子是按鍵,可以是按下去或釋放。這些狀態(tài)都是互斥的,因?yàn)殡x散動作空間的主要特征就是在有限的動作集合中,只能選擇一個動作執(zhí)行。

連續(xù)動作會附上一個數(shù)值,例如控制方向盤,它能轉(zhuǎn)到特定的角度,再比如油門踏板,它能用不同的力度踩壓。連續(xù)動作會有一個數(shù)值范圍限制的描述。在控制方向盤的場景下,范圍限制為–720°~720°。油門踏板則通常是0~1。

當(dāng)然,我們并沒有限制說只能執(zhí)行一個動作。在環(huán)境中可以同時執(zhí)行多個動作,例如同時按下好幾個按鈕,或者控制方向盤的同時踩兩個踏板(剎車和油門)。為了支持這樣的場景,Gym定義了一個特殊的容器類,允許用戶嵌入好幾個動作組成一個組合動作。

2.3.2 觀察空間

如第1章所述,觀察是除了獎勵之外,環(huán)境在每一時刻提供給智能體的信息。觀察可以簡單如一串?dāng)?shù)字,也可以復(fù)雜如包含來自多個攝像機(jī)彩色圖像的多維張量。觀察甚至可以像動作空間一樣是離散的。離散觀察空間的一個例子是燈泡,它可以處于兩種狀態(tài)——開或關(guān),以布爾值的形式提供給我們。

因此,動作和觀察之間存在某種相似性,圖2.1展示了它們的類如何在Gym中表示。

041-01

圖2.1 Gym中Space類的層級

最基本的抽象類Space包含兩個我們關(guān)心的方法:

  • sample():從該空間中返回隨機(jī)樣本。
  • contains(x):校驗(yàn)參數(shù)x是否屬于空間。

兩個方法都是抽象方法,會在每個Space的子類被重新實(shí)現(xiàn):

  • Discrete類表示一個互斥的元素集,用數(shù)字0到n–1標(biāo)記。它只有一個字段n,表示它包含的元素個數(shù)。例如,Discrete(n=4)表示動作空間有四個方向(上、下、左、右)可以移動。
  • Box類表示有理數(shù)的n維張量,范圍在[low, high]之間。例如,油門踏板只有一個0.0~1.0之間的值,它能被編碼成Box(low=0.0, high=1.0, shape=(1,), dtype=np.float32)shape參數(shù)被賦值成長度為1、值為1的元組,為我們提供了只有一個值的一個一維張量)。dtype參數(shù)指定空間的值類型,在此將其指定成NumPy 32-bit float。另一個Box的例子可以是Atari[2]屏幕的觀察(稍后將介紹更多Atari環(huán)境),它是一幅210×160的RGB(red, green, blue)圖像:Box(low=0, high=255, shape=(210, 160, 3), dtype=np.uint8)。在這個場景下,shape參數(shù)是有三個元素的元組,第一個維度是圖像的高,第二個維度是圖像的寬,第三個維度的值是3,它對應(yīng)于三原色的紅綠藍(lán)。因此,總結(jié)來說,每個觀察都是一個有100 800字節(jié)的三維張量。
  • 最后一個Space的子類是Tuple類,它允許我們將不同的Space實(shí)例組合起來使用。這使我們能夠創(chuàng)建出任何動作空間和觀察空間。例如,想象一下我們要為汽車創(chuàng)建一個動作空間。汽車每時每刻有好幾個可以改變的控制手段,包括:方向盤的方向、剎車踏板的位置,以及油門踏板的位置。這三個控制手段能在一個Box實(shí)例中,用三個浮點(diǎn)數(shù)來指定。除了這三個最基本的控制手段,汽車還有一些額外的離散控制手段,例如轉(zhuǎn)向燈(可能的狀態(tài)是關(guān)閉、右、左)或喇叭(開或關(guān))。為了將所有的這些組合到一個動作空間類中去,可以創(chuàng)建Tuple(spaces=(Box(low=-1.0, high=1.0, shape=(3,), dtype=np.float32), Discrete(n=3), Discrete(n=2)))。這樣過于靈活的用法很少見到,例如,在本書中,你只會看到BoxDiscrete的動作空間和觀察空間,但是Tuple類在某些場景下是很有用的。

Gym中還定義了一些其他的Space子類,但是前述的三個是最有用的。所有子類都實(shí)現(xiàn)了sample()contains()方法。sample()方法根據(jù)Space類以及傳入的參數(shù)進(jìn)行隨機(jī)采樣。它常被用在動作空間,用來選取隨機(jī)的動作。contains()方法用來檢驗(yàn)傳入的參數(shù)是否符合Space給定的可選參數(shù),Gym內(nèi)部會用它來檢驗(yàn)智能體的動作是否合理。例如,Discrete.sample()返回一個范圍中的隨機(jī)離散元素,Box.sample()則會返回一個維度正確的隨機(jī)張量,張量的值都會在給定范圍內(nèi)。

每個環(huán)境都有兩個類型為Space的成員:action_spaceobservation_space。這使得我們能夠創(chuàng)建適用于任何環(huán)境的通用代碼。當(dāng)然,處理屏幕上的像素和處理離散的觀察會有所不同(例如前面那個例子,你可能更想用卷積層或其他計算機(jī)視覺的工具庫來處理圖像),大多時候,Gym并不會阻止我們?nèi)ゾ帉懲ㄓ玫拇a,一般只有為特定的環(huán)境或一組環(huán)境優(yōu)化代碼時才需要定制代碼。

2.3.3 環(huán)境

如上所述,在Gym中環(huán)境用Env類表示,它包含下面這些成員:

  • action_spaceSpace類的一個字段,限定了環(huán)境中允許執(zhí)行的動作。
  • observation_space:也是Space類的一個字段,但是限定了環(huán)境中允許出現(xiàn)的觀察。
  • reset():將環(huán)境重置到初始狀態(tài),返回一個初始觀察的向量。
  • step():這個方法允許智能體執(zhí)行動作,并返回動作結(jié)果的信息——下一個觀察、立即獎勵以及片段是否結(jié)束的標(biāo)記。這個方法有一點(diǎn)復(fù)雜,我們會在本節(jié)后面詳細(xì)討論。

Env類中還有一些我們不會用到的實(shí)用方法,例如render(),它允許我們獲得人類可讀形式的觀察。你可以在Gym的文檔中找到這些方法的完整列表,在本書中我們還是要集中關(guān)注Env的核心方法:reset()step()

到目前為止,你已經(jīng)見過代碼如何獲取環(huán)境的動作和觀察信息,因此現(xiàn)在你需要熟悉動作本身了。通過stepreset可以和環(huán)境進(jìn)行交互。

由于reset更加簡單,我們會從它開始。reset()方法沒有參數(shù),它命令環(huán)境將自己重置成初始狀態(tài),并返回初始觀察。注意,必須在環(huán)境創(chuàng)建后調(diào)用reset()。你應(yīng)該還記得第1章中說的,智能體和環(huán)境的交互可能是會終止的(比如屏幕上顯示“游戲結(jié)束”)。這樣的一個時間段稱為片段,而智能體在片段結(jié)束后,需要重新開始。該方法返回的值是環(huán)境中的第一個觀察。

step()方法是環(huán)境的核心部分。它在一次調(diào)用中會完成多項(xiàng)操作,如下所示:

  • 告訴環(huán)境下一步將要執(zhí)行哪一個動作。
  • 在執(zhí)行動作后獲取該動作產(chǎn)生的新的觀察。
  • 獲取智能體在這一步獲得的獎勵。
  • 獲取片段是否結(jié)束的標(biāo)記。

第一項(xiàng)(動作)是該方法的唯一參數(shù),剩余幾項(xiàng)是step()方法的返回值。準(zhǔn)確地說,這是一個包含4個元素(observation, reward, done, info)的元組(這是Python元組而不是前一節(jié)所討論的Tuple類)。它們的類型和意義如下:

  • observation:包含觀察數(shù)據(jù)的NumPy向量或矩陣。
  • reward:浮點(diǎn)數(shù)的獎勵值。
  • done:布爾值標(biāo)記,如果是True則片段結(jié)束。
  • info:包含環(huán)境信息的任何東西,它和具體的環(huán)境有關(guān)。通常的做法是在通用RL方法中忽略這個值(不考慮和特定環(huán)境相關(guān)的一些細(xì)節(jié)信息)。

你可能從智能體的代碼中已經(jīng)知道環(huán)境怎么用了——在環(huán)境中,我們會不停地指定動作來調(diào)用step()方法,直到方法返回的done標(biāo)記為True。然后調(diào)用reset()方法重新開始。唯一遺漏的部分就是一開始如何創(chuàng)建Env對象。

2.3.4 創(chuàng)建環(huán)境

每個環(huán)境都有唯一的名字,形式為環(huán)境名-vN。N用來區(qū)分同一個環(huán)境的不同版本(例如,一些環(huán)境修復(fù)了bug或有重要的更新時會升級版本)。為了創(chuàng)建環(huán)境,gym包提供了函數(shù)make(env_name),它唯一的參數(shù)就是字符串形式的環(huán)境名。

在撰寫本文時,Gym的版本是0.13.1,包含859個不同名字的環(huán)境。當(dāng)然,并不是有這么多獨(dú)立的環(huán)境,因?yàn)榘谁h(huán)境的多個版本。此外,同樣的環(huán)境在不同的版本下設(shè)置或觀察空間可能會有變化。例如,Atari的Breakout游戲有這么多環(huán)境名字:

  • Breakout-v0、Breakout-v4:最原始的Breakout游戲,球的初始位置和方向是隨機(jī)的。
  • BreakoutDeterministic-v0、BreakoutDeterministic-v4:球的初始位置和速度矢量總是一樣的Breakout游戲。
  • BreakoutNoFrameskip-v0、BreakoutNoFrameskip-v4:每一幀都展示給智能體的Breakout游戲。
  • Breakout-ram-v0、Breakout-ram-v4:取代屏幕像素,用內(nèi)存模擬(128字節(jié))觀察的Breakout游戲。
  • Breakout-ramDeterministic-v0、Breakout-ramDeterministic-v4
  • Breakout-ramNoFrameskip-v0、Breakout-ramNoFrameskip-v4

總體而言,一共有12個Breakout游戲的環(huán)境。游戲的截圖如圖2.2所示(以防你從來沒有玩過)。

044-01

圖2.2 Breakout的游戲截圖

即使刪除了這些重復(fù)項(xiàng),0.13.1版本的Gym仍提供了154個獨(dú)立環(huán)境,分成以下幾組:

  • 經(jīng)典控制問題:這些是玩具任務(wù),用于最優(yōu)控制理論和RL論文的基準(zhǔn)或演示。它們一般比較簡單,觀察空間和動作空間的維度比較低,但是在快速驗(yàn)證算法的實(shí)現(xiàn)時它們還是比較有用的。將它們看作“RL”的“MNIST”(MNIST是Yann LeCun創(chuàng)建的手寫數(shù)字識別數(shù)據(jù)集,參見http://yann.lecun.com/exdb/mnist/)。
  • Atari 2600:來自20世紀(jì)70年代的經(jīng)典游戲平臺上的游戲,一共有63個。
  • 算法:這些問題旨在執(zhí)行小的計算任務(wù),例如復(fù)制觀察到的序列或數(shù)字相加。
  • 棋盤游戲:圍棋和六角棋。
  • Box2D:這些環(huán)境使用了Box2D物理引擎來模擬學(xué)習(xí)走路或汽車的控制。
  • MuJoCo:另一個用于連續(xù)控制問題的物理模擬環(huán)境。
  • 參數(shù)調(diào)優(yōu):用于調(diào)優(yōu)NN的參數(shù)的RL。
  • 玩具文本:簡單的網(wǎng)格世界文本環(huán)境。
  • PyGame:使用PyGame引擎實(shí)現(xiàn)的幾個環(huán)境。
  • Doom:基于ViZDoom實(shí)現(xiàn)的九個小游戲。

完整的環(huán)境列表可以在https://gym.openai.com/envs找到,也可以在項(xiàng)目GitHub倉庫的wiki頁面上找到。OpenAI Universe(目前已經(jīng)被OpenAI廢棄)包含更大的環(huán)境集,它提供了一個通用的連接器,用于連接智能體和跑在虛擬機(jī)中的Flash、原生游戲、瀏覽器以及其他真實(shí)的應(yīng)用。OpenAI Universe擴(kuò)展了Gym的API,但是還遵循同樣的設(shè)計原則和范式。你可以訪問https://github.com/openai/universe來了解它。由于要處理MiniWoB和瀏覽器自動化,我們會在第13章中進(jìn)一步使用Universe。

理論已足夠!是時候用Python來處理一種Gym環(huán)境了。

2.3.5 車擺系統(tǒng)

我們來應(yīng)用學(xué)到的知識探索Gym提供的最簡單的RL環(huán)境。

045-01

這里,我們導(dǎo)入了gym庫,創(chuàng)建了一個叫作CartPole(車擺系統(tǒng))的環(huán)境。該環(huán)境來自經(jīng)典的控制問題,其目的是控制底部附有木棒的平臺(見圖2.3)。

045-02

圖2.3 車擺環(huán)境

這里的難點(diǎn)是,木棒會向左或向右倒,你需要在每一步,通過讓平臺往左或往右移動來保持平衡。

這個環(huán)境的觀察是4個浮點(diǎn)數(shù),包含了木棒質(zhì)點(diǎn)的x坐標(biāo)、速度、與平臺的角度以及角速度的信息。當(dāng)然,通過應(yīng)用一些數(shù)學(xué)和物理知識,將這些數(shù)字轉(zhuǎn)換為動作來平衡木棒并不復(fù)雜,但問題是如何在不知道這些數(shù)字的確切含義、只知道獎勵的情況下,學(xué)會平衡該系統(tǒng)?這個環(huán)境每執(zhí)行一步,獎勵都是1。片段會一直持續(xù),直到木棒掉落為止,因此為了獲得更多的累積獎勵,我們需要以某種避免木棒掉落的方式平衡平臺。

這個問題看起來可能比較困難,但是在接下來的兩章中,我們會編寫一個算法,在無須了解所觀察的數(shù)字有什么含義的情況下,在幾分鐘內(nèi)輕松解決CartPole問題。我們會通過反復(fù)試驗(yàn)并加上一點(diǎn)RL魔術(shù)來做到這一點(diǎn)。

我們來繼續(xù)編寫代碼。

046-01

這里,先重置一下環(huán)境并獲得第一個觀察(在新創(chuàng)建環(huán)境時,總會重置一下它)。正如我所說,觀察結(jié)果是4個數(shù)字,我們來看一下如何提前知道這個信息。

046-02

action_space字段是Discrete類型,所以動作只會是0或1,其中0代表將平臺推向左邊,1代表推向右邊。觀察空間是Box(4,),這表示大小為4的向量,其值在[-inf, inf]區(qū)間內(nèi)。

046-03

現(xiàn)在,通過執(zhí)行動作0可以將平臺推向左邊,然后會獲得包含4個元素的元組:

  • 一個新的觀察,即包含4個數(shù)字的新向量。
  • 值為1.0的獎勵。
  • done的標(biāo)記為False,表示片段還沒有結(jié)束,目前的狀態(tài)多少還是可以的。
  • 環(huán)境的額外信息,在這里是一個空的字典。

接下來,對action_spaceobservation_space調(diào)用Space類的sample()方法。

046-04

這個方法從底層空間返回一個隨機(jī)樣本,在Discrete動作空間的情況下,這意味著為0或1的隨機(jī)數(shù),而對于觀察空間來說,這意味著包含4個數(shù)字的隨機(jī)向量。對觀察空間的隨機(jī)采樣看起來沒什么用,確實(shí)是這樣的,但是當(dāng)不知道如何執(zhí)行動作的時候,從動作空間進(jìn)行采樣是有用的。在還不知道任何RL方法,卻仍然想試一下Gym環(huán)境的時候,這個方法尤其方便。現(xiàn)在你知道如何為CartPole環(huán)境實(shí)現(xiàn)第一個行為隨機(jī)的智能體了,我們來試一試吧!


[1]原文是shape,表示一個多維數(shù)組的形狀,比如二維數(shù)組[[1,2], [3,4]]的shape是(2,2)。——譯者注

[2]Atari是美國諾蘭·布什內(nèi)爾在1972年成立的電腦公司,街機(jī)、家用電子游戲機(jī)和家用電腦的早期拓荒者。——譯者注

主站蜘蛛池模板: 泗阳县| 永康市| 凭祥市| 平江县| 烟台市| 龙门县| 吉水县| 中宁县| 隆德县| 舒城县| 枝江市| 双流县| 沈丘县| 海丰县| 衡阳县| 延吉市| 枣阳市| 龙井市| 长宁县| 绥江县| 冕宁县| 驻马店市| 福州市| 三穗县| 潼南县| 敖汉旗| 金乡县| 牡丹江市| 井研县| 嘉义县| 运城市| 虎林市| 金溪县| 富顺县| 邓州市| 阜新市| 武乡县| 临泽县| 麟游县| 和平区| 龙口市|