練的優(yōu)勢崩潰與GDPO解法)
周五上午九點的技術(shù)分享我差不多復(fù)盤了整整一個周末。題目是“GDPO 與 GRPO 在多獎勵 RL 訓(xùn)練中的優(yōu)勢崩潰問題”原本只是團(tuán)隊內(nèi)部例會的一個議題結(jié)果討論得太深大家干脆拉了個線上旁聽頻道。會后不少朋友私信我把思路整理成文這便有了這一篇。先說結(jié)論GRPO 在多獎勵multi-reward場景下出現(xiàn)的“優(yōu)勢崩潰”advantage collapse不是調(diào)幾個權(quán)重就能糊弄過去的簡單 bug而是優(yōu)勢估計機(jī)制與獎勵拼接方式之間的結(jié)構(gòu)性沖突。GDPO 這類把優(yōu)勢按獎勵維度先分解、再動態(tài)融合的方法是目前我在實踐中驗證過最穩(wěn)定、也最好解釋的解法之一。這篇文章會從原理、復(fù)現(xiàn)、解法、參數(shù)配置到邊界條件把整條鏈路完整展開。1. 從多獎勵訓(xùn)練說起GRPO 的優(yōu)點與它的“暗坑”1.1 GRPO 為什么能省下 critic組內(nèi)相對優(yōu)勢的原理先快速對齊一下 GRPO 的基本邏輯。GRPO 最早出現(xiàn)在開源推理模型相關(guān)的強(qiáng)化學(xué)習(xí)論文里核心動機(jī)是省掉 PPO 中那個與策略模型同等規(guī)模的價值網(wǎng)絡(luò)critic。PPO 的優(yōu)勢函數(shù)通常寫成A returns - V(s)也就是用“實際回報”減去“價值網(wǎng)絡(luò)預(yù)測的期望回報”差值就是某個動作比預(yù)期好多少或差多少。可價值網(wǎng)絡(luò)本身訓(xùn)練起來又慢又貴存儲和推理開銷也不小。GRPO 換了一條路同一個 prompt 下采樣一組groupresponse然后直接在這組 response 內(nèi)部做歸一化。假設(shè)某組有 n 條 response獎勵分別是 r1 到 rn那么第 i 條 response 的優(yōu)勢是A_i (r_i - mean(r_group)) / std(r_group)這個公式的意思是我們不關(guān)心絕對分?jǐn)?shù)只看這組兄弟里誰相對更好。省掉 critic 的前提是“組內(nèi)相對排序能替代絕對值”這在單個獎勵信號、且采樣組內(nèi)方差適中的情況下效果確實很好。省顯存、省訓(xùn)練時間還避免了價值網(wǎng)絡(luò)偏差對策略更新的污染。1.2 多獎勵拼接的誘惑與隱患三個保證的連環(huán)崩當(dāng)訓(xùn)練目標(biāo)從單一獎勵變成多獎勵——例如格式獎勵、正確答案獎勵、安全性獎勵、風(fēng)格對齊獎勵同時存在——最常見、最省事的做法就是線性加權(quán)求和R_total w1 * r1 w2 * r2 w3 * r3 ...接著再對 R_total 做組內(nèi)歸一化得到優(yōu)勢。很多團(tuán)隊一開始都會走這條路畢竟代碼改動最小。但問題恰恰出在這里。多獎勵拼接會破壞 GRPO 正常工作的三個隱含保證。第一個保證是“同一組內(nèi)獎勵差異主要由模型的真實改進(jìn)驅(qū)動”??啥鄠€獎勵同時存在時組內(nèi)差異可能來自某個獎勵的固有噪聲而噪聲恰恰主導(dǎo)了排序。第二個保證是“獎勵的量綱和方差在一個數(shù)量級”?,F(xiàn)實中根本不是這樣——格式獎勵通常是 0/1 的二值信號正確答案獎勵可能是一個 0 到 1 的連續(xù)分但極端值很多風(fēng)格獎勵可能是模型打出的 0 到 5 的分?jǐn)?shù)。方差一差就是好幾倍。第三個保證是“所有獎勵與策略改進(jìn)是同方向的”。多獎勵之間經(jīng)常相互制約例如“格式正確但答案錯誤”和“答案正確但格式錯誤”這兩類樣本在組內(nèi)的排序會被完全不同的維度支配。當(dāng)這三個保證被破壞組內(nèi)歸一化就變得不穩(wěn)定。于是GRPO 在多獎勵場景下的“優(yōu)勢崩潰”出現(xiàn)了。2. 親手復(fù)現(xiàn)一次“優(yōu)勢崩潰”現(xiàn)象、腳本與訓(xùn)練日志2.1 復(fù)現(xiàn)設(shè)置兩個獎勵通道的極端對照我說“崩潰”之前最好先有可復(fù)盤的證據(jù)。我這邊在內(nèi)部做了一次極簡復(fù)現(xiàn)實驗任務(wù)是一個帶格式約束的數(shù)學(xué)問答獎勵只保留兩路——格式分format二值判定和答案正確分correct逐步評分0到1。訓(xùn)練配置如下模型一個 7B 量級的開源底座每 prompt 組大小8獎勵加權(quán)w_format1.0w_correct1.0訓(xùn)練步長每批 128 個 prompts優(yōu)化器與學(xué)習(xí)率AdamWlr5e-6采樣溫度0.8表面上看權(quán)重比例是 1:1非常合理。但在訓(xùn)練到大約 300 步左右時我發(fā)現(xiàn)幾個關(guān)鍵指標(biāo)開始出現(xiàn)明顯異常。當(dāng)時第一反應(yīng)不是“崩潰”而是“怎么收益曲線長這樣”。2.2 崩潰的三階段特征曲線與權(quán)重診斷把訓(xùn)練日志拉出來優(yōu)勢崩潰基本會經(jīng)歷三個階段。第一階段初期正常平均優(yōu)勢值大致在 0.5 到 1.0 之間策略熵也在緩慢下降。此時格式獎勵還處于“多數(shù)樣本能拿到 0/1、偶爾有極端值”的狀態(tài)correct 獎勵則顯得平滑。第二階段大概在 200 步之后模型快速學(xué)會了“把格式搞對”format 獎勵的組內(nèi)方差急劇下降???format 獎勵仍帶著 1.0 的權(quán)重參與求和所以 R_total 的組內(nèi)差異就只剩下 correct 那一路在貢獻(xiàn)。此時公式分母 std(R_total) 如果校正不足某些組里所有 response 的 correct 分都很接近優(yōu)勢值會整體坍縮到 0 周圍的窄帶。策略梯度幾乎失去方向loss 看起來在走平實際是訓(xùn)練在空轉(zhuǎn)。第三階段一旦組內(nèi)出現(xiàn)一個“格式對但答案全錯”的離群樣本它的獎勵會被極端放大。我見過單個樣本的優(yōu)勢值瞬間跳高到 8 倍標(biāo)準(zhǔn)差以上隨后策略猛地把對正確性的權(quán)重降下來開始往回抽風(fēng)。訓(xùn)練日志里最直接的體現(xiàn)是advantage_std 從約 0.6 突然飆升到 4.0 以上然后 KL 項劇烈震蕩回答分布開始兩極分化。我用一個排查腳本把每個獎勵通道的歸一化貢獻(xiàn)單獨打出來可以說是證據(jù)確鑿stats {} for rew_name in reward_names: r train_batch[rew_name] # shape: [batch_size, group_size] stats[f{rew_name}_mean] r.mean().item() stats[f{rew_name}_std] r.std().item() stats[f{rew_name}_rel_gain] (r.max(dim-1).values - r.min(dim-1).values).mean().item() print(stats)結(jié)果顯示format 通道的rel_gain從 0.9 掉到 0.05幾乎不再提供排序信息而 correct 通道的rel_gain仍然在 0.5 上下??捎捎谇蠛秃笤贇w一化format 那一把“死掉的權(quán)重”還是掛在總獎勵里拉低了有效信號的信噪比。2.3 關(guān)于崩潰的判定給幾個務(wù)實的檢驗方法以后你遇到訓(xùn)練曲線異常不要憑感覺說“崩了”。我這邊總結(jié)出三個可靠判定方式。第一個是看“組內(nèi)優(yōu)勢分布”的形狀。正常 GRPO 的優(yōu)勢分布近似對稱、單峰標(biāo)準(zhǔn)差穩(wěn)定在 0.3 到 1.5 之間崩潰時會出現(xiàn)明顯的雙峰或重尾標(biāo)準(zhǔn)差劇烈波動。第二個是單樣本優(yōu)勢與最終回報的散點關(guān)系。如果單樣本優(yōu)勢高、但它所在的組內(nèi)總獎勵并不高說明優(yōu)勢空間里混入了和真實目標(biāo)不一致的排序。第三個是分獎勵維度的“組內(nèi)相對增益”變化。上面那個腳本已經(jīng)寫了因為它是按 channel 統(tǒng)計的。如果一個獎勵通道的相對增益持續(xù)走低優(yōu)勢矩陣主要由另一個通道驅(qū)動而混合優(yōu)勢仍是按原權(quán)重算出來的那么崩潰只是時間問題。3. GDPO 的核心解法按獎勵維度分離優(yōu)勢再動態(tài)融合3.1 第一刀將總獎勵拆成獨立優(yōu)勢通道GDPO 的做法用一句話說就是不先去加總獎勵而是讓每一個獎勵維度都單獨經(jīng)歷一次組內(nèi)歸一化得到各自的“優(yōu)勢分量”A_i^jm (r_i^jm - mean(r^jm_group)) / std(r^jm_group)這樣做的理由很直接每個獎勵維度先在自己的坐標(biāo)系里對齊量綱影響被清除了。格式獎勵即使組內(nèi)差異很小它的優(yōu)勢也只反映“通過格式而拉開差距的部分”不會被其他維度的噪聲淹沒。之后才是融合。但 GDPO 的融合不是固定權(quán)重外掛一個超參而是設(shè)計成動態(tài)權(quán)重。基礎(chǔ)形式可以寫成A_i_final sum_j w_j * A_i^j其中 w_j 的更新往往和每個獎勵通道的“有效信噪比”掛鉤而不是由我們手動固定。我在第一次實驗里就把這個改動套了上去訓(xùn)練很快穩(wěn)定下來。關(guān)鍵是即使 format 通道的組內(nèi)方差變小它的 w_j 會自動下調(diào)原來掛在總獎勵里的“死權(quán)重”被丟掉了。3.2 第二刀動態(tài)權(quán)重與方差保護(hù)機(jī)制動態(tài)權(quán)重的具體計算方法我見過兩種比較實用的路線。一種基于最近一段訓(xùn)練窗口內(nèi)的通道方差估計。比如維護(hù)一個指數(shù)滑動平均EMA對每個通道的優(yōu)勢標(biāo)準(zhǔn)差做統(tǒng)計ema_std {name: 1.0 for name in reward_names} alpha 0.05 for name in reward_names: cur_std batch_advantages[name].std().item() ema_std[name] (1 - alpha) * ema_std[name] alpha * cur_std inv_var {name: 1.0 / (ema_std[name] 1e-4) for name in reward_names} softmax_w softmax(inv_var, temperature0.5)核心直覺是優(yōu)勢方差越大的通道包含的排序信息可能更多理應(yīng)獲得更高權(quán)重優(yōu)勢方差趨于零的通道則表示這個信號已經(jīng)飽和權(quán)重自動下調(diào)。但要注意直接用原始方差做 softmax 也會有問題——一個離群樣本會把整條通道的方差拉高權(quán)重的波動也隨之劇烈。所以對原始方差做 EMA 平滑是必要的溫度系數(shù)也需要單獨調(diào)。另一種路線是對每個通道的動態(tài)權(quán)重做“下限保護(hù)和歸一化”所有通道權(quán)重保持在 0.1 到 0.5 之間防止某個通道權(quán)重歸零后策略完全無視某類約束。這個下限保護(hù)在實踐中對安全性獎勵尤其重要。3.3 近端約束讓策略更新重新安全只有優(yōu)勢重標(biāo)定還不夠。GRPO 組的更新本質(zhì)上是策略梯度近端約束clip決定了單步更新幅度上限。多獎勵場景下由于不同優(yōu)勢通道的尺度已經(jīng)被重標(biāo)定clip 的語義也要與原來不同。經(jīng)典 PPO clip 的做法是對概率比做截斷ratio_i π_new(x_i) / π_old(x_i) loss_i -min(ratio_i * A_i, clip(ratio_i, 1-ε, 1ε) * A_i)GDPO 在這部分的實踐是對優(yōu)勢做分解后還要把 clip 范圍與優(yōu)勢分布的標(biāo)準(zhǔn)差做聯(lián)動。我這邊常用的一種做法是當(dāng)某個通道的組內(nèi)優(yōu)勢標(biāo)準(zhǔn)差超過閾值比如 2.0時強(qiáng)制對該通道的優(yōu)勢做裁剪到 [-c, c]max_adv 2.0 clipped_adv torch.clamp(A_i_j, -max_adv, max_adv)這個操作的直觀理解是即便某一批數(shù)據(jù)里出現(xiàn)了極端優(yōu)勢也不允許它單槍匹馬把模型參數(shù)推得太遠(yuǎn)??棺∵@一步策略更新就市場穩(wěn)定很多。4. 落地訓(xùn)練時的完整配置與穩(wěn)定參數(shù)4.1 可復(fù)制的訓(xùn)練配置骨架理論講清楚后關(guān)鍵在于能復(fù)現(xiàn)。下面是一個經(jīng)過驗證的 GDPO 風(fēng)格訓(xùn)練配置骨架基于我這邊常駐的多獎勵強(qiáng)化學(xué)習(xí)訓(xùn)練框架。它不綁定具體代碼庫但核心邏輯是通用的。{ group_size: 8, reward_mode: decompose_and_dynamic_weight, reward_weights_ema_alpha: 0.05, reward_weight_temperature: 0.5, reward_weight_min: 0.1, reward_weight_max: 0.5, advantage_clip: 2.0, policy_clip_epsilon: 0.2, kl_target: 0.05, learning_rate: 5e-6, warmup_steps: 100, batch_size_prompts: 128 }配置里有個細(xì)節(jié)值得說清楚reward_weight_temperature直接控制動態(tài)權(quán)重的平滑程度。溫度越高權(quán)重越接近均勻溫度越低權(quán)重越極端。前期我建議溫度高一點比如 0.7讓各路獎勵先雨露均沾等訓(xùn)練進(jìn)入中段模型對各路信號相對穩(wěn)定后再把溫度降到 0.3 到 0.5。4.2 關(guān)鍵超參的調(diào)法和我踩過的坑最坑的一個參數(shù)是advantage_clip。我一開始設(shè)成 3.0覺得“反正優(yōu)勢分布正常情況下不會超太多clip 留足余量”。結(jié)果訓(xùn)練到 500 步左右format 通道方差變小correct 通道又出現(xiàn)高離群值優(yōu)勢被推到 3.0 上限多次觸發(fā)。策略確實沒有大幅震蕩但 KL 一直壓不下來。后來我改成 2.0同時把動態(tài)權(quán)重的 EMA 窗口拉大問題立刻緩解。經(jīng)驗是clip 值寧可偏小也不要偏大因為分解后的優(yōu)勢通道各不相同之后再融合時多通道的峰值效應(yīng)可能疊加。另一個容易踩的坑是獎勵通道之間的刷新頻率不同步。比如 correct 獎勵由一個規(guī)則判定器產(chǎn)生格式獎勵由模板判定器產(chǎn)生它們的計算延遲不一樣。如果你的 reward 信息是異步到達(dá)的那在做組內(nèi)歸一化時不同通道會站在不同的數(shù)據(jù)窗口上統(tǒng)計口徑不一致會直接污染優(yōu)勢估計。我們的做法是讓所有通道先同步到同一個 recent buffer再進(jìn)行統(tǒng)計。4.3 多獎勵信號的分析工具訓(xùn)練穩(wěn)定后我并不只看整體 reward 均值。我會同時跟蹤四個指標(biāo)per-channel 組內(nèi)相對增益判斷每個通道是否還在提供有效排序信息per-channel 權(quán)重的 EMA判斷動態(tài)權(quán)重是否合理收斂優(yōu)勢分布的標(biāo)準(zhǔn)差與峰度判斷是否重新出現(xiàn)崩潰前兆每條 response 在最終優(yōu)勢中的“主導(dǎo)通道標(biāo)簽”判斷策略當(dāng)前主要被誰牽著走我習(xí)慣在訓(xùn)練日志里加一行主導(dǎo)通道統(tǒng)計dominant torch.argmax(torch.stack(advs_per_channel, dim-1), dim-1) dominant_channel_counts torch.bincount(dominant.flatten(), minlengthlen(reward_names))如果訓(xùn)練后期“主導(dǎo)通道”長期只有某一個而其他通道的權(quán)重也一直偏低那說明模型正在過度擬合單一獎勵下一步就要考慮給其他通道加約束或補(bǔ)充新樣本了。5. GDPO 的邊界在哪里什么情況下依然需要保守方案5.1 獎勵器本身相關(guān)時分解也可能失靈GDPO 不是銀彈。最明顯的邊界是多個獎勵器高度相關(guān)的時候按通道分解并不能真正“去重”。舉個例子如果一個獎勵器是另一個獎勵器的線性變換或者說兩個獎勵器都基于同一套特征模型給出分?jǐn)?shù)那么它們各自的組內(nèi)優(yōu)勢會高度共線。動態(tài)權(quán)重即使能調(diào)也只是在重復(fù)強(qiáng)調(diào)同一個信息源。此時模型容易在表面指標(biāo)上刷高分實際上并沒有學(xué)到更本質(zhì)的規(guī)律。我遇到過一個典型案例格式獎勵與相關(guān)性獎勵都由同一個打分器產(chǎn)出相關(guān)性分?jǐn)?shù)越高格式分?jǐn)?shù)也越高兩者共線度超過了 0.85。用 GDPO 跑雖然不會出現(xiàn)優(yōu)勢崩潰但訓(xùn)練收斂后的輸出多樣性極差。最后這個場景不得不退回“單獎勵”或“獎勵降維”先把冗余通道去掉再訓(xùn)練。5.2 折中方案混合模式與漸進(jìn)式獎勵接管還有一類情況獎勵通道中等相關(guān)且方向大體一致。此時完全分解會丟掉通道間的共享信息完全拼接又可能崩潰。折中方案是采用混合模式——前半段用拼接獎勵做粗對齊后半段切換為 GDPO 式分解。這個順序有講究訓(xùn)練早期模型還在學(xué)習(xí)基礎(chǔ)行為通道間共享信息多一點反而有幫助訓(xùn)練后期需要精細(xì)化優(yōu)化分解和動態(tài)權(quán)重才能保住各獎勵維度的獨立性?!皾u進(jìn)式獎勵接管”是另一個實用技巧。不要一開始就把所有獎勵都接入訓(xùn)練先只開一個最重要的通道比如“答案正確率”跑幾百步讓模型先學(xué)會主干行為再逐步加入格式、風(fēng)格、安全性通道。每新增一個通道都觀察優(yōu)勢分布 48 小時左右確認(rèn)穩(wěn)定后再加下一步。這在多目標(biāo) RL 工程上屬于最穩(wěn)妥的迭代策略。我在一套實際項目里正是用“先單通道、后多通道、再切換分解融合”的節(jié)奏把原本一加多獎勵就崩的訓(xùn)練曲線穩(wěn)定收斂到了 KL 與正確率雙達(dá)標(biāo)的水平。整個過程沒有什么靈丹妙藥就是反復(fù)驗證優(yōu)勢分布、動態(tài)權(quán)重、clip 邊界的相互作用。最后分享一個我個人的習(xí)慣不管用什么算法訓(xùn)練日志里一定要把 per-channel 的優(yōu)勢統(tǒng)計放進(jìn)可視化面板而不是只看總獎勵。優(yōu)勢崩潰這種事等到總獎勵曲線難看的時候再排查往往已經(jīng)浪費了好幾天算力。把這個維度提前亮出來很多問題在萌芽階段就能被看到——這比任何花哨的新算法都更值得投入精力。