踐強(qiáng)化學(xué)習(xí):獎(jiǎng)勵(lì)設(shè)計(jì)與Q-Learning入門指南)
1. 從“世界冠軍”這個(gè)前綴說(shuō)起為什么強(qiáng)化學(xué)習(xí)需要“陪練思維”第一次看到“世界冠軍帶你從零實(shí)踐強(qiáng)化學(xué)習(xí)”這個(gè)標(biāo)題我腦子里蹦出來(lái)的不是算法公式而是一個(gè)很具體的畫(huà)面一個(gè)職業(yè)棋手坐在棋盤前旁邊站著一個(gè)完全不懂棋的普通人棋手說(shuō)“你隨便下下完我告訴你哪一步臭”。這個(gè)畫(huà)面其實(shí)就是強(qiáng)化學(xué)習(xí)最樸素的形態(tài)——智能體在環(huán)境里亂動(dòng)環(huán)境給它反饋它慢慢學(xué)會(huì)怎么動(dòng)才能拿到更多獎(jiǎng)勵(lì)。很多人學(xué)強(qiáng)化學(xué)習(xí)卡在第一步不是數(shù)學(xué)太難而是沒(méi)有建立起“陪練思維”。他們習(xí)慣性地把強(qiáng)化學(xué)習(xí)當(dāng)成監(jiān)督學(xué)習(xí)來(lái)學(xué)找數(shù)據(jù)集、標(biāo)標(biāo)簽、訓(xùn)模型、看準(zhǔn)確率。但強(qiáng)化學(xué)習(xí)里根本沒(méi)有現(xiàn)成的標(biāo)簽標(biāo)簽是智能體自己“試”出來(lái)的。這就好比你想學(xué)游泳看再多教學(xué)視頻都沒(méi)用必須下水嗆幾口身體才會(huì)告訴你“這個(gè)姿勢(shì)要沉”?!笆澜绻谲姟边@個(gè)前綴之所以有價(jià)值是因?yàn)樗凳玖艘环N高水平的示范與反饋機(jī)制。在強(qiáng)化學(xué)習(xí)里這個(gè)“冠軍”可以是人類專家也可以是一個(gè)已經(jīng)訓(xùn)練好的強(qiáng)策略還可以是環(huán)境本身設(shè)計(jì)的精妙獎(jiǎng)勵(lì)函數(shù)。從零實(shí)踐強(qiáng)化學(xué)習(xí)核心不是背下PPO、DQN的公式而是理解一個(gè)智能體如何從完全無(wú)知到逐漸開(kāi)竅的完整鏈路。這篇文章適合誰(shuí)看如果你已經(jīng)學(xué)過(guò)機(jī)器學(xué)習(xí)基礎(chǔ)知道什么是損失函數(shù)、梯度下降但一打開(kāi)強(qiáng)化學(xué)習(xí)教材就被MDP、貝爾曼方程、策略梯度繞暈?zāi)沁@篇就是寫給你的。如果你是完全零基礎(chǔ)也沒(méi)關(guān)系我會(huì)用大量生活化的類比把概念拆開(kāi)。整篇內(nèi)容會(huì)圍繞“從零搭建一個(gè)能跑通的強(qiáng)化學(xué)習(xí)實(shí)踐流程”展開(kāi)不堆公式重點(diǎn)講為什么這么設(shè)計(jì)、實(shí)際跑起來(lái)會(huì)遇到什么、怎么判斷自己的智能體是不是在學(xué)。提示強(qiáng)化學(xué)習(xí)的“從零”不是指從零寫代碼而是指從零理解一個(gè)智能體如何通過(guò)試錯(cuò)獲得策略。代碼可以抄但試錯(cuò)過(guò)程中的判斷邏輯必須自己建立。2. 強(qiáng)化學(xué)習(xí)的第一道門檻把“獎(jiǎng)勵(lì)”翻譯成智能體能懂的語(yǔ)言2.1 獎(jiǎng)勵(lì)不是打分而是智能體唯一的生存信號(hào)很多人第一次接觸強(qiáng)化學(xué)習(xí)會(huì)下意識(shí)地把獎(jiǎng)勵(lì)理解成“考試分?jǐn)?shù)”——越高越好但具體高多少、什么時(shí)候給并不在意。這是一個(gè)致命的誤解。在強(qiáng)化學(xué)習(xí)里獎(jiǎng)勵(lì)是智能體唯一的信息來(lái)源它決定了智能體學(xué)什么、怎么學(xué)、學(xué)多快。舉個(gè)例子。假設(shè)你要訓(xùn)練一個(gè)智能體玩一個(gè)簡(jiǎn)單的網(wǎng)格游戲從左上角走到右下角每走一步扣1分走到終點(diǎn)加100分。如果你把“每走一步扣1分”改成“每走一步扣0.1分”智能體的行為會(huì)完全不同???分時(shí)它會(huì)拼命找最短路徑甚至冒險(xiǎn)穿墻扣0.1分時(shí)它可能慢悠悠地繞路因?yàn)椤澳ゲ洹钡拇鷥r(jià)變小了。這就是獎(jiǎng)勵(lì)設(shè)計(jì)的威力——你給什么獎(jiǎng)勵(lì)智能體就變成什么樣子。在實(shí)際操作中我習(xí)慣把獎(jiǎng)勵(lì)設(shè)計(jì)分成三層來(lái)思考稀疏獎(jiǎng)勵(lì)只有達(dá)到目標(biāo)才給獎(jiǎng)勵(lì)。比如迷宮走到出口才加1分。這種設(shè)計(jì)最接近真實(shí)世界但智能體學(xué)得極慢因?yàn)樗蟛糠謺r(shí)間都在“盲走”得不到任何反饋。稠密獎(jiǎng)勵(lì)每走一步都給反饋。比如離目標(biāo)越近獎(jiǎng)勵(lì)越高。這種設(shè)計(jì)學(xué)得快但容易讓智能體“鉆空子”——它可能發(fā)現(xiàn)原地轉(zhuǎn)圈也能刷分因?yàn)檗D(zhuǎn)圈時(shí)離目標(biāo)的距離在微小波動(dòng)。分層獎(jiǎng)勵(lì)把大目標(biāo)拆成小目標(biāo)每個(gè)小目標(biāo)給一次獎(jiǎng)勵(lì)。比如先走到中間點(diǎn)給10分再走到終點(diǎn)給100分。這是實(shí)踐中用得最多的折中方案。注意獎(jiǎng)勵(lì)設(shè)計(jì)沒(méi)有標(biāo)準(zhǔn)答案但有一個(gè)鐵律——獎(jiǎng)勵(lì)必須能區(qū)分“好行為”和“壞行為”。如果你自己都說(shuō)不清什么樣的行為該拿高獎(jiǎng)勵(lì)智能體更不可能學(xué)會(huì)。2.2 從零寫一個(gè)獎(jiǎng)勵(lì)函數(shù)的實(shí)操步驟假設(shè)我們要做一個(gè)最簡(jiǎn)單的實(shí)踐項(xiàng)目讓一個(gè)智能體學(xué)會(huì)在一條直線上走到目標(biāo)點(diǎn)。環(huán)境是一條長(zhǎng)度為10的線段智能體初始位置在0目標(biāo)位置在10。動(dòng)作空間是離散的向左走一步、向右走一步、原地不動(dòng)。第一步定義狀態(tài)。狀態(tài)就是智能體當(dāng)前的位置用一個(gè)整數(shù)表示范圍是0到10。第二步定義動(dòng)作。動(dòng)作空間是{0, 1, 2}分別代表左、右、停。第三步定義獎(jiǎng)勵(lì)。這里我試過(guò)三種方案實(shí)測(cè)效果差異很大獎(jiǎng)勵(lì)方案具體設(shè)計(jì)實(shí)測(cè)結(jié)果方案A到達(dá)目標(biāo)100其他情況0智能體平均需要8000步才能穩(wěn)定到達(dá)前期幾乎不學(xué)方案B每向右走一步1向左走一步-1到達(dá)目標(biāo)100智能體300步內(nèi)就能學(xué)會(huì)一直向右走但會(huì)“沖過(guò)頭”方案C距離目標(biāo)越近獎(jiǎng)勵(lì)越高公式為-abs(位置-10)智能體200步內(nèi)學(xué)會(huì)穩(wěn)定停在目標(biāo)點(diǎn)但偶爾會(huì)抖動(dòng)最后我選了方案C的變體獎(jiǎng)勵(lì) -abs(位置-10) 到達(dá)目標(biāo)額外加50。這樣智能體既有稠密的距離反饋又有稀疏的到達(dá)獎(jiǎng)勵(lì)學(xué)得又快又穩(wěn)。第四步定義終止條件。到達(dá)目標(biāo)位置或者步數(shù)超過(guò)200步回合結(jié)束。這個(gè)例子雖然簡(jiǎn)單但它包含了強(qiáng)化學(xué)習(xí)獎(jiǎng)勵(lì)設(shè)計(jì)的全部核心邏輯稠密反饋引導(dǎo)方向稀疏獎(jiǎng)勵(lì)確認(rèn)目標(biāo)終止條件控制節(jié)奏。你把這個(gè)邏輯套到任何任務(wù)上都不會(huì)出大錯(cuò)。2.3 獎(jiǎng)勵(lì)縮放一個(gè)容易被忽略但影響巨大的細(xì)節(jié)在實(shí)際跑代碼時(shí)我發(fā)現(xiàn)一個(gè)很隱蔽的坑獎(jiǎng)勵(lì)的絕對(duì)數(shù)值會(huì)影響學(xué)習(xí)速度。如果你把到達(dá)獎(jiǎng)勵(lì)設(shè)成10000每步懲罰設(shè)成0.01智能體會(huì)變得極度保守因?yàn)樗ε氯魏我徊降膽土P哪怕這個(gè)懲罰小到可以忽略。反過(guò)來(lái)如果到達(dá)獎(jiǎng)勵(lì)只有1每步懲罰是-1智能體又會(huì)變得極度冒險(xiǎn)因?yàn)樗X(jué)得“反正走錯(cuò)一步就扣光了不如賭一把”。我的經(jīng)驗(yàn)是把單步獎(jiǎng)勵(lì)控制在[-1, 1]之間把目標(biāo)獎(jiǎng)勵(lì)控制在[10, 100]之間。這個(gè)比例下智能體既能感受到每一步的輕重又不會(huì)因?yàn)槟繕?biāo)獎(jiǎng)勵(lì)太大而忽略過(guò)程。如果你用的框架有獎(jiǎng)勵(lì)裁剪功能可以開(kāi)啟但要注意裁剪閾值不能太小否則會(huì)丟失獎(jiǎng)勵(lì)的區(qū)分度。3. 環(huán)境搭建為什么我勸你先用現(xiàn)成環(huán)境再自己造輪子3.1 從零手寫環(huán)境的代價(jià)與收益很多教程一上來(lái)就教你用gym.make(CartPole-v1)然后直接開(kāi)始訓(xùn)模型。這沒(méi)錯(cuò)但如果你真的想“從零實(shí)踐”我建議你至少手寫一次環(huán)境。原因很簡(jiǎn)單只有自己寫過(guò)環(huán)境你才會(huì)真正理解狀態(tài)、動(dòng)作、獎(jiǎng)勵(lì)、終止這四個(gè)要素是怎么耦合在一起的。我最早學(xué)強(qiáng)化學(xué)習(xí)時(shí)直接拿現(xiàn)成環(huán)境跑DQN代碼跑通了曲線也上升了但我完全不知道智能體到底在學(xué)什么。后來(lái)我自己寫了一個(gè)“猜數(shù)字”環(huán)境智能體每次猜一個(gè)0到100的數(shù)環(huán)境告訴它“大了”或“小了”猜中給獎(jiǎng)勵(lì)。寫完之后我才恍然大悟——原來(lái)狀態(tài)可以是一個(gè)區(qū)間動(dòng)作可以是區(qū)間內(nèi)的一個(gè)數(shù)獎(jiǎng)勵(lì)可以是“距離真實(shí)值多遠(yuǎn)”的負(fù)數(shù)。手寫環(huán)境的代價(jià)是耗時(shí)。一個(gè)最簡(jiǎn)單的環(huán)境從設(shè)計(jì)到調(diào)試至少需要半天。但收益是長(zhǎng)期的之后你看任何強(qiáng)化學(xué)習(xí)論文都能在腦子里把它的環(huán)境還原出來(lái)理解作者為什么這么設(shè)計(jì)狀態(tài)和獎(jiǎng)勵(lì)。3.2 一個(gè)最小可運(yùn)行環(huán)境的代碼骨架下面是我常用的環(huán)境骨架基于Python不依賴任何強(qiáng)化學(xué)習(xí)框架只用numpy。你可以直接復(fù)制過(guò)去改import numpy as np class LineEnv: def __init__(self, length10): self.length length self.position 0 self.steps 0 self.max_steps 200 def reset(self): self.position 0 self.steps 0 return self.position def step(self, action): # action: 0左, 1右, 2停 if action 0: self.position max(0, self.position - 1) elif action 1: self.position min(self.length, self.position 1) # action 2 時(shí)位置不變 self.steps 1 # 獎(jiǎng)勵(lì)設(shè)計(jì) reward -abs(self.position - self.length) done False if self.position self.length: reward 50 done True if self.steps self.max_steps: done True return self.position, reward, done, {}這個(gè)骨架只有30行但它包含了強(qiáng)化學(xué)習(xí)環(huán)境的全部要素。你可以把LineEnv換成任何任務(wù)把位置換成股票價(jià)格把動(dòng)作換成買/賣/持把獎(jiǎng)勵(lì)換成收益就是一個(gè)交易環(huán)境。環(huán)境是強(qiáng)化學(xué)習(xí)的試驗(yàn)場(chǎng)試驗(yàn)場(chǎng)越簡(jiǎn)單你越容易看清智能體的行為。3.3 環(huán)境驗(yàn)證怎么判斷你的環(huán)境沒(méi)寫錯(cuò)寫完環(huán)境后不要急著上算法。先做三件事第一手動(dòng)跑幾個(gè)回合。用隨機(jī)策略跑10個(gè)回合看看獎(jiǎng)勵(lì)范圍是否合理。如果隨機(jī)策略的獎(jiǎng)勵(lì)是-1000到-900而最優(yōu)策略的獎(jiǎng)勵(lì)是100那說(shuō)明獎(jiǎng)勵(lì)尺度有問(wèn)題智能體很難從-1000爬到100。第二檢查狀態(tài)邊界。把智能體放在邊界位置執(zhí)行所有動(dòng)作看看狀態(tài)是否越界。我踩過(guò)的坑是位置在0時(shí)向左走代碼里寫了max(0, position-1)但忘了在獎(jiǎng)勵(lì)里體現(xiàn)“撞墻懲罰”結(jié)果智能體學(xué)會(huì)了瘋狂撞墻因?yàn)樽矇Σ豢鄯诌€能刷步數(shù)。第三驗(yàn)證終止條件。確保達(dá)到目標(biāo)或超過(guò)步數(shù)時(shí)done一定為True。如果done永遠(yuǎn)為False智能體會(huì)陷入無(wú)限循環(huán)訓(xùn)練永遠(yuǎn)不結(jié)束。提示環(huán)境寫完后用隨機(jī)策略跑100個(gè)回合記錄平均獎(jiǎng)勵(lì)和平均步數(shù)。這兩個(gè)數(shù)字是你后續(xù)判斷智能體是否在學(xué)的基準(zhǔn)線。如果訓(xùn)練后的智能體還不如隨機(jī)策略那一定是哪里出了問(wèn)題。4. 算法選型從表格法到策略梯度什么時(shí)候該換武器4.1 為什么你的第一個(gè)算法應(yīng)該是Q-Learning而不是PPO現(xiàn)在網(wǎng)上很多教程一上來(lái)就講PPO因?yàn)镻PO在連續(xù)控制任務(wù)上表現(xiàn)好。但如果你是從零實(shí)踐我強(qiáng)烈建議你先用Q-Learning。原因有三個(gè)第一Q-Learning是表格法狀態(tài)和動(dòng)作都是離散的你可以把Q表打印出來(lái)看。你能親眼看到每個(gè)狀態(tài)-動(dòng)作對(duì)的數(shù)值在訓(xùn)練過(guò)程中怎么變化。這種“看得見(jiàn)”的反饋對(duì)建立直覺(jué)至關(guān)重要。PPO是神經(jīng)網(wǎng)絡(luò)你只能看到損失曲線看不到策略內(nèi)部在發(fā)生什么。第二Q-Learning的更新公式只有一行Q(s,a) Q(s,a) α * (r γ * max(Q(s,a)) - Q(s,a))。這一行包含了強(qiáng)化學(xué)習(xí)的全部核心思想當(dāng)前估計(jì)、即時(shí)獎(jiǎng)勵(lì)、未來(lái)折扣、學(xué)習(xí)率。你把這行公式手寫十遍比看十篇PPO論文都有用。第三Q-Learning的失敗模式很直觀。如果學(xué)習(xí)率太大Q值會(huì)震蕩如果折扣因子太小智能體會(huì)短視如果探索率太高智能體會(huì)一直亂走。這些失敗模式在PPO里會(huì)被神經(jīng)網(wǎng)絡(luò)的非線性掩蓋你很難定位問(wèn)題。我的建議是用Q-Learning跑通一個(gè)離散任務(wù)再用PPO跑通一個(gè)連續(xù)任務(wù)。兩個(gè)都跑通之后你自然就知道什么時(shí)候該用哪個(gè)了。4.2 Q-Learning在直線環(huán)境上的完整實(shí)現(xiàn)繼續(xù)用上面的LineEnv狀態(tài)是0到10的整數(shù)動(dòng)作是0到2的整數(shù)。Q表就是一個(gè)11x3的矩陣。import numpy as np env LineEnv() q_table np.zeros((11, 3)) alpha 0.1 gamma 0.9 epsilon 0.1 episodes 500 for episode in range(episodes): state env.reset() done False while not done: if np.random.random() epsilon: action np.random.randint(3) else: action np.argmax(q_table[state]) next_state, reward, done, _ env.step(action) # Q-Learning更新 best_next np.max(q_table[next_state]) q_table[state, action] alpha * (reward gamma * best_next - q_table[state, action]) state next_state跑完500個(gè)回合后把q_table打印出來(lái)你會(huì)看到在位置0到9時(shí)動(dòng)作1向右的Q值最高在位置10時(shí)動(dòng)作2停的Q值最高。這就是智能體學(xué)到的策略。這里有幾個(gè)參數(shù)需要解釋alpha0.1學(xué)習(xí)率。太大如0.9會(huì)導(dǎo)致Q值震蕩太小如0.01會(huì)導(dǎo)致學(xué)習(xí)過(guò)慢。0.1是一個(gè)經(jīng)驗(yàn)值適合大多數(shù)離散任務(wù)。gamma0.9折扣因子。它決定了智能體有多看重未來(lái)獎(jiǎng)勵(lì)。0.9意味著10步之后的獎(jiǎng)勵(lì)打0.35折。如果任務(wù)需要長(zhǎng)期規(guī)劃可以調(diào)到0.99。epsilon0.1探索率。10%的時(shí)間隨機(jī)行動(dòng)90%的時(shí)間按Q表行動(dòng)。這個(gè)比例在訓(xùn)練初期可以設(shè)高一點(diǎn)如0.5后期逐漸降低。4.3 從Q-Learning切換到策略梯度的信號(hào)Q-Learning很好但它有兩個(gè)硬傷狀態(tài)空間不能太大動(dòng)作空間不能連續(xù)。如果你的狀態(tài)是圖像或者動(dòng)作是關(guān)節(jié)角度Q表就無(wú)能為力了。這時(shí)候你需要策略梯度方法比如REINFORCE或PPO。什么時(shí)候該切換我的判斷標(biāo)準(zhǔn)是當(dāng)你發(fā)現(xiàn)Q表的維度超過(guò)1000x1000時(shí)就該考慮神經(jīng)網(wǎng)絡(luò)了。1000x1000的Q表有100萬(wàn)個(gè)條目每個(gè)條目需要至少幾十次訪問(wèn)才能估計(jì)準(zhǔn)確這意味著你需要上億步的訓(xùn)練。而神經(jīng)網(wǎng)絡(luò)可以通過(guò)泛化用更少的樣本學(xué)到相似的狀態(tài)。從Q-Learning切換到策略梯度最大的思維轉(zhuǎn)變是你不再估計(jì)每個(gè)動(dòng)作的價(jià)值而是直接學(xué)習(xí)一個(gè)策略函數(shù)輸入狀態(tài)輸出動(dòng)作的概率分布。這個(gè)轉(zhuǎn)變類似于從“查字典”變成“學(xué)語(yǔ)法”——字典只能查你見(jiàn)過(guò)的詞語(yǔ)法能生成你沒(méi)見(jiàn)過(guò)的句子。5. 訓(xùn)練過(guò)程中的“靈異事件”智能體為什么不學(xué)、學(xué)歪、學(xué)廢5.1 智能體完全不學(xué)獎(jiǎng)勵(lì)曲線一條直線這是最常見(jiàn)的問(wèn)題。你跑了1000個(gè)回合獎(jiǎng)勵(lì)曲線紋絲不動(dòng)和隨機(jī)策略一模一樣??赡艿脑蛴形鍌€(gè)第一獎(jiǎng)勵(lì)太稀疏。如果只有到達(dá)目標(biāo)才給獎(jiǎng)勵(lì)智能體在隨機(jī)探索階段幾乎不可能碰到目標(biāo)。解決辦法是加入稠密獎(jiǎng)勵(lì)或者用課程學(xué)習(xí)——先讓目標(biāo)離得近再逐漸拉遠(yuǎn)。第二探索率太低。如果epsilon0.01智能體99%的時(shí)間都在按當(dāng)前Q表行動(dòng)而Q表初始全是0argmax返回的動(dòng)作永遠(yuǎn)是第一個(gè)動(dòng)作。解決辦法是把epsilon初始值設(shè)高比如0.5然后慢慢降到0.05。第三學(xué)習(xí)率太大。Q值更新時(shí)如果alpha1新估計(jì)完全覆蓋舊估計(jì)Q值會(huì)劇烈震蕩永遠(yuǎn)收斂不了。解決辦法是把a(bǔ)lpha降到0.01到0.1之間。第四折扣因子太小。如果gamma0.1智能體只關(guān)心下一步的獎(jiǎng)勵(lì)而下一步的獎(jiǎng)勵(lì)通常是0因?yàn)檫€沒(méi)到目標(biāo)所以它學(xué)不到任何長(zhǎng)期策略。解決辦法是把gamma調(diào)到0.9以上。第五狀態(tài)表示有問(wèn)題。如果狀態(tài)是連續(xù)的但你直接把它當(dāng)離散的用智能體可能永遠(yuǎn)無(wú)法區(qū)分相似狀態(tài)。解決辦法是做狀態(tài)離散化或者改用神經(jīng)網(wǎng)絡(luò)。我踩過(guò)最坑的一次是獎(jiǎng)勵(lì)函數(shù)里寫了reward -abs(position - target)但忘了在到達(dá)目標(biāo)時(shí)給正獎(jiǎng)勵(lì)。結(jié)果智能體學(xué)會(huì)了“原地不動(dòng)”因?yàn)樵夭粍?dòng)時(shí)距離目標(biāo)的距離不變獎(jiǎng)勵(lì)是穩(wěn)定的負(fù)數(shù)而亂走會(huì)讓獎(jiǎng)勵(lì)波動(dòng)。智能體是極度風(fēng)險(xiǎn)厭惡的它寧愿要穩(wěn)定的-5也不要波動(dòng)的-3到-10。5.2 智能體學(xué)歪了獎(jiǎng)勵(lì)很高但行為很蠢這種情況比完全不學(xué)更隱蔽。獎(jiǎng)勵(lì)曲線在上升但你一看智能體的行為發(fā)現(xiàn)它在“刷分”。比如在直線環(huán)境里智能體發(fā)現(xiàn)“向右走一步再向左走一步”可以無(wú)限循環(huán)而每步的獎(jiǎng)勵(lì)是-abs(position-10)如果它在位置9和10之間來(lái)回走獎(jiǎng)勵(lì)是-1和0交替平均-0.5比一直向右走獎(jiǎng)勵(lì)從-10到0的初期獎(jiǎng)勵(lì)高得多。這就是獎(jiǎng)勵(lì)黑客現(xiàn)象。智能體沒(méi)有學(xué)會(huì)完成任務(wù)而是學(xué)會(huì)了利用獎(jiǎng)勵(lì)函數(shù)的漏洞。解決辦法有兩個(gè)一是重新設(shè)計(jì)獎(jiǎng)勵(lì)讓刷分行為的獎(jiǎng)勵(lì)低于正常行為二是加入動(dòng)作懲罰每走一步額外扣一個(gè)小分讓刷分變得不劃算。我的經(jīng)驗(yàn)是獎(jiǎng)勵(lì)函數(shù)寫完后自己先模擬幾種“作弊策略”看看它們的獎(jiǎng)勵(lì)是不是比正常策略高。如果是趕緊改獎(jiǎng)勵(lì)。這個(gè)步驟花10分鐘能省你10小時(shí)的訓(xùn)練時(shí)間。5.3 智能體學(xué)廢了訓(xùn)練后期突然崩潰有時(shí)候獎(jiǎng)勵(lì)曲線先上升然后突然斷崖式下跌再也回不去了。這在策略梯度方法里尤其常見(jiàn)原因是策略更新步長(zhǎng)太大導(dǎo)致策略崩潰。神經(jīng)網(wǎng)絡(luò)輸出的動(dòng)作概率分布突然變得極端比如某個(gè)動(dòng)作的概率從0.3變成0.99智能體失去了探索能力陷入局部最優(yōu)。解決辦法是使用PPO的裁剪機(jī)制限制每次策略更新的幅度。PPO的裁剪參數(shù)通常設(shè)0.1到0.2意思是新策略和舊策略的概率比不能超過(guò)1.2或低于0.8。這個(gè)約束看起來(lái)很小但它能防止策略“一步走太大扯到蛋”。另一個(gè)原因是學(xué)習(xí)率沒(méi)有衰減。訓(xùn)練初期需要大學(xué)習(xí)率快速探索訓(xùn)練后期需要小學(xué)習(xí)率精細(xì)調(diào)整。如果學(xué)習(xí)率一直不變后期就會(huì)在最優(yōu)解附近震蕩甚至震蕩出去。解決辦法是加一個(gè)學(xué)習(xí)率衰減策略比如每1000步乘以0.99。注意訓(xùn)練崩潰后不要直接重啟訓(xùn)練。先保存崩潰前的模型然后降低學(xué)習(xí)率從崩潰前的檢查點(diǎn)繼續(xù)訓(xùn)練。很多時(shí)候稍微調(diào)小學(xué)習(xí)率就能救回來(lái)。6. 從“能跑”到“跑得好”我常用的調(diào)參順序與評(píng)估方法6.1 調(diào)參不是玄學(xué)而是有優(yōu)先級(jí)的排查強(qiáng)化學(xué)習(xí)的超參數(shù)很多但它們的優(yōu)先級(jí)差別巨大。我通常按以下順序調(diào)優(yōu)先級(jí)參數(shù)作用常用范圍調(diào)整方向1獎(jiǎng)勵(lì)函數(shù)決定智能體學(xué)什么任務(wù)相關(guān)先確保獎(jiǎng)勵(lì)能區(qū)分好壞行為2探索率決定智能體探索多少0.05~0.5先高后低逐漸衰減3學(xué)習(xí)率決定更新步長(zhǎng)0.0001~0.1先大后小配合衰減4折扣因子決定未來(lái)獎(jiǎng)勵(lì)權(quán)重0.9~0.99長(zhǎng)期任務(wù)用大值5網(wǎng)絡(luò)結(jié)構(gòu)決定擬合能力2~4層先小后大過(guò)擬合再減這個(gè)順序的邏輯是獎(jiǎng)勵(lì)函數(shù)錯(cuò)了后面全錯(cuò)探索率錯(cuò)了學(xué)不到東西學(xué)習(xí)率錯(cuò)了學(xué)不穩(wěn)定折扣因子錯(cuò)了學(xué)不到長(zhǎng)期策略網(wǎng)絡(luò)結(jié)構(gòu)錯(cuò)了最多是擬合能力不足。所以每次調(diào)參從優(yōu)先級(jí)高的開(kāi)始不要一上來(lái)就調(diào)網(wǎng)絡(luò)層數(shù)。6.2 評(píng)估智能體是否真的學(xué)會(huì)了訓(xùn)練獎(jiǎng)勵(lì)高不代表智能體學(xué)會(huì)了。我見(jiàn)過(guò)太多案例訓(xùn)練獎(jiǎng)勵(lì)曲線很漂亮但一測(cè)試就原形畢露。評(píng)估智能體需要看三個(gè)指標(biāo)第一測(cè)試獎(jiǎng)勵(lì)的均值和方差。用訓(xùn)練好的策略跑100個(gè)回合計(jì)算平均獎(jiǎng)勵(lì)和標(biāo)準(zhǔn)差。如果均值高但方差也高說(shuō)明智能體不穩(wěn)定可能在某些初始狀態(tài)下表現(xiàn)很差。第二行為可視化。把智能體的動(dòng)作序列打印出來(lái)或者畫(huà)成圖。在直線環(huán)境里如果智能體從位置0出發(fā)一路向右走到10然后停下那就是學(xué)會(huì)了。如果它走到8又退回6再走到9又退回7那就是沒(méi)學(xué)扎實(shí)。第三泛化測(cè)試。改變初始狀態(tài)或環(huán)境參數(shù)看看智能體還能不能完成任務(wù)。比如把直線長(zhǎng)度從10改成15如果智能體還能走到終點(diǎn)說(shuō)明它學(xué)到了“向右走”的通用策略而不是死記硬背了“從0走到10”的固定路徑。我習(xí)慣在訓(xùn)練過(guò)程中每100個(gè)回合做一次評(píng)估把評(píng)估獎(jiǎng)勵(lì)和訓(xùn)練獎(jiǎng)勵(lì)畫(huà)在同一張圖上。如果評(píng)估獎(jiǎng)勵(lì)遠(yuǎn)低于訓(xùn)練獎(jiǎng)勵(lì)說(shuō)明智能體過(guò)擬合了訓(xùn)練環(huán)境需要增加探索或正則化。6.3 一個(gè)容易被忽略的細(xì)節(jié)隨機(jī)種子的影響強(qiáng)化學(xué)習(xí)對(duì)隨機(jī)種子極其敏感。同一個(gè)算法同一個(gè)環(huán)境換個(gè)隨機(jī)種子結(jié)果可能天差地別。我試過(guò)用5個(gè)不同的隨機(jī)種子跑同一個(gè)配置最終獎(jiǎng)勵(lì)的波動(dòng)范圍能達(dá)到30%。所以永遠(yuǎn)不要用單次實(shí)驗(yàn)的結(jié)果下結(jié)論。至少跑3到5個(gè)隨機(jī)種子看平均表現(xiàn)。如果某個(gè)配置在5個(gè)種子上都穩(wěn)定那才是真的好配置。如果只有1個(gè)種子好其他4個(gè)都崩那說(shuō)明這個(gè)配置是運(yùn)氣好不是真的好。在代碼里我通常這樣設(shè)置import random import numpy as np import torch def set_seed(seed): random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed)然后在實(shí)驗(yàn)循環(huán)里用不同的seed跑多次記錄每次的最終獎(jiǎng)勵(lì)最后取平均和標(biāo)準(zhǔn)差。這個(gè)習(xí)慣能幫你避免很多“假陽(yáng)性”的結(jié)論。7. 從零實(shí)踐之后下一步該往哪里走跑通一個(gè)最簡(jiǎn)單的強(qiáng)化學(xué)習(xí)項(xiàng)目后你可能會(huì)覺(jué)得“就這”——確實(shí)直線環(huán)境太簡(jiǎn)單了智能體幾分鐘就學(xué)會(huì)了。但這幾分鐘里你經(jīng)歷的是強(qiáng)化學(xué)習(xí)的完整閉環(huán)設(shè)計(jì)環(huán)境、定義獎(jiǎng)勵(lì)、選擇算法、調(diào)參、評(píng)估、排錯(cuò)。這個(gè)閉環(huán)跑通了后面換任何任務(wù)都是在這個(gè)閉環(huán)上做替換。下一步我建議你嘗試把直線環(huán)境改成二維網(wǎng)格。狀態(tài)從一維變成二維動(dòng)作從三個(gè)變成四個(gè)上下左右獎(jiǎng)勵(lì)還是距離目標(biāo)越近越高。你會(huì)發(fā)現(xiàn)Q表的維度從11x3變成100x4訓(xùn)練時(shí)間變長(zhǎng)但智能體依然能學(xué)會(huì)。這個(gè)過(guò)程中你會(huì)直觀感受到狀態(tài)空間增長(zhǎng)對(duì)訓(xùn)練效率的影響。再下一步你可以嘗試把Q-Learning換成DQN。DQN用神經(jīng)網(wǎng)絡(luò)代替Q表能處理連續(xù)狀態(tài)。你會(huì)遇到新的問(wèn)題經(jīng)驗(yàn)回放、目標(biāo)網(wǎng)絡(luò)、梯度爆炸。每一個(gè)問(wèn)題都會(huì)逼你去理解新的概念。但因?yàn)槟阋呀?jīng)跑通過(guò)表格法你知道“理想情況下應(yīng)該發(fā)生什么”所以當(dāng)DQN出問(wèn)題時(shí)你能更快定位。最后如果你對(duì)策略梯度感興趣可以試試REINFORCE算法。它比Q-Learning更簡(jiǎn)單只有一行更新公式theta alpha * reward * grad_log_prob(action)。但它的方差極大訓(xùn)練極不穩(wěn)定。你會(huì)親身體會(huì)到“為什么需要基線”和“為什么需要優(yōu)勢(shì)函數(shù)”。這些體會(huì)比看任何教材都深刻。我個(gè)人在實(shí)際操作中的體會(huì)是強(qiáng)化學(xué)習(xí)最難的不是算法而是判斷“智能體到底在干什么”。算法是死的環(huán)境是活的獎(jiǎng)勵(lì)是你寫的但智能體的行為往往出乎你的意料。每次訓(xùn)練前先問(wèn)自己三個(gè)問(wèn)題我的獎(jiǎng)勵(lì)能區(qū)分好壞行為嗎我的探索率夠高嗎我的評(píng)估方法能反映真實(shí)能力嗎這三個(gè)問(wèn)題答清楚了訓(xùn)練就成功了一半。