0
本文作者: AI研習(xí)社-譯站 | 2018-05-03 10:13 |
雷鋒網(wǎng)按:本文為雷鋒字幕組編譯的技術(shù)博客 Lessons Learned Reproducing a Deep Reinforcement Learning Paper,作者Amid Fish。
翻譯 | 黃達(dá) Moonsea 趙鵬飛 校對 | 陳俊雅 整理 | 吳璇
去年,OpenAI和DeepMind聯(lián)手做了當(dāng)時(shí)最酷的實(shí)驗(yàn),不用經(jīng)典的獎勵信號來訓(xùn)練智能體,而是根據(jù)人類反饋進(jìn)行強(qiáng)化學(xué)習(xí)的新方法。有篇博客專門講了這個(gè)實(shí)驗(yàn) Learning from Human Preferences,原始論文是《 Deep Reinforcement Learning from Human Preferences》(根據(jù)人類偏好進(jìn)行的深度增強(qiáng)學(xué)習(xí))。
通過一些深度強(qiáng)化學(xué)習(xí),你也可以訓(xùn)練木棍做后空翻
我曾經(jīng)看到過一些建議:復(fù)現(xiàn)論文是提高機(jī)器學(xué)習(xí)能力的一種很好的方法,這對我自己來說是一個(gè)有趣的嘗試。Learning from Human Preferences 的確是一個(gè)很有意思的項(xiàng)目,我很高興能復(fù)現(xiàn)它,但是回想起來這段經(jīng)歷,卻和預(yù)期有出入。
如果你也想復(fù)現(xiàn)論文,以下是一些深度強(qiáng)化學(xué)習(xí)的注意事項(xiàng):
· · ·
首先,通常來說,強(qiáng)化學(xué)習(xí)要比你預(yù)期的要復(fù)雜得多。
很大一部分原因是,強(qiáng)化學(xué)習(xí)非常敏感。有很多細(xì)節(jié)需要正確處理,如果不正確的話,你很難判斷出哪里出了問題。
情況1:完成基本實(shí)現(xiàn)后,執(zhí)行訓(xùn)練卻沒有成功。對于這個(gè)問題,我有各種各樣的想法,但結(jié)果證明是因?yàn)榧畹恼齽t化和關(guān)鍵階段1的像素?cái)?shù)據(jù)。盡管事后我知道是哪里出了問題,但也找不到可循的通關(guān)路徑:基于像素?cái)?shù)據(jù)的激勵預(yù)測器網(wǎng)絡(luò)準(zhǔn)確性的確很好,我花了很長時(shí)間仔細(xì)檢查激勵預(yù)測器,才發(fā)現(xiàn)注意到激勵正則化錯誤。找出問題發(fā)生的原因很偶然,因?yàn)樽⒁獾揭粋€(gè)小的差錯,才找到了正確的道路。
情況2:在做最后的代碼清理時(shí),我意識到我把Dropout搞錯了。激勵預(yù)測器網(wǎng)絡(luò)以一對視頻片段作為輸入,每個(gè)視頻片段由兩個(gè)具有共享權(quán)重的網(wǎng)絡(luò)進(jìn)行相同的處理。如果你在每個(gè)網(wǎng)絡(luò)中都添加了Dropout,并且不小心忘記給每個(gè)網(wǎng)絡(luò)提供相同的隨機(jī)種子,那么對于每個(gè)網(wǎng)絡(luò),Dropout出的網(wǎng)絡(luò)都是不同的,這樣視頻剪輯就不會進(jìn)行相同的處理了。盡管預(yù)測網(wǎng)絡(luò)的準(zhǔn)確性看起來完全一樣,但實(shí)際上完全破壞了原來的網(wǎng)絡(luò)訓(xùn)練。
哪一個(gè)是壞的?嗯,我也看不明白
我覺得這是經(jīng)常會發(fā)生的事情 (比如:《Deep Reinforcement Learning Doesn’t Work Yet 》)。我的收獲是,當(dāng)你開始一個(gè)強(qiáng)化學(xué)習(xí)項(xiàng)目的時(shí)候,理論上會遇到一個(gè)像被數(shù)學(xué)題困住了一樣的困境。這并不像我通常的編程經(jīng)驗(yàn):在你被困的地方,通常有一條清晰的線索可以遵循,你最多可以在幾天之內(nèi)擺脫困境。 這更像是當(dāng)你試圖解決一個(gè)難題時(shí),問題沒有明顯的進(jìn)展,唯一的方法就是各種嘗試,直到你找到關(guān)鍵的證據(jù),或者找到重要的靈感,讓你找到答案。
所以結(jié)論是在感到疑惑時(shí)應(yīng)該盡可能注意到細(xì)節(jié)。
在這個(gè)項(xiàng)目中有很多要點(diǎn),唯一的線索來自于注意那些微不足道的小事情。 例如,有時(shí)將幀之間的差異作為特征會很有效。直接利用新的特征是很有誘惑力的,但是我意識到,我并不清楚為什么它對我當(dāng)時(shí)使用的簡單環(huán)境產(chǎn)生如此大的影響。 只有處在這樣的困惑下,才能發(fā)現(xiàn),將背景歸零后取幀之間的差異會使得正則化問題顯現(xiàn)出來。
我不太確定怎么樣能讓人意識這些,但我目前最好的猜測是:
學(xué)會了解困惑是什么樣的感覺。 有很多各種各樣“不太對”的感覺。 有時(shí)候你知道代碼很難看。 有時(shí)候擔(dān)心在錯誤的事情上浪費(fèi)時(shí)間。 但有時(shí)你看到了一些你沒有預(yù)料到的東西:困惑。 能夠認(rèn)識到不舒服的確切程度是很重要的,這樣你就可以發(fā)現(xiàn)問題。
養(yǎng)成在困惑中堅(jiān)持的習(xí)慣。 有一些不舒服的地方可以暫時(shí)忽略 (例如:原型開發(fā)過程中的代碼嗅覺 ),但困惑不能忽略。當(dāng)你感到到困惑時(shí),盡量去找到原因這是很重要的。
還有,最好做好每幾周就會陷入困境的準(zhǔn)備。如果你堅(jiān)持下去,注意那些小細(xì)節(jié)并且充滿信心,你就能到達(dá)彼岸。
· · ·
說到過去編程經(jīng)驗(yàn)的不同,第二個(gè)主要的學(xué)習(xí)經(jīng)驗(yàn)是在長迭代時(shí)間下工作所需的思維方式的差異。
調(diào)試似乎涉及四個(gè)基本步驟:
搜集關(guān)于問題可能性的相關(guān)證據(jù)
形成關(guān)于這個(gè)問題的假設(shè)(根據(jù)你迄今為止搜集到的證據(jù))
選擇最有可能的假設(shè),實(shí)現(xiàn)修復(fù),看看會發(fā)生什么
重復(fù)以上步驟,直到問題消失
在我以前做過的大多數(shù)編程中,我已經(jīng)習(xí)慣了快速反饋。如果有些東西不起作用,你可以做一個(gè)改變,看看它在幾秒鐘或幾分鐘內(nèi)會產(chǎn)生什么不同。收集這些證據(jù)很容易。
事實(shí)上,在快速反饋的情況下,收集證據(jù)比形成假設(shè)要容易得多。當(dāng)你能在短時(shí)間內(nèi)驗(yàn)證第一個(gè)想法時(shí),為什么要花15分鐘仔細(xì)考慮所有的事情,即使它們可能是導(dǎo)致現(xiàn)象的原因?換句話說:如果你能獲得快速反饋的話,不用經(jīng)過認(rèn)真思考,只要不停嘗試就行了。
如果你采用的是嘗試策略,每次嘗試都需要花10小時(shí),是種非常浪費(fèi)時(shí)間的做法。如果最后一次都沒有成功呢?好吧,我承認(rèn)事情有時(shí)候就是這樣。那我們就再檢查一次。第二天早上回來:還是沒用?好吧,也許是另一種,那我們就再跑一次吧。一個(gè)星期過后,你還沒有解決這個(gè)問題。
同時(shí)進(jìn)行多次運(yùn)行,每次嘗試不同的事情,在某種程度上都會有所幫助。但是 a) 除非你能夠用集群,否則你最終可能會在云計(jì)算上付出大量的代價(jià)(見下文); b) 由于上面提到的強(qiáng)化學(xué)習(xí)的困難,如果你試圖迭代得太快,你可能永遠(yuǎn)不會意識到你到底需要什么樣的證據(jù)。
從大量的實(shí)驗(yàn)和少量的思考,轉(zhuǎn)變?yōu)樯倭康膰L試和大量的思考,是生產(chǎn)力的一個(gè)關(guān)鍵轉(zhuǎn)變。在較長的迭代時(shí)間進(jìn)行調(diào)試時(shí),你確實(shí)需要投入大量的時(shí)間到建立假設(shè)--形成步驟--思考所有的可能性是什么,它們自己看起來有多大的可能性,以及根據(jù)到目前為止所看到的一切,它們看起來有多大的可能性。盡可能多地花你時(shí)間在上面,即使需要30分鐘或一個(gè)小時(shí)。一旦你把假設(shè)空間盡可能完善了充實(shí)了,知道哪些證據(jù)可以讓你能夠最好地區(qū)分不同的可能性才可以著手實(shí)驗(yàn)。
(如果你把該項(xiàng)目作為業(yè)余項(xiàng)目,那么仔細(xì)考慮這個(gè)問題就顯得尤為重要了。 如果你每天只在這個(gè)項(xiàng)目上工作一個(gè)小時(shí),每次迭代都需要一天的時(shí)間,那么每周運(yùn)行的次數(shù)更像你必須充分利用的稀有商品。每天擠出工作時(shí)間來思考怎么樣改善運(yùn)行結(jié)果,會讓人感覺壓力非常大。所以轉(zhuǎn)變思路,花幾天的時(shí)間思考,而不是開始任何運(yùn)行,直到我對“問題是什么”的假設(shè)非常有信心為止。)
要想更多地思考,堅(jiān)持做更詳細(xì)的工作日志是非常重要的一環(huán)。當(dāng)進(jìn)展時(shí)間不到幾個(gè)小時(shí)的時(shí)候,沒有工作日志也無關(guān)緊要, 但是如果再長一點(diǎn)的話,你就很容易忘記你已經(jīng)嘗試過的東西,結(jié)果只能是在原地打轉(zhuǎn)。 我總結(jié)的日志格式是:
Log 1: 我現(xiàn)在在做的有什么具體的輸出?
Log 2: 大膽思考,例如關(guān)于當(dāng)前問題的假設(shè),下一步該做什么?
Log 3: 對當(dāng)前的運(yùn)行做個(gè)記錄,并簡短地提醒你每次運(yùn)行應(yīng)該回答哪些問題。
Log 4: 運(yùn)行的結(jié)果 (TensorBoard 圖, 任何其他重要的觀察結(jié)果), 按運(yùn)行類型分類 (例如:根據(jù)智能體訓(xùn)練時(shí)的環(huán)境)
一開始,我的日志相對較少,但在項(xiàng)目結(jié)束時(shí),我的態(tài)度更傾向于“記錄我所想的一切”。 雖然付出的時(shí)間成本很高,但我認(rèn)為是值得的,部分原因是有些調(diào)試需要相互參照的結(jié)果和想法,往往要間隔數(shù)天或數(shù)周,部分是因?yàn)椋ㄖ辽龠@是我的印象)從大規(guī)模升級轉(zhuǎn)變?yōu)橛行У乃季S的整體改進(jìn)。
典型的日志
· · ·
為了將實(shí)驗(yàn)成果效益最大化,在實(shí)驗(yàn)過程中我做了兩件事情,這些事也許會在未來發(fā)揮作用。
首先,記錄所有指標(biāo),這樣你能最大限度提升每次運(yùn)行時(shí)收集的證據(jù)數(shù)量。其中有一些明顯的指標(biāo),比如訓(xùn)練/驗(yàn)證準(zhǔn)確性。當(dāng)然,用大量時(shí)間來頭腦風(fēng)暴,研究其他指標(biāo)對于診斷潛在的問題也很重要。
我之所以提出這個(gè)建議,部分是因?yàn)楹笠暺?,因?yàn)槲抑缿?yīng)該更早地開始記錄哪些指標(biāo)。很難預(yù)測哪些指標(biāo)在高級階段會有用。不過,可能有用的策略方法是:
對于系統(tǒng)中的每一個(gè)重要組件,考慮一下可以測量什么。如果有一個(gè)數(shù)據(jù)庫,測量它在大小上增長的速度。如果有隊(duì)列,測量處理項(xiàng)目的速度。
對于每一個(gè)復(fù)雜的過程,測量它的不同部分花了多長時(shí)間。如果你有一個(gè)訓(xùn)練循環(huán),測量每一批運(yùn)行所需的時(shí)間。如果你有一個(gè)復(fù)雜的推理過程,測量每個(gè)子推理所花費(fèi)的時(shí)間。這些時(shí)間對以后的性能調(diào)試會有很大幫助,有時(shí)還會發(fā)現(xiàn)一些其他很難發(fā)現(xiàn)的錯誤。 (例如,如果你看到某些結(jié)果的時(shí)間越來越長,可能是因?yàn)閮?nèi)存泄漏。)
同樣,請考慮分析不同組件的內(nèi)存使用情況。小內(nèi)存泄漏可以指向各種事情。
另一種策略是觀察其他人在衡量什么。在深入強(qiáng)化學(xué)習(xí)的背景下,John Schulman在他的研究 Nuts and Bolts of Deep RL talk 中有一些很好的建議。對于策略梯度方法,我發(fā)現(xiàn)策略熵是一個(gè)很好的指標(biāo),它可以很好地反映訓(xùn)練是否再進(jìn)行,比每一次訓(xùn)練的獎勵都要敏感得多。
不健康和健康的策略熵圖。失敗模式1(左):收斂到常量熵(隨機(jī)選擇一個(gè)行為子集);失敗模式2(中間):收斂到零熵(每次選擇相同的動作)。右:成功的乒乓球訓(xùn)練運(yùn)行的策略熵
當(dāng)你在記錄的度量中看到一些可疑的東西時(shí),記住要注意困惑,寧愿錯誤地假設(shè)它是重要的東西,而不僅僅把它當(dāng)做一些數(shù)據(jù)結(jié)構(gòu)的低效實(shí)現(xiàn)。(我忽略了每秒的幀中一個(gè)微小但莫名的衰變,從而導(dǎo)致幾個(gè)月的多線程錯誤。)
如果能在一個(gè)地方看到所有的度量標(biāo)準(zhǔn),調(diào)試就容易得多。我喜歡盡可能多得使用Tensorboard。使用Tensorflow記錄度量標(biāo)準(zhǔn)比較困難,所以考慮使用查看easy-tf-log,它提供了一個(gè)簡單的沒有任何額外的設(shè)置界面的接口 tflog(key, value) 。
第二件看起來很有意義的是花時(shí)間嘗試和提前預(yù)測失敗。
多虧了后視偏差在回顧實(shí)驗(yàn)時(shí)失敗原因往往是顯而易見的。但真正令人沮喪的是,在你觀察到它是什么之前,失敗模式已經(jīng)顯而易見了。當(dāng)你開始訓(xùn)練一個(gè)模型,等你第二天回來一看它失敗了,甚至在你研究失敗原因之前,你就意識到“哦,那一定是因?yàn)槲彝嗽O(shè)置frobulator”?
簡單的是有時(shí)你可以提前觸發(fā)這種半事后認(rèn)知(half-hindsight-realisation)。它需要有意識的努力,在開始運(yùn)行之前先停下來思考五分鐘哪里可能出錯。我認(rèn)為最有用的腳本是: 2
1、問問自己,“如果運(yùn)行失敗了自己會有多驚訝?”
2、如果答案是“不是很驚訝”,那么設(shè)想自己處于未來場景中——這次運(yùn)行已經(jīng)失敗了,然后問問自己,“如果失敗了,哪些地方錯了?”
3、修正想到的任何地方
4、重復(fù)上述步驟知道問題1的答案是“非常驚訝”(或者至少“要多驚訝有多驚訝”)
總是會有一些你無法預(yù)測的錯誤,并且有時(shí)你仍然會忽略一些明顯可以避免的錯誤,但是這個(gè)方法至少看起來能夠減少一些你會因?yàn)闆]有事先想到而犯的非常愚蠢的錯誤。
· · ·
最后,該項(xiàng)目最令人驚訝的是花費(fèi)的時(shí)間,以及所需的計(jì)算資源。
我最初估計(jì)作為一個(gè)業(yè)余項(xiàng)目,它會耗費(fèi)3個(gè)月的時(shí)間。但是實(shí)際上它耗費(fèi)了大約8個(gè)月時(shí)間。(最初的估計(jì)其實(shí)已經(jīng)很悲觀了?。┎糠衷蚴堑凸懒嗣總€(gè)階段可能花費(fèi)的時(shí)間,但是最大的低估是沒有預(yù)測到該項(xiàng)目之外出現(xiàn)的其他事情。很難說這個(gè)推論有多么嚴(yán)謹(jǐn),但是對于業(yè)余項(xiàng)目來說,將你初始的預(yù)估時(shí)間(已經(jīng)悲觀估計(jì)的)加倍或許是個(gè)不錯的經(jīng)驗(yàn)方法。
更令人感到意外的是:每個(gè)階段實(shí)際花費(fèi)的時(shí)間。我初始的項(xiàng)目計(jì)劃中主要階段的時(shí)間表基本如下:
這是每個(gè)階段實(shí)際花費(fèi)的時(shí)間
不是寫代碼花費(fèi)了很長時(shí)間,而是調(diào)試代碼。實(shí)際上,在一個(gè)所謂的簡單環(huán)境上運(yùn)行起來花費(fèi)了4倍最初預(yù)想的實(shí)現(xiàn)時(shí)間。(這是第一個(gè)我連續(xù)花費(fèi)數(shù)小時(shí)時(shí)間的業(yè)余項(xiàng)目,但是所獲得的經(jīng)驗(yàn)與過去機(jī)器學(xué)習(xí)項(xiàng)目類似。)
(備注:從一開始就仔細(xì)設(shè)計(jì),你想象中強(qiáng)化學(xué)習(xí)的“簡單”環(huán)境。尤其是,要仔細(xì)考慮:a)你的獎勵是否能夠真正傳達(dá)解決任務(wù)的正確信息;b)獎勵是否只僅依賴之前的觀測結(jié)果還是也依賴當(dāng)前的動作。實(shí)際上,如果你在進(jìn)行任意的獎勵預(yù)測時(shí),后者可能也是相關(guān)的,例如,使用一個(gè)critic)
另一個(gè)是所需的計(jì)算資源總量。我很幸運(yùn)可以使用學(xué)校的集群,雖然機(jī)器只有 CPU ,但對一些工作來說已經(jīng)很好了。對于需要 GPU 的工作(如在一些小部分上進(jìn)行快速迭代)或集群太繁忙的時(shí)候,我用兩個(gè)云服務(wù)進(jìn)行實(shí)驗(yàn):谷歌云計(jì)算引擎的虛擬機(jī)、FloydHub。
如果你只想通過shell訪問GPU機(jī)器,谷歌云計(jì)算引擎還是不錯的,不過我更多是在FloydHub上進(jìn)行嘗試的。FloydHub基本上是一個(gè)專門面向機(jī)器學(xué)習(xí)的云計(jì)算服務(wù)。運(yùn)行floyd run python awesomecode.py 命令,F(xiàn)loydHub會初始化一個(gè)容器,將你的代碼上傳上去,并且運(yùn)行你的代碼。FloydHub如此強(qiáng)大有兩個(gè)關(guān)鍵因素:
容器預(yù)裝了GPU驅(qū)動和常用庫。(甚至在2018年,我仍然在谷歌云計(jì)算引擎虛擬機(jī)上花費(fèi)了好幾個(gè)小時(shí)處理更新TensorFlow時(shí)CUDA的版本問題。)
每次運(yùn)行都是自動存檔的。對于每次運(yùn)行,使用的代碼、用來運(yùn)行代碼的命令、命令行任意輸出以及任何輸出的數(shù)據(jù)都會自動保存,并且通過一個(gè)網(wǎng)頁接口建立索引。
如圖為FloydHub的網(wǎng)頁接口。上面:歷史運(yùn)行的索引,和單次運(yùn)行的概觀。下面:每次運(yùn)行所使用的代碼和運(yùn)行輸出的任意數(shù)據(jù)都被自動存檔。
第二點(diǎn)的重要程度我難以言表。對于任何項(xiàng)目,這種長期且詳細(xì)記錄操作和復(fù)現(xiàn)之前實(shí)驗(yàn)的能力都是絕對有必要的。雖然版本控制軟件也能有所幫助,但是a)管理大量輸出非常困難;b)需要非常勤奮。(例如,如果你開始運(yùn)行了一些,然后做了一點(diǎn)修改后又運(yùn)行了另一個(gè),當(dāng)你提交首次運(yùn)行的結(jié)果時(shí),能否清楚使用了哪份代碼?)你可以仔細(xì)記筆記或者檢查你自己的系統(tǒng),但是在FloydHub上,它都自動完成壓根不需要你花費(fèi)這么多精力。
我喜歡FloydHub的其他一些方面還有:
一旦運(yùn)行結(jié)束,容器會自動關(guān)閉。不用擔(dān)心地查看運(yùn)行是否完成、虛擬機(jī)是否關(guān)閉。
付費(fèi)比谷歌云更加直接。比如說你支付了10小時(shí)的費(fèi)用,你的虛擬機(jī)立馬就被充值了10個(gè)小時(shí)。這樣使得每周的預(yù)算更加容易。
我用FloydHub遇到的一個(gè)麻煩是它不能自定義容器。如果你的代碼有非常多的依賴包,你在每次運(yùn)行前都需要安裝這些依賴包。這就限制了短期運(yùn)行上的迭代速率。但是,你可以通過創(chuàng)建一個(gè)包含安裝這些依賴包之后文件系統(tǒng)變更的“dataset”,然后再每次開始運(yùn)行時(shí)都從“dataset”中拷貝出來這些文件解決這個(gè)問題(例如 create_floyd_base.sh)。雖然這很尷尬,但仍然比解決GPU驅(qū)動問題要好一些。
FloydHub比谷歌云稍微貴一點(diǎn):FloydHub上一個(gè)K80 GPU機(jī)器1.2美元/小時(shí),而谷歌云上類似配置的機(jī)器只需要0.85美元/小時(shí)(如果你不需要高達(dá)61G 內(nèi)存的機(jī)器的話費(fèi)用更低)。除非你的預(yù)算真的有限,我認(rèn)為FloydHub帶來的額外便利是值這個(gè)價(jià)的。只有在并行運(yùn)行大量計(jì)算的情況下,谷歌云才算是更加劃算,因?yàn)槟憧梢栽趩蝹€(gè)大型虛擬機(jī)上運(yùn)行多個(gè)。
(第三個(gè)選擇是谷歌的新Colaboratory服務(wù),這就相當(dāng)于提供給你了一個(gè)能夠在K80 GPU 機(jī)器上免費(fèi)訪問的Jupyter筆記本。但不會因?yàn)镴upyter而延遲:你可以執(zhí)行任意命令,并且如果你真的想的話可以設(shè)置shell訪問。這個(gè)最大的弊端是如果你關(guān)閉了瀏覽器窗口,你的代碼不會保持運(yùn)行,而且還有在托管該筆記本的容器重置之前能夠運(yùn)行時(shí)間的限制。所以這一點(diǎn)不適宜長期運(yùn)行,但對運(yùn)行在GPU上快速原型是有幫助的。)
這個(gè)項(xiàng)目總共花費(fèi)了:
谷歌計(jì)算引擎上150個(gè)小時(shí)GPU運(yùn)行時(shí)間,和7700小時(shí)(實(shí)際時(shí)間x核數(shù))的CPU運(yùn)行時(shí)間,
FloydHub上292小時(shí)的GPU運(yùn)行時(shí)間,
和我大學(xué)集群上 1500 小時(shí)的CPU運(yùn)行時(shí)間(實(shí)際時(shí)間,4到16核)。
我驚訝地發(fā)現(xiàn)在實(shí)現(xiàn)這個(gè)項(xiàng)目的8個(gè)月時(shí)間里,總共花費(fèi)了大約850美元(FloydHub上花了200美元,谷歌云計(jì)算引擎上花了650美元)。
其中一些原因是我笨手笨腳(見上文慢迭代思想章節(jié))。一些原因是強(qiáng)化學(xué)習(xí)仍然是如此低效,運(yùn)行起來需要花費(fèi)很長時(shí)間(每次都需要花費(fèi)多達(dá)10小時(shí)的時(shí)間來訓(xùn)練一個(gè)Pong代理)。
但其中很大一部分原因是我在這個(gè)項(xiàng)目最后階段遇到意外:強(qiáng)化學(xué)習(xí)可能不太穩(wěn)定,我們需要使用不同的隨機(jī)種子重復(fù)運(yùn)行多次以確定性能。
舉例來說,一旦我認(rèn)為基本完成了所有事情,我就會在這個(gè)環(huán)境上進(jìn)行端到端測試。但是即使我一直使用最簡單的環(huán)境,當(dāng)訓(xùn)練一個(gè)點(diǎn)移動到正方形中央上,仍然遇到了非常大的問題。因此我重新回到 FloydHub 進(jìn)行調(diào)整并運(yùn)行了三個(gè)副本,事實(shí)證明我認(rèn)為優(yōu)秀的超參數(shù)在三次測試中只成功了一次。
2/3 的隨機(jī)種子出現(xiàn)失敗(紅/藍(lán))并不罕見
對需要的計(jì)算量,我給你一個(gè)直觀的數(shù)字:
使用 A3C和16名人員,Pong 需要花費(fèi) 10 小時(shí)訓(xùn)練;
花費(fèi)160小時(shí)CPU時(shí)間;
運(yùn)行3個(gè)隨機(jī)數(shù)種子, 需要CPU花費(fèi)480小時(shí)(20天)。
成本方面:
FloydHub 每小時(shí)收費(fèi) $0.50 美金,使用8核的設(shè)備;
所以每運(yùn)行10小時(shí)收費(fèi)5美金;
同時(shí)運(yùn)行3個(gè)不同的隨機(jī)數(shù)種子,每運(yùn)行一次需要花費(fèi)15美元。
就相當(dāng)于每驗(yàn)證一次你的想法就需要花費(fèi)3個(gè)三明治的錢。
再次,從 《Deep Reinforcement Learning Doesn’t Work Yet》這篇文章中可以看到,這種不穩(wěn)定貌似正常也可接受。事實(shí)上,即使“ 五個(gè)隨機(jī)種子 (一種通用標(biāo)準(zhǔn)) 可能不足以說明結(jié)果有意義, 通過仔細(xì)選擇,你會得到不重疊的置信區(qū)間?!?br/>
(突然之間,OpenAI學(xué)者計(jì)劃提供的25,000美元的AWS學(xué)分看起來并不那么瘋狂,這可能與你給予某人的數(shù)量有關(guān),因此計(jì)算完全不用擔(dān)心。)
我的意思是,如果你想要解決一個(gè)深入的強(qiáng)化學(xué)習(xí)項(xiàng)目,請確保你知道你在做什么。確保你準(zhǔn)備好需要花費(fèi)多少時(shí)間,花多少錢。
· · ·
總的來說,復(fù)現(xiàn)一篇強(qiáng)化學(xué)習(xí)方面的論文作為業(yè)余項(xiàng)目還是很有趣的。反過來看,也可以想想從中學(xué)到了什么技能,我也想知道花費(fèi)幾個(gè)月時(shí)間復(fù)現(xiàn)一篇論文是否值得。
另一方面, 我感覺到我在機(jī)器學(xué)習(xí)方面的研究能力并沒有很大提升 (回想起來,這實(shí)際上是我的目標(biāo)),反而應(yīng)用能力得到了提升,研究中相當(dāng)多的困難似乎會產(chǎn)生出很多有趣和具體的想法;這些想法會讓你覺得為此花費(fèi)的時(shí)間是值得的。 產(chǎn)生一個(gè)有趣的想法似乎是一個(gè)問題 a) 需要大量可供利用的概念, b) 對好的想法或創(chuàng)意擁有敏銳的嗅覺 (例如,什么樣的工作會對社區(qū)有用)。為了達(dá)成以上目的,我認(rèn)為一個(gè)好的做法是閱讀有影響力論文,總結(jié)并批判性分析這些論文。
所以我認(rèn)為我從這個(gè)項(xiàng)目中得到的主要結(jié)論是,無論你是想提高工程技能還是研究技能都值得仔細(xì)思考。并不是說沒有兩者兼得的情況; 但是如果某方面是你的弱項(xiàng)的話,你可以找一個(gè)專門針對此項(xiàng)的項(xiàng)目做,來提高你的水平。
如果這兩項(xiàng)技能你都想提升,比較好的方法或許是閱讀大量論文,尋找你感興趣且有清晰代碼的論文,并嘗試實(shí)現(xiàn)或擴(kuò)展它。
· · ·
如果你想做深度強(qiáng)化學(xué)習(xí)的項(xiàng)目,這里有一些細(xì)節(jié)需要注意。
找些研究論文來復(fù)現(xiàn)
找一些知識點(diǎn)相對單一的論文,避免需要多個(gè)知識點(diǎn)協(xié)同工作的論文;
強(qiáng)化學(xué)習(xí)
如果你做的項(xiàng)目是將強(qiáng)化學(xué)習(xí)算法作為大型系統(tǒng)的一部分,不要嘗試自己編寫強(qiáng)化學(xué)習(xí)算法,盡管這是一個(gè)有趣的挑戰(zhàn),你也可以學(xué)到很多東西,但是強(qiáng)化學(xué)習(xí)目前還不足夠穩(wěn)定,你有可能會無法確定你的系統(tǒng)不工作是因?yàn)槟愕膹?qiáng)化學(xué)習(xí)算法有bug,還是因?yàn)槟愕倪@個(gè)系統(tǒng)有Bug。
做任何事之前, 檢查如何在你的環(huán)境中使用基線算法簡化智能體訓(xùn)練。
不要忘記標(biāo)準(zhǔn)化觀察,這些觀察有可能使用在所有地方。
一旦你覺得你做出了什么,就盡快寫一個(gè)端到端的測試。成功的訓(xùn)練可能比你期望的要更脆弱。
如果你使用 OpenAI Gym 環(huán)境,注意使用 -v0 環(huán)境, 有25%的可能,當(dāng)前的操作被忽略,反而重復(fù)之前的操作 (降低環(huán)境的確定性)。如果你不希望出現(xiàn)那么多隨機(jī)性的話,請使用 -v4 環(huán)境 。另外注意默認(rèn)的環(huán)境每次只提供給你從仿真器得到的4幀,與早期的DeepMInd論文一致。如果你不想這樣的話,請使用 NoFrameSkip 環(huán)境。因?yàn)檫@是一個(gè)完全穩(wěn)定的環(huán)境,它實(shí)際呈現(xiàn)出的和仿真器上給你的完全一致,例如可以使用 PongNoFrameskip-v4。
通用機(jī)器學(xué)習(xí)
端到端測試需要運(yùn)行很長時(shí)間,如果后面要進(jìn)行大規(guī)模的重構(gòu),你將浪費(fèi)大量時(shí)間。 第一次運(yùn)行時(shí)就做好總比先計(jì)算出來然后保存重構(gòu)留著后面再說要好。
初始化一個(gè)模塊需要花費(fèi)20秒。比如因?yàn)檎Z法錯誤而浪費(fèi)時(shí)間,確實(shí)讓人頭疼。如果你不喜歡IDE開發(fā)環(huán)境,或者因?yàn)槟阒荒茉趕hell的命令行窗口進(jìn)行編輯,就值得花時(shí)間為你的編輯器創(chuàng)建一個(gè)Linter。(對 Vim來說, 我喜歡帶Pylint 和 Flake8的ALE. Flake8更像一個(gè)格式檢查器, 它可以發(fā)現(xiàn)Pylint不能發(fā)現(xiàn)的問題,比如傳遞錯誤參數(shù)給某個(gè)函數(shù)。)不管怎樣,花點(diǎn)時(shí)間在linter工具上,可以在運(yùn)行前發(fā)現(xiàn)一個(gè)愚蠢的錯誤。
不僅僅dropout你要小心,在實(shí)現(xiàn)權(quán)分享網(wǎng)絡(luò)中時(shí),你也需要格外小心 - 這也是批規(guī)范化。 別忘了網(wǎng)絡(luò)中有很多規(guī)范化統(tǒng)計(jì)數(shù)據(jù)和額外的變量需要匹配。
經(jīng)??吹竭\(yùn)行過程中內(nèi)存的峰值? 這可能是你的驗(yàn)證批量規(guī)模太大了。
如果你在使用Adam作為優(yōu)化器使用時(shí)看到了奇怪的事情發(fā)生,這可能是由于 Adam 的動量參數(shù)引起。 嘗試使用沒有動量參數(shù)的優(yōu)化器,比如RMSprop,或者通過設(shè)置 β1 =0 屏蔽動量參數(shù)。
TensorFlow
如果你想調(diào)試看計(jì)算圖中間的一些節(jié)點(diǎn)發(fā)生了什么,使用 tf.Print,可以將每次運(yùn)行的輸入值打印出來。
如果你正在保存推斷的檢查點(diǎn),你可以通過忽略優(yōu)化器參數(shù)來節(jié)省大量空間。
session.run() 很燒錢。盡量批量調(diào)用。
如果您在同一臺機(jī)器上運(yùn)行多個(gè)TensorFlow實(shí)例時(shí),會出現(xiàn)GPU內(nèi)存不足的錯誤, 這很可能是因?yàn)槠渲幸粋€(gè)實(shí)例試圖占用所有內(nèi)存空間導(dǎo)致的,并不是因?yàn)槟愕哪P吞蟆_@是TensorFlow的默認(rèn)做法,你需要告訴TensorFlow只按需使用內(nèi)存空間,可以參考 allow_growth 操作。
如果你想在正在運(yùn)行的的很多東西的時(shí)候,及時(shí)訪問一個(gè)圖表,就像你從多個(gè)進(jìn)程訪問同一個(gè)圖表一樣,但是有一種鎖只允許同一時(shí)間只能有一個(gè)進(jìn)程進(jìn)行進(jìn)行相關(guān)操作。這似乎與Python的全局解釋鎖明顯不同,TensorFlow會在執(zhí)行繁重工作前釋放鎖。對此我不敢確定,也沒有時(shí)間做徹底調(diào)試。但如果你也遇到相同狀況,可以使用多進(jìn)程,并用分布式TensorFlow將圖表分復(fù)制每個(gè)進(jìn)程,將會比較簡便。
使用Python不用擔(dān)心溢出,但應(yīng)用TensorFlow時(shí),你就需要格外小心了:
當(dāng)不能使用GPU時(shí),請注意使用 allow_soft_placement 切換到CPU。如果你偶爾寫的代碼無法在GPU上運(yùn)行時(shí),它可以平滑切換到CPU。例如:
我不清楚有多少像這樣無法在GPU上運(yùn)行的操作,但安全起見,手動切換到CPU,例如:
健康的心理
不要對TensorBoard上癮。 我是認(rèn)真的。這是一個(gè)關(guān)于不可預(yù)知的獎勵上癮的完美例子:你檢查自己的操作是如何運(yùn)行的時(shí)候,而且它在不停的運(yùn)行,有時(shí)檢查時(shí)你會突然中大獎!這是件超級興奮的事。 如果你每過一段時(shí)間就有檢查 TensorBoard 的沖動,這時(shí)對你來說,應(yīng)該設(shè)置一個(gè)規(guī)則,規(guī)定合理的檢查時(shí)間間隔。
· · ·
如果你毫不猶豫地讀了這篇文章,那就太棒了!
如果你也想進(jìn)入深度強(qiáng)化學(xué)習(xí)領(lǐng)域,這里有一些資源供你入門時(shí)參考:
Andrej Karpathy的 Deep Reinforcement Learning: Pong from Pixels 是一份關(guān)于建立動機(jī)和直覺方面很好的介紹文章。
想了解更多關(guān)于強(qiáng)化學(xué)習(xí)方面的理論,可以參考 David Silver的演講 。這篇演講沒有過多關(guān)于深度強(qiáng)化學(xué)習(xí)的內(nèi)容( 基于神經(jīng)網(wǎng)絡(luò)的強(qiáng)化學(xué)習(xí) ),但至少教會了你很多詞匯,幫助你理解相關(guān)論文。
John Schulman的 Nuts and Bolts of Deep RL talk 有很多實(shí)際應(yīng)用方面的建議,這些問題你在后面都可能遇到。
想了解目前深度強(qiáng)化學(xué)習(xí)領(lǐng)域發(fā)生了什么,可以參考一下這些內(nèi)容:
Alex Irpan的 Deep Reinforcement Learning Doesn’t Work Yet 對目前的狀況有一個(gè)很好的概述。
Vlad Mnih的 Recent Advances and Frontiers in Deep RL ,有很多關(guān)于實(shí)際例子,用以解決 Alex 文章中提到的問題。
Sergey Levine的 Deep Robotic Learning 談話,聚焦改善機(jī)器人的泛化和樣本效率問題。
Pieter Abbeel 在2017 NIPS會議上 Deep Learning for Robotics 主題演講, 提到很多最新的深度強(qiáng)化學(xué)習(xí)技術(shù)。
雷鋒字幕組正在招募中,掃描下方二維碼,備注“雷鋒字幕組+姓名”加入我們。雷鋒網(wǎng)雷鋒網(wǎng)
雷峰網(wǎng)原創(chuàng)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。