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