新聞中心
本文將圍繞一個(gè)實(shí)際的問(wèn)題進(jìn)行介紹:應(yīng)用強(qiáng)化學(xué)習(xí)的社區(qū)可以如何從對(duì)腳本和單個(gè)案例的收集更進(jìn)一步,實(shí)現(xiàn)一個(gè)強(qiáng)化學(xué)習(xí) API——一個(gè)用于強(qiáng)化學(xué)習(xí)的 tf-learn 或 skikit-learn?在討論 TensorForce 框架之前,我們將談一談啟發(fā)了這個(gè)項(xiàng)目的觀察和思想。如果你只想了解這個(gè) API,你可以跳過(guò)這一部分。我們要強(qiáng)調(diào)一下:這篇文章并不包含對(duì)深度強(qiáng)化學(xué)習(xí)本身的介紹,也沒(méi)有提出什么新模型或談?wù)撟钚碌淖罴阉惴?,因此?duì)于純研究者來(lái)說(shuō),這篇文章可能并不會(huì)那么有趣。

10多年的定日網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開(kāi)發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。全網(wǎng)整合營(yíng)銷推廣的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整定日建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無(wú)論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)公司從事“定日網(wǎng)站設(shè)計(jì)”,“定日網(wǎng)站推廣”以來(lái),每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
開(kāi)發(fā)動(dòng)機(jī)
假設(shè)你是計(jì)算機(jī)系統(tǒng)、自然語(yǔ)言處理或其它應(yīng)用領(lǐng)域的研究者,你一定對(duì)強(qiáng)化學(xué)習(xí)有一些基本的了解,并且有興趣將深度強(qiáng)化學(xué)習(xí)(deep RL)用來(lái)控制你的系統(tǒng)的某些方面。
對(duì)深度強(qiáng)化學(xué)習(xí)、DQN、vanilla 策略梯度、A3C 等介紹文章已經(jīng)有很多了,比如 Karpathy 的文章(http://karpathy.github.io/2016/05/31/rl/)對(duì)策略梯度方法背后的直觀思想就進(jìn)行了很好的描述。另外,你也能找到很多可以幫助上手的代碼,比如 OpenAI 上手智能體(https://github.com/openai/baselines)、rllab(https://github.com/openai/rllab)以及 GitHub 上許多特定的算法。
但是,我們發(fā)現(xiàn)在強(qiáng)化學(xué)習(xí)的研究框架開(kāi)發(fā)和實(shí)際應(yīng)用之間還存在一個(gè)巨大的鴻溝。在實(shí)際應(yīng)用時(shí),我們可能會(huì)面臨如下的問(wèn)題:
- 強(qiáng)化學(xué)習(xí)邏輯與模擬句柄的緊密耦合:模擬環(huán)境 API 是非常方便的,比如,它們讓我們可以創(chuàng)建一個(gè)環(huán)境對(duì)象然后將其用于一個(gè) for 循環(huán)中,同時(shí)還能管理其內(nèi)部的更新邏輯(比如:通過(guò)收集輸出特征)。如果我們的目標(biāo)是評(píng)估一個(gè)強(qiáng)化學(xué)習(xí)思想,那么這就是合理的,但將強(qiáng)化學(xué)習(xí)代碼和模擬環(huán)境分開(kāi)則要艱難得多。它還涉及到流程控制的問(wèn)題:當(dāng)環(huán)境就緒后,強(qiáng)化學(xué)習(xí)代碼可以調(diào)用它嗎?或者當(dāng)環(huán)境需要決策時(shí),它會(huì)調(diào)用強(qiáng)化學(xué)習(xí)智能體嗎?對(duì)于在許多領(lǐng)域中實(shí)現(xiàn)的應(yīng)用強(qiáng)化學(xué)習(xí)庫(kù),我們往往需要后者。
- 固定的網(wǎng)絡(luò)架構(gòu):大多數(shù)實(shí)現(xiàn)案例都包含了硬編碼的神經(jīng)網(wǎng)絡(luò)架構(gòu)。這通常并不是一個(gè)大問(wèn)題,因?yàn)槲覀兛梢院苤苯拥匕凑招枨蠹尤牖蛞瞥煌木W(wǎng)絡(luò)層。盡管如此,如果有一個(gè)強(qiáng)化學(xué)習(xí)庫(kù)能夠提供聲明式接口的功能,而無(wú)需修改庫(kù)代碼,那么情況就會(huì)好得多。此外,在有的案例中,修改架構(gòu)(出人意外地)要難得多,比如當(dāng)需要管理內(nèi)部狀態(tài)的時(shí)候(見(jiàn)下文)。
- 不兼容狀態(tài)/動(dòng)作接口:很多早期的開(kāi)源代碼都使用了流行的 OpenAI Gym 環(huán)境,具有平坦的狀態(tài)輸入的簡(jiǎn)單接口和單個(gè)離散或連續(xù)動(dòng)作輸出。但 DeepMind Lab 則使用了一種詞典格式,一般具有多個(gè)狀態(tài)和動(dòng)作。而 OpenAI Universe 則使用的是命名關(guān)鍵事件(named key events)。理想情況下,我們想讓強(qiáng)化學(xué)習(xí)智能體能處理任意數(shù)量的狀態(tài)和動(dòng)作,并且具有潛在的不同類型和形狀。比如說(shuō),TensorForce 的一位作者正在 NLP 中使用強(qiáng)化學(xué)習(xí)并且想要處理多模態(tài)輸入,其中一個(gè)狀態(tài)在概念上包含兩個(gè)輸入——一張圖像和一個(gè)對(duì)應(yīng)的描述。
- 不透明的執(zhí)行設(shè)置和性能問(wèn)題:寫(xiě) TensorFlow 代碼的時(shí)候,我們很自然地會(huì)優(yōu)先關(guān)注邏輯。這會(huì)帶來(lái)大量重復(fù)/不必要的運(yùn)算或?qū)崿F(xiàn)不必要的中間值。此外,分布式/異步/并行強(qiáng)化學(xué)習(xí)的目標(biāo)也有點(diǎn)不固定,而分布式 TensorFlow 需要對(duì)特定的硬件設(shè)置進(jìn)行一定程度的人工調(diào)節(jié)。同樣,如果最終有一種執(zhí)行配置只需要聲明可用設(shè)備或機(jī)器,然后就能在內(nèi)部處理好其它一切就好了,比如兩臺(tái)有不同 IP 的機(jī)器可以運(yùn)行異步 VPG。
明確一下,這些問(wèn)題并不是要批評(píng)研究者寫(xiě)的代碼,因?yàn)檫@些代碼本來(lái)就沒(méi)打算被用作 API 或用于其它應(yīng)用。在這里我們介紹的是想要將強(qiáng)化學(xué)習(xí)應(yīng)用到不同領(lǐng)域中的研究者的觀點(diǎn)。
TensorForce API
TensorForce 提供了一種聲明式接口,它是可以使用深度強(qiáng)化學(xué)習(xí)算法的穩(wěn)健實(shí)現(xiàn)。在想要使用深度強(qiáng)化學(xué)習(xí)的應(yīng)用中,它可以作為一個(gè)庫(kù)使用,讓用戶無(wú)需擔(dān)心所有底層的設(shè)計(jì)就能實(shí)驗(yàn)不同的配置和網(wǎng)絡(luò)架構(gòu)。我們完全了解當(dāng)前的深度強(qiáng)化學(xué)習(xí)方法往往比較脆弱,而且需要大量的微調(diào),但這并不意味著我們還不能為強(qiáng)化學(xué)習(xí)解決方案構(gòu)建通用的軟件基礎(chǔ)設(shè)施。
TensorForce 并不是原始實(shí)現(xiàn)結(jié)果的集合,因?yàn)檫@不是研究模擬,要將原始實(shí)現(xiàn)用在實(shí)際環(huán)境的應(yīng)用中還需要大量的工作。任何這樣的框架都將不可避免地包含一些結(jié)構(gòu)決策,這會(huì)使得非標(biāo)準(zhǔn)的事情變得更加惱人(抽象泄漏(leaky abstractions))。這就是為什么核心強(qiáng)化學(xué)習(xí)研究者可能更傾向于從頭打造他們的模型的原因。使用 TensorForce,我們的目標(biāo)是獲取當(dāng)前最佳研究的整體方向,包含其中的新興見(jiàn)解和標(biāo)準(zhǔn)。
接下來(lái),我們將深入到 TensorForce API 的各個(gè)基本方面,并討論我們的設(shè)計(jì)選擇。
創(chuàng)建和配置智能體
我們首先開(kāi)始用 TensorForce API 創(chuàng)建一個(gè)強(qiáng)化學(xué)習(xí)智能體:
from tensorforce import Configuration
from tensorforce.agents import DQNAgent
from tensorforce.core.networks import layered_network_builder
# Define a network builder from an ordered list of layers
layers = [dict(type='dense', size=32),
dict(type='dense', size=32)]
network = layered_network_builder(layers_config=layers)
# Define a state
states = dict(shape=(10,), type='float')
# Define an action (models internally assert whether
# they support continuous and/or discrete control)
actions = dict(continuous=False, num_actions=5)
# The agent is configured with a single configuration object
agent_config = Configuration(
batch_size=8,
learning_rate=0.001,
memory_capacity=800,
first_update=80,
repeat_update=4,
target_update_frequency=20,
states=states,
actions=actions,
network=network
)
agent = DQNAgent(config=agent_config)
這個(gè)示例中的狀態(tài)和動(dòng)作是更一般的狀態(tài)/動(dòng)作的短形式(short-form)。比如由一張圖像和一個(gè)描述構(gòu)成多模態(tài)輸入按如下方式定義。類似地,也可以定義多輸出動(dòng)作。注意在整個(gè)代碼中,單個(gè)狀態(tài)/動(dòng)作的短形式必須被持續(xù)不斷地用于與智能體的通信。
states = dict(
image=dict(shape=(64, 64, 3), type='float'),
caption=dict(shape=(20,), type='int')
)
配置參數(shù)依賴于所用的基本智能體和模型。每個(gè)智能體的完整參數(shù)列表可見(jiàn)于這個(gè)示例配置:https://github.com/reinforceio/tensorforce/tree/master/examples/configs
TensorForce 目前提供了以下強(qiáng)化學(xué)習(xí)算法:
- 隨機(jī)智能體基線(RandomAgent)
- 帶有 generalized advantage estimation 的 vanilla 策略梯度(VPGAgent)
- 信任區(qū)域策略優(yōu)化(TRPOAgent)
- 深度 Q 學(xué)習(xí)/雙深度 Q 學(xué)習(xí)(DQNAgent)
- 規(guī)范化的優(yōu)勢(shì)函數(shù)(NAFAgent)
- 對(duì)專家演示的深度 Q 學(xué)習(xí)(DQFDAgent)
- Asynchronous Advantage Actor-Critic(A3C)(可以隱含地通過(guò) distributed 使用)
最后一項(xiàng)的意思是說(shuō)并沒(méi)有 A3CAgent 這樣的東西,因?yàn)?nbsp;A3C 實(shí)際上描述的是一種異步更新的機(jī)制,而不是一種特定的智能體。因此,使用分布式 TensorFlow 的異步更新機(jī)制是通用 Model 基類的一部分,所有智能體都衍生于此。正如論文《Asynchronous Methods for Deep Reinforcement Learning》中描述的那樣,A3C 是通過(guò)為 VPGAgent 設(shè)置 distributed flag 而隱含地實(shí)現(xiàn)的。應(yīng)該指出,A3C 并不是對(duì)每種模型而言都是最優(yōu)的分布式更新策略(對(duì)一些模型甚至完全沒(méi)意義),我們將在本文結(jié)尾處討論實(shí)現(xiàn)其它方法(比如 PAAC)。重要的一點(diǎn)是要在概念上將智能體和更新語(yǔ)義的問(wèn)題與執(zhí)行語(yǔ)義區(qū)分開(kāi)。
我們還想談?wù)勀P停╩odel)和智能體(agent)之間的區(qū)別。Agent 類定義了將強(qiáng)化學(xué)習(xí)作為 API 使用的接口,可以管理傳入觀察數(shù)據(jù)、預(yù)處理、探索等各種工作。其中兩個(gè)關(guān)鍵方法是 agent.act(state) 和 agent.observe(reward, terminal)。agent.act(state) 返回一個(gè)動(dòng)作,而 agent.observe(reward, terminal) 會(huì)根據(jù)智能體的機(jī)制更新模型,比如離策略記憶回放(MemoryAgent)或在策略批處理(BatchAgent)。注意,要讓智能體的內(nèi)在機(jī)制正確工作,必須交替調(diào)用這些函數(shù)。Model 類實(shí)現(xiàn)了核心強(qiáng)化學(xué)習(xí)算法,并通過(guò) get_action 和 update 方法提供了必要的接口,智能體可以在相關(guān)點(diǎn)處內(nèi)在地調(diào)用。比如說(shuō),DQNAgent 是一個(gè)帶有 DQNModel 和額外一行(用于目標(biāo)網(wǎng)絡(luò)更新)的 MemoryAgent 智能體。
def observe(self, reward, terminal):
super(DQNAgent, self).observe(reward, terminal)
if self.timestep >= self.first_update \
and self.timestep % self.target_update_frequency == 0:
self.model.update_target()
神經(jīng)網(wǎng)絡(luò)配置
強(qiáng)化學(xué)習(xí)的一個(gè)關(guān)鍵問(wèn)題是設(shè)計(jì)有效的價(jià)值函數(shù)。在概念上講,我們將模型看作是對(duì)更新機(jī)制的描述,這有別于實(shí)際更新的東西——在深度強(qiáng)化學(xué)習(xí)的例子中是指一個(gè)(或多個(gè))神經(jīng)網(wǎng)絡(luò)。因此,模型中并沒(méi)有硬編碼的網(wǎng)絡(luò),而是根據(jù)配置不同的實(shí)例化。
在上面的例子中,我們通過(guò)編程創(chuàng)造了一個(gè)網(wǎng)絡(luò)配置作為描述每一層的詞典列表。這樣的配置也可以通過(guò) JSON 給出,然后使用一個(gè)效用函數(shù)將其變成一個(gè)網(wǎng)絡(luò)構(gòu)建器(network constructor)。這里給出了一個(gè) JSON 網(wǎng)絡(luò)規(guī)范的例子:
[
{
"type": "conv2d",
"size": 32,
"window": 8,
"stride": 4
},
{
"type": "conv2d",
"size": 64,
"window": 4,
"stride": 2
},
{
"type": "flatten"
},
{
"type": "dense",
"size": 512
}
]
和之前一樣,這個(gè)配置必須被添加到該智能體的配置(configuration)對(duì)象中:
from tensorforce.core.networks import from_json
agent_config = Configuration(
...
network=from_json('configs/network_config.json')
...
)
默認(rèn)的激活層是 relu,但也還有其它激活函數(shù)可用(目前有 elu、selu、softmax、tanh 和 sigmoid)。此外也可以修改層的其它性質(zhì),比如,可以將一個(gè)稠密層(dense layer)改成這樣:
[
{
"type": "dense",
"size": 64,
"bias": false,
"activation": "selu",
"l2_regularization": 0.001
}
]
我們選擇不使用已有的層實(shí)現(xiàn)(比如來(lái)自 tf.layers),從而能對(duì)內(nèi)部運(yùn)算施加明確的控制,并確保它們能與 TensorForce 的其余部分正確地整合在一起。我們想要避免對(duì)動(dòng)態(tài) wrapper 庫(kù)的依賴,因此僅依賴于更低層的 TensorFlow 運(yùn)算。
我們的 layer 庫(kù)目前僅提供了非常少的基本層類型,但未來(lái)還會(huì)擴(kuò)展。另外你也可以輕松整合你自己的層,下面給出了一個(gè)批規(guī)范化層的例子:
def batch_normalization(x, variance_epsilon=1e-6):
mean, variance = tf.nn.moments(x, axes=tuple(range(x.shape.ndims - 1)))
x = tf.nn.batch_normalization(x, mean=mean, variance=variance,
variance_epsilon=variance_epsilon)
return x
{
"type": "[YOUR_MODULE].batch_normalization",
"variance_epsilon": 1e-9
}
到目前為止,我們已經(jīng)給出了 TensorForce 創(chuàng)建分層網(wǎng)絡(luò)的功能,即一個(gè)采用單一輸入狀態(tài)張量的網(wǎng)絡(luò),具有一個(gè)層的序列,可以得出一個(gè)輸出張量。但是在某些案例中,可能需要或更適合偏離這樣的層堆疊結(jié)構(gòu)。最顯著的情況是當(dāng)要處理多個(gè)輸入狀態(tài)時(shí),這是必需的,使用單個(gè)處理層序列無(wú)法自然地完成這一任務(wù)。
我們目前還沒(méi)有為自動(dòng)創(chuàng)建對(duì)應(yīng)的網(wǎng)絡(luò)構(gòu)建器提供更高層的配置接口。因此,對(duì)于這樣的案例,你必須通過(guò)編程來(lái)定義其網(wǎng)絡(luò)構(gòu)建器函數(shù),并像之前一樣將其加入到智能體配置中。比如之前的多模態(tài)輸入(image 和 caption)例子,我們可以按以下方式定義一個(gè)網(wǎng)絡(luò):
def network_builder(inputs):
image = inputs['image'] # 64x64x3-dim, float
caption = inputs['caption'] # 20-dim, int
with tf.variable_scope('cnn'):
weights = tf.Variable(tf.random_normal(shape=(3, 3, 3, 16), stddev=0.01))
image = tf.nn.conv2d(image, filter=weights, strides=(1, 1, 1, 1))
image = tf.nn.relu(image)
image = tf.nn.max_pool(image, ksize=(1, 2, 2, 1), strides=(1, 2, 2, 1))
weights = tf.Variable(tf.random_normal(shape=(3, 3, 16, 32), stddev=0.01))
image = tf.nn.conv2d(image, filter=weights, strides=(1, 1, 1, 1))
image = tf.nn.relu(image)
image = tf.nn.max_pool(image, ksize=(1, 2, 2, 1), strides=(1, 2, 2, 1))
image = tf.reshape(image, shape=(-1, 16 * 16, 32))
image = tf.reduce_mean(image, axis=1)
with tf.variable_scope('lstm'):
weights = tf.Variable(tf.random_normal(shape=(30, 32), stddev=0.01))
caption = tf.nn.embedding_lookup(params=weights, ids=caption)
lstm = tf.contrib.rnn.LSTMCell(num_units=64)
caption, _ = tf.nn.dynamic_rnn(cell=lstm, inputs=caption, dtype=tf.float32)
caption = tf.reduce_mean(caption, axis=1)
return tf.multiply(image, caption)
agent_config = Configuration(
...
network=network_builder
...
)
內(nèi)部狀態(tài)和 Episode 管理
和經(jīng)典的監(jiān)督學(xué)習(xí)設(shè)置(其中的實(shí)例和神經(jīng)網(wǎng)絡(luò)調(diào)用被認(rèn)為是獨(dú)立的)不同,強(qiáng)化學(xué)習(xí)一個(gè) episode 中的時(shí)間步取決于之前的動(dòng)作,并且還會(huì)影響后續(xù)的狀態(tài)。因此除了其每個(gè)時(shí)間步的狀態(tài)輸入和動(dòng)作輸出,可以想象神經(jīng)網(wǎng)絡(luò)可能有內(nèi)部狀態(tài)在 episode 內(nèi)的對(duì)應(yīng)于每個(gè)時(shí)間步的輸入/輸出。下圖展示了這種網(wǎng)絡(luò)隨時(shí)間的工作方式:
這些內(nèi)部狀態(tài)的管理(即在時(shí)間步之間前向傳播它們和在開(kāi)始新 episode 時(shí)重置它們)可以完全由 TensorForce 的 agent 和 model 類處理。注意這可以處理所有的相關(guān)用例(在 batch 之內(nèi)一個(gè) episode,在 batch 之內(nèi)多個(gè) episode,在 batch 之內(nèi)沒(méi)有終端的 episode)。到目前為止,LSTM 層類型利用了這個(gè)功能:
[
{
"type": "dense",
"size": 32
},
{
"type": "lstm"
}
]
在這個(gè)示例架構(gòu)中,稠密層的輸出被送入一個(gè) LSTM cell,然后其得出該時(shí)間步的最終輸出。當(dāng)向前推進(jìn)該 LSTM 一步時(shí),其內(nèi)部狀態(tài)會(huì)獲得更新并給出此處的內(nèi)部狀態(tài)輸出。對(duì)于下一個(gè)時(shí)間步,網(wǎng)絡(luò)會(huì)獲得新?tīng)顟B(tài)輸入及這個(gè)內(nèi)部狀態(tài),然后將該 LSTM 又推進(jìn)一步并輸出實(shí)際輸出和新的內(nèi)部 LSTM 狀態(tài),如此繼續(xù)……
對(duì)于帶有內(nèi)部狀態(tài)的層的自定義實(shí)現(xiàn),該函數(shù)不僅必須要返回該層的輸出,而且還要返回一個(gè)內(nèi)部狀態(tài)輸入占位符的列表、對(duì)應(yīng)的內(nèi)部狀態(tài)輸出張量和一個(gè)內(nèi)部狀態(tài)初始化張量列表(這些都長(zhǎng)度相同,并且按這個(gè)順序)。以下代碼片段給出了我們的 LSTM 層實(shí)現(xiàn)(一個(gè)簡(jiǎn)化版本),并說(shuō)明了帶有內(nèi)部狀態(tài)的自定義層的定義方式:
def lstm(x):
size = x.get_shape()[1].value
internal_input = tf.placeholder(dtype=tf.float32, shape=(None, 2, size))
lstm = tf.contrib.rnn.LSTMCell(num_units=size)
state = tf.contrib.rnn.LSTMStateTuple(internal_input[:, 0, :],
internal_input[:, 1, :])
x, state = lstm(inputs=x, state=state)
internal_output = tf.stack(values=(state.c, state.h), axis=1)
internal_init = np.zeros(shape=(2, size))
return x, [internal_input], [internal_output], [internal_init]
預(yù)處理狀態(tài)
我們可以定義被應(yīng)用于這些狀態(tài)(如果指定為列表的詞典,則可能是多個(gè)狀態(tài))的預(yù)處理步驟,比如,為了對(duì)視覺(jué)輸入進(jìn)行下采樣。下面的例子來(lái)自 Arcade Learning Environment 預(yù)處理器,大多數(shù) DQN 實(shí)現(xiàn)都這么用:
config = Configuration(
...
preprocessing=[
dict(
type='image_resize',
kwargs=dict(width=84, height=84)
),
dict(
type='grayscale'
),
dict(
type='center'
),
dict(
type='sequence',
kwargs=dict(
length=4
)
)
]
...
)
這個(gè) stack 中的每一個(gè)預(yù)處理器都有一個(gè)類型,以及可選的 args 列表和/或 kwargs 詞典。比如 sequence 預(yù)處理器會(huì)取最近的四個(gè)狀態(tài)(即:幀)然后將它們堆疊起來(lái)以模擬馬爾可夫?qū)傩浴kS便一提:在使用比如之前提及的 LSTM 層時(shí),這顯然不是必需的,因?yàn)?nbsp;LSTM 層可以通過(guò)內(nèi)部狀態(tài)建模和交流時(shí)間依賴。
探索
探索可以在 configuration 對(duì)象中定義,其可被智能體應(yīng)用到其模型決定所在的動(dòng)作上(以處理多個(gè)動(dòng)作,同樣,會(huì)給出一個(gè)規(guī)范詞典)。比如,為了使用 Ornstein-Uhlenbeck 探索以得到連續(xù)的動(dòng)作輸出,下面的規(guī)范會(huì)被添加到配置中。
config = Configuration(
...
exploration=dict(
type='OrnsteinUhlenbeckProcess',
kwargs=dict(
sigma=0.1,
mu=0,
theta=0.1
)
)
...
)
以下幾行代碼添加了一個(gè)用于離散動(dòng)作的 epsilon 探索,它隨時(shí)間衰減到最終值:
config = Configuration(
...
exploration=dict(
type='EpsilonDecay',
kwargs=dict(
epsilon=1,
epsilon_final=0.01,
epsilon_timesteps=1e6
)
)
...
)
用 Runner 效用函數(shù)使用智能體
讓我們使用一個(gè)智能體,這個(gè)代碼是在我們測(cè)試環(huán)境上運(yùn)行的一個(gè)智能體:https://github.com/reinforceio/tensorforce/blob/master/tensorforce/environments/minimal_test.py,我們將其用于連續(xù)積分——一個(gè)為給定智能體/模型的工作方式驗(yàn)證行動(dòng)、觀察和更新機(jī)制的最小環(huán)境。注意我們所有的環(huán)境實(shí)現(xiàn)(OpenAI Gym、OpenAI Universe、DeepMind Lab)都使用了同一個(gè)接口,因此可以很直接地使用另一個(gè)環(huán)境運(yùn)行測(cè)試。
Runner 效用函數(shù)可以促進(jìn)一個(gè)智能體在一個(gè)環(huán)境上的運(yùn)行過(guò)程。給定任意一個(gè)智能體和環(huán)境實(shí)例,它可以管理 episode 的數(shù)量,每個(gè) episode 的最大長(zhǎng)度、終止條件等。Runner 也可以接受 cluster_spec 參數(shù),如果有這個(gè)參數(shù),它可以管理分布式執(zhí)行(TensorFlow supervisors/sessions/等等)。通過(guò)可選的 episode_finished 參數(shù),你還可以周期性地報(bào)告結(jié)果,還能給出在最大 episode 數(shù)之前停止執(zhí)行的指標(biāo)。
environment = MinimalTest(continuous=False)
network_config = [
dict(type='dense', size=32)
]
agent_config = Configuration(
batch_size=8,
learning_rate=0.001,
memory_capacity=800,
first_update=80,
repeat_update=4,
target_update_frequency=20,
states=environment.states,
actions=environment.actions,
network=layered_network_builder(network_config)
)
agent = DQNAgent(config=agent_config)
runner = Runner(agent=agent, environment=environment)
def episode_finished(runner):
if runner.episode % 100 == 0:
print(sum(runner.episode_rewards[-100:]) / 100)
return runner.episode < 100 \
or not all(reward >= 1.0 for reward in runner.episode_rewards[-100:])
runner.run(episodes=1000, episode_finished=episode_finished)
為了完整,我們明確給出了在一個(gè)環(huán)境上運(yùn)行一個(gè)智能體的最小循環(huán):
episode = 0
episode_rewards = list()
while True:
state = environment.reset()
agent.reset()
timestep = 0
episode_reward = 0
while True:
action = agent.act(state=state)
state, reward, terminal = environment.execute(action=action)
agent.observe(reward=reward, terminal=terminal)
timestep += 1
episode_reward += reward
if terminal or timestep == max_timesteps:
break
episode += 1
episode_rewards.append(episode_reward)
if all(reward >= 1.0 for reward in episode_rewards[-100:]) \
or episode == max_episodes:
break
正如在引言中說(shuō)的一樣,在一個(gè)給定應(yīng)用場(chǎng)景中使用 runner 類取決于流程控制。如果使用強(qiáng)化學(xué)習(xí)可以讓我們合理地在 TensorForce 中查詢狀態(tài)信息(比如通過(guò)一個(gè)隊(duì)列或網(wǎng)絡(luò)服務(wù))并返回動(dòng)作(到另一個(gè)隊(duì)列或服務(wù)),那么它可被用于實(shí)現(xiàn)環(huán)境接口,并因此可以使用(或擴(kuò)展)runner 效用函數(shù)。
更常見(jiàn)的情況可能是將 TensorForce 用作驅(qū)動(dòng)控制的外部應(yīng)用庫(kù),因此無(wú)法提供一個(gè)環(huán)境句柄。對(duì)研究者來(lái)說(shuō),這可能無(wú)足輕重,但在計(jì)算機(jī)系統(tǒng)等領(lǐng)域,這是一個(gè)典型的部署問(wèn)題,這也是大多數(shù)研究腳本只能用于模擬,而無(wú)法實(shí)際應(yīng)用的根本原因。
另外值得提及的一點(diǎn)是聲明式的中心配置對(duì)象使得我們可以直接用超參數(shù)優(yōu)化為強(qiáng)化學(xué)習(xí)模型的所有組件配置接口,尤其還有網(wǎng)絡(luò)架構(gòu)。
進(jìn)一步思考
我們希望你能發(fā)現(xiàn) TensorForce 很有用。到目前為止,我們的重點(diǎn)還是讓架構(gòu)先就位,我們認(rèn)為這能讓我們更持續(xù)一致地實(shí)現(xiàn)不同的強(qiáng)化學(xué)習(xí)概念和新的方法,并且避免探索新領(lǐng)域中的深度強(qiáng)化學(xué)習(xí)用例的不便。
在這樣一個(gè)快速發(fā)展的領(lǐng)域,要決定在實(shí)際的庫(kù)中包含哪些功能是很困難的?,F(xiàn)在的算法和概念是非常多的,而且看起來(lái)在 Arcade Learning Environment (ALE) 環(huán)境的一個(gè)子集上,每周都有新想法得到更好的結(jié)果。但也有一個(gè)問(wèn)題存在:許多想法都只在易于并行化或有特定 episode 結(jié)構(gòu)的環(huán)境中才有效——對(duì)于環(huán)境屬性以及它們與不同方法的關(guān)系,我們還沒(méi)有一個(gè)準(zhǔn)確的概念。但是,我們能看到一些明顯的趨勢(shì):
- 策略梯度和 Q 學(xué)習(xí)方法混合以提升樣本效率(PGQ、Q-Prop 等):這是一種合乎邏輯的事情,盡管我們還不清楚哪種混合策略將占上風(fēng),但是我們認(rèn)為這將成為下一個(gè)「標(biāo)準(zhǔn)方法」。我們非常有興趣理解這些方法在不同應(yīng)用領(lǐng)域(數(shù)據(jù)豐富/數(shù)據(jù)稀疏)的實(shí)用性。我們一個(gè)非常主觀的看法是大多數(shù)應(yīng)用研究者都傾向于使用 vanilla 策略梯度的變體,因?yàn)樗鼈円子诶斫狻?shí)現(xiàn),而且更重要的是比新算法更穩(wěn)健,而新算法可能需要大量的微調(diào)才能處理潛在的數(shù)值不穩(wěn)定性(numerical instabilities)。一種不同的看法是非強(qiáng)化學(xué)習(xí)研究者可能只是不知道相關(guān)的新方法,或者不愿意費(fèi)力去實(shí)現(xiàn)它們。而這就激勵(lì)了 TensorForce 的開(kāi)發(fā)。最后,值得考慮的是,應(yīng)用領(lǐng)域的更新機(jī)制往往沒(méi)有建模狀態(tài)、動(dòng)作和回報(bào)以及網(wǎng)絡(luò)架構(gòu)重要。
- 更好地利用 GPU 和其他可用于并行/一步/分布式方法的設(shè)備(PAAC、GA3C 等):這一領(lǐng)域的方法的一個(gè)問(wèn)題是關(guān)于收集數(shù)據(jù)與更新所用時(shí)間的隱含假設(shè)。在非模擬的領(lǐng)域,這些假設(shè)可能并不成立,而理解環(huán)境屬性會(huì)如何影響設(shè)備執(zhí)行語(yǔ)義還需要更多的研究。我們?nèi)匀辉谑褂?nbsp;feed_dicts,但也在考慮提升輸入處理的性能。
- 探索模式(比如,基于計(jì)數(shù)的探索、參數(shù)空間噪聲……)
- 大型離散動(dòng)作空間、分層模型和子目標(biāo)(subgoal)的分解。比如 Dulac-Arnold 等人的論文《Deep Reinforcement Learning in Large Discrete Action Spaces》。復(fù)雜離散空間(比如許多依賴于狀態(tài)的子選項(xiàng))在應(yīng)用領(lǐng)域是高度相關(guān)的,但目前還難以通過(guò) API 使用。我們預(yù)計(jì)未來(lái)幾年會(huì)有大量成果。
- 用于狀態(tài)預(yù)測(cè)的內(nèi)部模塊和基于全新模型的方法:比如論文《The Predictron: End-To-End Learning and Planning》。
- 貝葉斯深度強(qiáng)化學(xué)習(xí)和關(guān)于不確定性的推理
總的來(lái)說(shuō),我們正在跟蹤這些發(fā)展,并且將會(huì)將此前錯(cuò)過(guò)的已有技術(shù)(應(yīng)該有很多)納入進(jìn)來(lái);而一旦我們相信一種新想法有變成穩(wěn)健的標(biāo)準(zhǔn)方法的潛力,我們也會(huì)將其納入進(jìn)來(lái)。在這個(gè)意義上,我們并沒(méi)有與研究框架構(gòu)成明確的競(jìng)爭(zhēng),而是更高程度的覆蓋。
本文轉(zhuǎn)自機(jī)器之心,原文來(lái)自reinforce,作者M(jìn)ichael Schaarschmidt、Alexander Kuhnle、Kai Fricke。
文章標(biāo)題:基于TensorFlow打造強(qiáng)化學(xué)習(xí)API:TensorForce是怎樣煉成的?
網(wǎng)站鏈接:http://m.fisionsoft.com.cn/article/ccoiijd.html


咨詢
建站咨詢
