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