化學(xué)習(xí)算法詳解:從策略梯度穩(wěn)定到GAE調(diào)參實(shí)戰(zhàn))
如果你跟我一樣是從策略梯度一路調(diào)參調(diào)過(guò)來(lái)的應(yīng)該對(duì)“步長(zhǎng)選擇”這四個(gè)字有心理陰影。REINFORCE的方差大到你懷疑人生DQN換了個(gè)環(huán)境就翻車好不容易找到一個(gè)能收斂的任務(wù)稍微改一改獎(jiǎng)勵(lì)尺度策略又炸了。等你被折磨到需要一套“放在新任務(wù)上大概率能跑起來(lái)”的算法時(shí)幾乎所有人都會(huì)把目光轉(zhuǎn)向PPOProximal Policy Optimization近端策略優(yōu)化。這個(gè)算法看起來(lái)簡(jiǎn)單到不像是學(xué)術(shù)界給的答案——它只是把策略更新的步子限制在一個(gè)可控范圍內(nèi)但就是這“限制”二字解決了強(qiáng)化學(xué)習(xí)里最要命的穩(wěn)定性問(wèn)題。如果你順著這個(gè)系列看到第五篇應(yīng)該已經(jīng)對(duì)策略梯度、Actor-Critic框架這些基礎(chǔ)不陌生。今天這篇只干一件事把PPO從頭到尾拆開講清楚它為什么能穩(wěn)定clip到底在保護(hù)什么GAE里的λ怎么選訓(xùn)練循環(huán)里每個(gè)loss是干嘛的以及我在實(shí)際跑任務(wù)時(shí)踩過(guò)的幾個(gè)坑和對(duì)應(yīng)的救法。文章最后還會(huì)給出一套可以直接往自己項(xiàng)目里抄的工程經(jīng)驗(yàn)。1. 從TRPO的穩(wěn)到PPO的好用PPO到底解決了個(gè)什么問(wèn)題1.1 策略梯度方法的老毛病一步踩空就翻車先回到一個(gè)重要共識(shí)策略梯度類算法的核心是“用當(dāng)前策略采樣然后在采到的那批數(shù)據(jù)上更新策略”。參數(shù)更新之后下一次采樣用的策略就變了。如果這次更新的幅度太大新策略跟采樣時(shí)用的舊策略差異會(huì)非常大你在舊策略上估計(jì)出來(lái)的梯度方向可能已經(jīng)完全失效?;貞浺幌翿EINFORCE或者樸素Actor-Critic的更新方式θ ← θ α * ?θ J(θ)這個(gè)公式看起來(lái)沒(méi)什么問(wèn)題但實(shí)際跑起來(lái)你就知道α稍微大一點(diǎn)動(dòng)作概率分布就會(huì)猛地偏向某一個(gè)方向。下一輪采樣時(shí)智能體碰到的狀態(tài)分布也變了原來(lái)的Q值估計(jì)、優(yōu)勢(shì)估計(jì)全部失真訓(xùn)練曲線直接斷崖式下跌。小步慢走倒是穩(wěn)但收斂速度慢到?jīng)]法用。1.2 TRPO的硬核方案為什么代價(jià)高順著這個(gè)思路TRPOTrust Region Policy Optimization做的事情是把“新策略和舊策略的KL散度不能太大”作為一個(gè)硬約束然后去解一個(gè)帶約束的優(yōu)化問(wèn)題。理論上這很漂亮實(shí)踐上卻很痛苦。你需要計(jì)算策略梯度的二階近似做Fisher信息矩陣的共軛梯度求解還要做線搜索來(lái)保證每一步都滿足KL約束。我不是說(shuō)TRPO不好它確實(shí)穩(wěn)定。但它實(shí)現(xiàn)起來(lái)太啰嗦而且二階優(yōu)化相關(guān)的數(shù)學(xué)細(xì)節(jié)多很容易在實(shí)現(xiàn)時(shí)埋bug。尤其到了深度學(xué)習(xí)框架里跑分布式TRPO的約束計(jì)算要同步新舊策略的統(tǒng)計(jì)信息工程復(fù)雜度直接翻倍。所以很長(zhǎng)一段時(shí)間里學(xué)術(shù)界大家都在找一個(gè)“有一階優(yōu)化的簡(jiǎn)潔又有TRPO的穩(wěn)定”的替代方案。1.3 PPO給出一階優(yōu)化版本的信任域PPO的做法其實(shí)很粗暴我不顯式去算KL散度約束了我在目標(biāo)函數(shù)里直接對(duì)“新舊策略的比值”做裁剪。如果比值超出[1-ε, 1ε]這個(gè)區(qū)間我就把對(duì)應(yīng)的收益截?cái)?。這樣一來(lái)策略每次更新能偏離的程度天然被限制住了而且整個(gè)目標(biāo)函數(shù)是可微的可以走普通梯度下降。PPO論文里其實(shí)給了兩個(gè)版本一個(gè)是自適應(yīng)KL懲罰版本另一個(gè)是clipped surrogate objective版本。后者因?yàn)閷?shí)現(xiàn)簡(jiǎn)單、效果好成了大家默認(rèn)說(shuō)的PPO。OpenAI在早期把PPO用在機(jī)器人控制、Atari、MuJoCo上都表現(xiàn)穩(wěn)定后來(lái)很多工業(yè)場(chǎng)景也直接拿它當(dāng)基線。對(duì)我們做實(shí)際項(xiàng)目的人來(lái)說(shuō)PPO最大的價(jià)值不是“理論分?jǐn)?shù)高”而是“給你一批默認(rèn)超參數(shù)它大概率能出點(diǎn)像樣的學(xué)習(xí)曲線”這種省心屬性在算法研發(fā)里太珍貴了。2. 裁剪比值還是施加懲罰clip技巧背后的數(shù)學(xué)直覺(jué)2.1 importance ratio到底在衡量什么PPO對(duì)應(yīng)的目標(biāo)函數(shù)里最核心的量是這個(gè)比值r_t(θ) π_θ(a_t | s_t) / π_old(a_t | s_t)分母上是你采樣時(shí)用的舊策略分子上是當(dāng)前正在優(yōu)化的新策略。這個(gè)比值如果等于1說(shuō)明新舊策略在這一步上沒(méi)有差別大于1說(shuō)明新策略現(xiàn)在給出這個(gè)動(dòng)作的概率比舊策略高小于1說(shuō)明新策略對(duì)這個(gè)動(dòng)作的概率在下降。我們會(huì)把優(yōu)勢(shì)函數(shù)A_t乘到這個(gè)比值上。如果某個(gè)動(dòng)作比平均表現(xiàn)好A_t是正的那模型就有動(dòng)力增大這個(gè)動(dòng)作的概率r_t會(huì)往上走。反過(guò)來(lái)如果表現(xiàn)差A(yù)_t是負(fù)的模型就會(huì)降低這個(gè)動(dòng)作的概率r_t往下走。問(wèn)題在于r_t可以因?yàn)橐粋€(gè)極小概率動(dòng)作被翻倍而變得非常大單條樣本就能把策略拉飛這正是樽頸所在。2.2 clip函數(shù)如何把更新框進(jìn)安全區(qū)PPO的clipped目標(biāo)函數(shù)長(zhǎng)這樣L^CLIP(θ) E[ min( r_t(θ) * A_t, clip(r_t(θ), 1-ε, 1ε) * A_t ) ]這里的clip操作會(huì)把r_t限幅到[1-ε, 1ε]之間然后再乘以A_t。最后取min意思是要原始目標(biāo)值和裁剪后的目標(biāo)值兩兄弟當(dāng)中的一個(gè)更小者。結(jié)合A_t的正負(fù)分開看邏輯非常直白當(dāng)A_t 0時(shí)這個(gè)動(dòng)作是“好動(dòng)作”我們想讓r_t變大。但r_t一旦超過(guò)1εmin就會(huì)選擇裁剪后的較小的那部分梯度被截?cái)嗄P筒辉侬偪裉Ц哌@個(gè)動(dòng)作的概率。當(dāng)A_t 0時(shí)這個(gè)動(dòng)作是對(duì)表現(xiàn)有負(fù)面影響的我們想讓r_t變小。但r_t一旦小于1-εmin會(huì)選中未被裁剪的較大的那部分還是裁剪后的這里要仔細(xì)理解一句A_t是負(fù)值裁剪后值域在[-1-ε, -1ε]區(qū)間乘上A_t取負(fù)之后和原始值相比取min最終會(huì)限制下降速度。這個(gè)“好動(dòng)作也不許一把梭”的思路就是PPO在阻止你踩空的核心機(jī)制。它不阻止小步修正只攔著大步莽撞。2.3 ε的默認(rèn)值0.2是怎么來(lái)的PPO論文里ε取0.2OpenAI的baselines實(shí)現(xiàn)里也跟著用0.2。為什么不是0.1也不是0.5根據(jù)論文里的消融實(shí)驗(yàn)ε太小比如0.1時(shí)策略更新更保守學(xué)習(xí)速度慢ε太大比如0.5時(shí)更新步長(zhǎng)過(guò)大穩(wěn)定性退化。0.2是一個(gè)經(jīng)驗(yàn)上“既要學(xué)習(xí)速度又要穩(wěn)定”的折中。我自己在連續(xù)控制任務(wù)上試過(guò)ε0.2基本是安全牌。如果你發(fā)現(xiàn)學(xué)習(xí)曲線太平可以稍微調(diào)小到0.1-0.15如果訓(xùn)練不穩(wěn)定可以調(diào)大到0.25-0.3。但總的來(lái)說(shuō)不用在這個(gè)超參數(shù)上花太多時(shí)間它的敏感度比學(xué)習(xí)率和GAE的λ低得多。提示實(shí)現(xiàn)時(shí)clip的上下界最好不要寫死1-ε和1ε而是寫成一個(gè)區(qū)間[a, b]傳進(jìn)來(lái)方便后面做自適應(yīng)裁剪或動(dòng)態(tài)調(diào)整。代碼層面多做這一步抽象后面調(diào)參能省很多事。3. 像素級(jí)拆解PPO的Actor-Critic訓(xùn)練循環(huán)3.1 一遍Rollout加多輪SGD更新的完整流程PPO的訓(xùn)練循環(huán)可以濃縮成以下幾個(gè)步驟用當(dāng)前策略π_old在環(huán)境里采樣若干條軌跡或者用多個(gè)環(huán)境并行采樣收集狀態(tài)、動(dòng)作、獎(jiǎng)勵(lì)、下一狀態(tài)、終止標(biāo)志。在這些軌跡上計(jì)算GAE優(yōu)勢(shì)估計(jì)以及每個(gè)狀態(tài)的回報(bào)目標(biāo)值也就是V target。將新舊策略比值r_t和優(yōu)勢(shì)A_t代入clipped目標(biāo)構(gòu)造總的loss。把整批數(shù)據(jù)打亂用mini-batch SGD方式對(duì)loss做多輪優(yōu)化常見(jiàn)的是同一個(gè)batch上優(yōu)化3-4個(gè)epoch。訓(xùn)練完一批后把當(dāng)前策略快照作為新的π_old回到第1步繼續(xù)采樣收集新的數(shù)據(jù)。第4步是PPO和普通策略梯度最明顯的區(qū)別。普通策略梯度一般每批數(shù)據(jù)只做一次梯度更新因?yàn)橐徊礁绿镁捅?。而PPO因?yàn)橛衏lip機(jī)制保護(hù)同一個(gè)batch上多輪更新也不會(huì)讓策略跑飛太多數(shù)據(jù)利用效率明顯提高。3.2 三個(gè)loss拼起來(lái)的組合目標(biāo)實(shí)際工程里PPO的loss并不是只有clipped policy loss還包含值函數(shù)loss和熵正則lossL(θ) L^CLIP(θ) - c1 * L^VF(θ) c2 * H(π_θ(s))其中L^CLIP還是上面那個(gè)裁剪目標(biāo)負(fù)責(zé)優(yōu)化策略。L^VF一般是MSE讓值函數(shù)網(wǎng)絡(luò)去擬合回報(bào)目標(biāo)L^VF E[(V_θ(s_t) - V_target_t)^2]。H(π_θ(s))是當(dāng)前策略的熵加進(jìn)去是為了鼓勵(lì)探索防止策略過(guò)早收斂到某個(gè)確定性動(dòng)作。c2通常設(shè)為0.01太小不行太大策略會(huì)一直瞎轉(zhuǎn)。在很多實(shí)現(xiàn)里Actor和Critic會(huì)共享底層的特征提取網(wǎng)絡(luò)只有最后的輸出層分叉。這種情況下總loss里的policy項(xiàng)和value項(xiàng)會(huì)一起反傳到共享層要注意平衡一下兩者的梯度尺度。如果發(fā)現(xiàn)value loss比policy loss大太多共享層梯度會(huì)被值函數(shù)帶偏提前特征全都用于預(yù)測(cè)價(jià)值了。一個(gè)保險(xiǎn)做法是分開設(shè)置c1系數(shù)通常c10.5或1.0視loss量級(jí)調(diào)整。3.3 PyTorch風(fēng)格的核心代碼骨架下面是一個(gè)簡(jiǎn)化但結(jié)構(gòu)完整的PPO更新代碼片段不含環(huán)境交互細(xì)節(jié)重點(diǎn)看loss計(jì)算邏輯# policy_old和policy分別是舊策略快照和當(dāng)前策略 # buffer里存了batch的狀態(tài)、動(dòng)作、優(yōu)勢(shì)、回報(bào)目標(biāo) def compute_ppo_loss(policy, policy_old, buffer, epsilon0.2, c11.0, c20.01): # 取出batch數(shù)據(jù) states buffer.states actions buffer.actions advantages buffer.advantages v_targets buffer.value_targets # 當(dāng)前策略和舊策略分別算動(dòng)作log概率 log_probs policy.get_log_prob(states, actions) old_log_probs policy_old.get_log_prob(states, actions).detach() # importance ratio exp(log_prob - old_log_prob) ratios torch.exp(log_probs - old_log_probs) # clipped surrogate loss surr1 ratios * advantages surr2 torch.clamp(ratios, 1 - epsilon, 1 epsilon) * advantages policy_loss -torch.min(surr1, surr2).mean() # value loss value_pred policy.get_value(states) value_loss ((value_pred - v_targets) ** 2).mean() # entropy bonus entropy policy.get_entropy(states).mean() total_loss policy_loss c1 * value_loss - c2 * entropy return total_loss注意幾個(gè)細(xì)節(jié)old_log_probs一定要用detach()斷開梯度否則old策略本身也會(huì)被更新r_t算出來(lái)就錯(cuò)了。value_targets不要直接用當(dāng)前值函數(shù)輸出而是用GAE算出來(lái)的回報(bào)目標(biāo)。entropy符號(hào)是負(fù)的因?yàn)槲覀円畲蠡厮詌oss里要減。4. GAE讓優(yōu)勢(shì)估計(jì)不抖的黃金參數(shù)怎么選4.1 單步TD和蒙特卡洛的恩怨PPO的critic要輸出一個(gè)V(s)來(lái)估計(jì)狀態(tài)價(jià)值而advantage的估計(jì)方式直接決定了訓(xùn)練穩(wěn)定性。最簡(jiǎn)單的方式有兩種單步TDλ0A_t r_t γ*V(s_{t1}) - V(s_t)。方差小但偏差大因?yàn)閂函數(shù)本身不準(zhǔn)時(shí)單步估計(jì)的噪聲會(huì)被放大。蒙特卡洛λ1A_t Σ_{k0}^{∞} γ^k * r_{tk} - V(s_t)。偏差小但方差極大尤其任務(wù)步數(shù)很長(zhǎng)時(shí)后面累加的隨機(jī)性全都會(huì)注入到每一條樣本里。GAEGeneralized Advantage Estimation做的就是兩端的加權(quán)融合A_t^GAE Σ_{l0}^{∞} (γλ)^l * δ_{tl}其中δ_t r_t γ*V(s_{t1}) - V(s_t)就是單步TD誤差。λ把單步TD誤差向未來(lái)傳播λ為0時(shí)退化成單步TDλ為1時(shí)退化成蒙特卡洛。實(shí)際使用中λ取0.95是一個(gè)經(jīng)典配置在MuJoCo和大部分連續(xù)控制任務(wù)上穩(wěn)定性和方差控制都很好。λ越大優(yōu)勢(shì)估計(jì)越“長(zhǎng)遠(yuǎn)”但對(duì)于獎(jiǎng)勵(lì)稀疏的長(zhǎng)任務(wù)來(lái)說(shuō)λ接近1會(huì)帶來(lái)明顯方差增大這時(shí)候我會(huì)降到0.9左右。4.2 γ和λ的分工很多人混淆γ折扣因子和λ其實(shí)它們管的不是同一件事。γ決定的是“任務(wù)回報(bào)要考慮多遠(yuǎn)”本質(zhì)上是馬爾可夫決策過(guò)程層面的目標(biāo)定義λ決定的是“優(yōu)勢(shì)估計(jì)工具用多大窗口”是個(gè)純估計(jì)器層面的參數(shù)。舉例來(lái)說(shuō)一個(gè)任務(wù)設(shè)定γ0.99表示智能體要關(guān)心未來(lái)約100步內(nèi)的累計(jì)獎(jiǎng)勵(lì)。λ0.95則表示GAE在計(jì)算優(yōu)勢(shì)時(shí)實(shí)際使用的TD誤差傳播權(quán)重它不完全等價(jià)于γ但二者結(jié)合時(shí)有效的優(yōu)勢(shì)估計(jì)視界大概是1/(1-γλ)。知道這個(gè)換算關(guān)系后你可以有意識(shí)地調(diào)節(jié)這兩個(gè)參數(shù)的組合。4.3 advantage歸一化這個(gè)隱藏技巧我踩過(guò)最莫名其妙的一個(gè)坑是模型在某些batch里優(yōu)勢(shì)整體偏大因?yàn)槟且欢诬壽E里智能體碰上了異常高的獎(jiǎng)勵(lì)比如環(huán)境中不小心得到大量分?jǐn)?shù)導(dǎo)致clip的邊界對(duì)模型起不到限制作用整個(gè)batch梯度方向被csv到極端。解決辦法非常簡(jiǎn)單在每次訓(xùn)練前對(duì)當(dāng)前batch的advantage做一次標(biāo)準(zhǔn)化減均值除以標(biāo)準(zhǔn)差。advantages (advantages - advantages.mean()) / (advantages.std() 1e-8)這個(gè)操作本身不改變相對(duì)優(yōu)劣關(guān)系但能把劣勢(shì)和優(yōu)勢(shì)的分布拉回到對(duì)稱區(qū)間。原版PPO論文沒(méi)有強(qiáng)調(diào)這個(gè)trick但OpenAI的實(shí)現(xiàn)和很多成熟框架都默認(rèn)加上。你不做也行但在獎(jiǎng)勵(lì)尺度差異大的任務(wù)上訓(xùn)練曲線會(huì)明顯毛躁許多。5. 我把PPO跑崩了的幾個(gè)典型場(chǎng)景與調(diào)參救法5.1 訓(xùn)練到中途Loss一路飄到NaN這是連續(xù)控制任務(wù)里最常碰到的情況。原因通常是狀態(tài)或獎(jiǎng)勵(lì)尺度太大網(wǎng)絡(luò)輸出變成極大值導(dǎo)致梯度爆炸。常見(jiàn)場(chǎng)景某個(gè)環(huán)境中狀態(tài)的量級(jí)在幾百上千而動(dòng)作輸出只有[-1,1]網(wǎng)絡(luò)初始化時(shí)forward直接算出一個(gè)巨大對(duì)數(shù)概率比值指數(shù)爆炸。我的排查套路是這樣先在采樣時(shí)順手打印狀態(tài)和獎(jiǎng)勵(lì)的min/max發(fā)現(xiàn)問(wèn)題后給狀態(tài)做歸一化計(jì)算RunningMeanStd并標(biāo)準(zhǔn)化。PPO原論文附錄里專門提過(guò)這個(gè)做法我們?cè)诠こ躺蠋缀醣貍?。其次給訓(xùn)練加梯度裁剪max_norm0.5或1.0。最后如果策略網(wǎng)絡(luò)輸出的是高斯動(dòng)作分布記得給std設(shè)一個(gè)下限比如1e-4防止std收斂到接近0后log概率飛上天。5.2 策略收斂到單一動(dòng)作任務(wù)解不開了訓(xùn)練前期熵掉得特別快這通常是一個(gè)危險(xiǎn)的信號(hào)。模型為了盡快拿到眼前獎(jiǎng)勵(lì)會(huì)把動(dòng)作分布?jí)旱梅浅<怃J。這在獎(jiǎng)勵(lì)密集的任務(wù)里會(huì)形成惡性循環(huán)—策略一旦變確定采樣多樣性下降優(yōu)勢(shì)估計(jì)覆蓋面變窄模型再也探索不到更好的策略。治本的手段是提高entropy coef從默認(rèn)的0.01往上調(diào)到0.05甚至0.1。不過(guò)我后來(lái)更喜歡用的方法是entropy target設(shè)定一個(gè)目標(biāo)熵值比如連續(xù)動(dòng)作環(huán)境里設(shè)定目標(biāo)熵等于動(dòng)作維度的對(duì)數(shù)水平訓(xùn)練過(guò)程中每個(gè)epoch根據(jù)當(dāng)前熵和目標(biāo)之間的差距動(dòng)態(tài)調(diào)整c2系數(shù)這樣不會(huì)導(dǎo)致策略一直亂遛。如果你覺(jué)得實(shí)現(xiàn)麻煩先試固定0.01到0.02之間大多數(shù)任務(wù)夠用。5.3 優(yōu)勢(shì)歸一化沒(méi)做曲線毛刺嚴(yán)重如果你發(fā)現(xiàn)訓(xùn)練曲線像心電圖一樣每一批之間差距巨大先別急著加學(xué)習(xí)率。去檢查一下當(dāng)前batch的advantage是否被極端值綁架了。因?yàn)镻PO是on-policy算法每批數(shù)據(jù)都來(lái)自當(dāng)前策略如果這一批里恰好有幾步獎(jiǎng)勵(lì)爆高整個(gè)batch的優(yōu)勢(shì)均值可能被null對(duì)待原本不差的正常動(dòng)作看起來(lái)都是“差動(dòng)作”策略更新方向就歪了。做完advantage標(biāo)準(zhǔn)化之后至少曲線會(huì)平滑得多。我自己的實(shí)踐里還會(huì)配合使用reward clip把單步獎(jiǎng)勵(lì)截?cái)嗟絒-10,10]區(qū)間這看起來(lái)粗暴但對(duì)消除極端獎(jiǎng)勵(lì)影響很有效。注意別把獎(jiǎng)勵(lì)clip設(shè)成[0,1]否則區(qū)分度太差。5.4 同一個(gè)batch滾太多epoch策略過(guò)擬合到樣本噪聲PPO雖然允許在同一個(gè)batch上做多輪SGD但這不是讓你無(wú)限epoch。經(jīng)驗(yàn)上每個(gè)batch訓(xùn)練3-4個(gè)epoch比較常見(jiàn)超過(guò)這個(gè)值模型會(huì)對(duì)當(dāng)前批次數(shù)據(jù)“背答案”舊樣本的噪聲被反復(fù)放大新一輪采樣時(shí)策略表現(xiàn)反而變差。你可以觀察一條指標(biāo)clip_fraction也就是當(dāng)前batch里有多少比例樣本的r_t被clip到邊界。理想情況下clip_fraction應(yīng)該在0.1到0.3之間。如果占比太高說(shuō)明當(dāng)前batch上每輪更新都讓策略快速偏離要么降低epoch數(shù)要么調(diào)大ε要么降低學(xué)習(xí)率。6. 從實(shí)驗(yàn)代碼到能跑系統(tǒng)PPO工程落地的幾個(gè)細(xì)節(jié)6.1 并行采樣與mini-batch的節(jié)奏怎么搭理論課上講的PPO是“采樣一批更新多輪”但工程上采樣太慢會(huì)讓訓(xùn)練空轉(zhuǎn)。我建議至少準(zhǔn)備4到8個(gè)并行環(huán)境看CPU和任務(wù)復(fù)雜度一次采樣收集256到2048條transition然后按mini-batch size128到512切分。在MuJoCo這類視覺(jué)不做復(fù)雜渲染的任務(wù)上這個(gè)參數(shù)區(qū)間體驗(yàn)很好。在代碼結(jié)構(gòu)上有共享網(wǎng)絡(luò)Actor和Critic共用特征層和分離網(wǎng)絡(luò)兩種。共享網(wǎng)絡(luò)參數(shù)少、前向快但前文說(shuō)了容易互相干擾分離網(wǎng)絡(luò)更穩(wěn)但參數(shù)多一倍。我的建議是簡(jiǎn)單任務(wù)用共享網(wǎng)絡(luò)加c10.5復(fù)雜視覺(jué)任務(wù)用分離網(wǎng)絡(luò)。如果你要復(fù)現(xiàn)別人的任務(wù)先看它的network結(jié)構(gòu)別只抄loss公式抄一半。6.2 策略快照同步是on-policy的隱形門檻PPO是on-policy算法意味著訓(xùn)練時(shí)必須在“舊策略”采樣出的數(shù)據(jù)上更新。中途如果Actor的參數(shù)變了而采樣進(jìn)程還在跑那你采回來(lái)的數(shù)據(jù)跟當(dāng)前策略根本對(duì)不上算法退化成一個(gè)沒(méi)有意義的off-policy混合體。工程實(shí)現(xiàn)上一定保證訓(xùn)練用的每一條樣本必須有對(duì)應(yīng)的舊策略的log_prob和舊值函數(shù)輸出不能再現(xiàn)算。這也是為什么很多框架里會(huì)維護(hù)一個(gè)policy_old deepcopy(policy)每次rollout開始前先同步快照。我在自己做分布式版本的時(shí)候還在采樣端額外緩存了每個(gè)樣本對(duì)應(yīng)的old_log_prob哪怕之后程序出bug也能快速定位是不是快照同步出了問(wèn)題。6.3 訓(xùn)練結(jié)束后評(píng)估模型別指望一張曲線PPO訓(xùn)練過(guò)程中有大量隨機(jī)性seed不同結(jié)果可能差得遠(yuǎn)。因此評(píng)估模型時(shí)不要只看一次rollout的總回報(bào)建議固定幾個(gè)評(píng)測(cè)seed取平均和標(biāo)準(zhǔn)差。如果標(biāo)準(zhǔn)差太大說(shuō)明策略在狀態(tài)分布邊緣不穩(wěn)定還要再加熵或調(diào)整reward shaping。同理后期比較兩個(gè)變體時(shí)固定統(tǒng)一的環(huán)境seed和初始隨機(jī)種子不然你對(duì)比出來(lái)的提升可能都是噪聲。我自己習(xí)慣在訓(xùn)練日志里同時(shí)記錄總回報(bào)均值、熵值、clip_fraction、優(yōu)勢(shì)均值。這四個(gè)指標(biāo)能幫我快速判斷當(dāng)前訓(xùn)練有沒(méi)有病。熵值快速下降是過(guò)擬合到當(dāng)前策略的信號(hào)clip_fraction幾乎為零說(shuō)明更新限制沒(méi)起作用可以適當(dāng)調(diào)小ε優(yōu)勢(shì)均值長(zhǎng)期偏離零說(shuō)明值函數(shù)還沒(méi)跟上策略。PPO不是那種一勞永逸的算法但它確實(shí)是強(qiáng)化學(xué)習(xí)實(shí)踐里“最省心”的起點(diǎn)。先把它跑通再去想SAC、PPO的分布式變體或者因果強(qiáng)化學(xué)習(xí)那些更復(fù)雜的思路每一步都有實(shí)在的收益。你現(xiàn)在跑過(guò)的每一個(gè)坑都是在幫自己建立一套“算法感覺(jué)到不對(duì)勁”的直覺(jué)這比背下任何公式都有用。