GDPO: NVIDIA risolve il "Reward Collapse" di GRPO nel Multi-Reward RL
GDPO è una nuova tecnica di ottimizzazione per il Multi-reward RL che risolve il "reward collapse" di GRPO, fornendo segnali di addestramento più ricchi e precisi.

In GDPO: Group reward-Decoupled Normalization Policy Optimization for Multi-reward RL Optimization, i ricercatori di NVIDIA e partner accademici affrontano un limite critico del popolare algoritmo GRPO quando applicato a scenari con ricompense multiple (es. correttezza + formato + sicurezza).
Il paper dimostra che il GRPO tradizionale, sommando le ricompense prima della normalizzazione, causa un fenomeno definito "reward normalization collapse": combinazioni diverse di punteggi possono risultare nello stesso valore di advantage, appiattendo il segnale di apprendimento. GDPO risolve questo problema disaccoppiando la normalizzazione: ogni ricompensa viene normalizzata indipendentemente rispetto al gruppo (group-wise) prima di essere aggregata. Questo semplice cambiamento di design migliora drasticamente la convergenza e le performance su task complessi come il tool calling, il ragionamento matematico e la generazione di codice, senza richiedere risorse computazionali aggiuntive significative.
Qui puoi trovare i vari link di riferimento ufficiali:
- Code: https://github.com/NVlabs/GDPO
- Paper: https://arxiv.org/abs/2601.05242
- Project Page: https://nvlabs.github.io/GDPO/
GDPO Obiettivi di ricerca
-
Perché il GRPO fallisce negli scenari Multi-reward? Il GRPO aggrega (somma) tutte le ricompense diverse (es.
reward_formatereward_accuracy) in un unico scalare prima di calcolare la media e deviazione standard del gruppo. Questo causa una perdita di informazioni: scenari in cui il modello soddisfa entrambi gli obiettivi possono generare lo stesso advantage normalizzato di scenari in cui ne soddisfa solo uno parzialmente, riducendo l'efficacia del gradiente propagato (insomma, crea rumore). -
Come fa GDPO a garantire segnali di addestramento più precisi? GDPO inverte l'ordine delle operazioni: calcola la normalizzazione (z-score) per ogni specifica ricompensa all'interno del gruppo di generazioni, e solo dopo aggrega i risultati ponderati. Questo preserva le differenze relative per ogni obiettivo, garantendo che un output che soddisfa tutti i criteri riceva un segnale di rinforzo distintamente più alto.
-
GDPO è computazionalmente più oneroso di GRPO? No. L'overhead computazionale introdotto dalla normalizzazione separata è trascurabile rispetto al costo dell'inferenza e della backpropagation del modello. Può essere integrato nelle pipeline esistenti modificando poche righe di codice.
GDPO: Cosa ne pensa Mauro?
- Novelty: 4/5. L'identificazione del problema del "reward collapse" nel GRPO è un'intuizione sottile ma fondamentale. Sebbene la soluzione tecnica (normalizzare prima di sommare) possa sembrare semplice, l'impatto teorico e pratico sulla stabilità del Multi-reward RL è significativo.
- Clarity: 4/5. Il paper spiega il problema con esempi numerici cristallini (mostrando come vettori di reward diversi collassano nello stesso scalare con GRPO). La visualizzazione del problema tramite vettori di advantage rende il concetto accessibile anche a chi non ha fatto Analisi 2.
- Reproducibility: 5/5. Il codice è stato rilasciato come open source ed è progettato per essere un "drop-in replacement" (sostituzione diretta) nelle librerie popolari come
TRL. Gli autori forniscono script per replicare gli esperimenti. - Affordability: 2.5/5. RL resta sempre dispendioso, ma a differenza di molti paper moderni che richiedono cluster massivi, GDPO è stato validato con setup pressochè gestibili (1.5B - 7B parametri). Gli autori dichiarano che gli esperimenti possono essere replicati su una singola GPU A100 in circa 2.5 ore, o in meno di un'ora su 8xA100, rendendo la ricerca accessibile a singoli sviluppatori e piccoli laboratori.
GDPO: Metodi e tecniche
Il cuore del paper risiede nella modifica del calcolo dell'Advantage.
Il problema di GRPO (Standard)
Nel GRPO classico, per un prompt , il modello genera un gruppo di output . Se abbiamo diverse funzioni di ricompensa , il GRPO calcola prima la ricompensa totale sommata:
Successivamente, normalizza questo scalare totale rispetto alla media e deviazione standard del gruppo:
Il paper dimostra che vettori di reward molto diversi (es. [0, 1] vs [0, 2]) possono risultare in valori identici dopo questa operazione.
La soluzione GDPO
GDPO propone di calcolare l'advantage per ogni singola ricompensa separatamente:
E solo successivamente combinare gli advantage normalizzati:
Infine, viene applicata una normalizzazione finale a livello di batch per stabilità.
PyTorch Implementation (Pseudo-code)
Ecco come appare l'implementazione logica, basata sul codice rilasciato per la libreria TRL:
import torch
def gdpo_advantage_computation(rewards_per_func, reward_weights, num_generations):
"""
rewards_per_func: Tensor [batch_size, num_rewards]
Ogni riga rappresenta i reward grezzi per una generazione.
"""
all_reward_advantages = []
# 1. Decoupled Normalization (Ciclo sui diversi tipi di reward)
for i, weight in enumerate(reward_weights):
# Estrai i reward specifici per l'obiettivo 'i'
reward_i = rewards_per_func[:, i]
# Reshape per calcolare statistiche di gruppo (Group-wise)
# [batch_size] -> [num_prompts, num_generations]
reward_i_grouped = reward_i.view(-1, num_generations)
# Calcola mean e std per gruppo
mean_grouped = reward_i_grouped.mean(dim=1, keepdim=True)
std_grouped = reward_i_grouped.std(dim=1, keepdim=True)
# Espandi per matchare le dimensioni originali
mean_broadcast = mean_grouped.repeat_interleave(num_generations, dim=0).flatten()
std_broadcast = std_grouped.repeat_interleave(num_generations, dim=0).flatten()
# Calcola Advantage per questo specifico reward
adv_i = (reward_i - mean_broadcast) / (std_broadcast + 1e-4)
all_reward_advantages.append(adv_i)
# 2. Aggregazione Ponderata
# Stack degli advantage: [batch_size, num_rewards]
combined_advantages = torch.stack(all_reward_advantages, dim=1)
# Somma ponderata (Weighted Sum)
# pre_bn_advantages: [batch_size]
pre_bn_advantages = (combined_advantages * reward_weights.unsqueeze(0)).sum(dim=1)
# 3. Batch-wise Normalization (Opzionale ma raccomandata per stabilità)
final_mean = pre_bn_advantages.mean()
final_std = pre_bn_advantages.std()
final_advantages = (pre_bn_advantages - final_mean) / (final_std + 1e-4)
return final_advantages
GDPO: Dataset
Il paper valida la tecnica su tre domini principali che richiedono il bilanciamento di obiettivi multipli (es. correttezza vs lunghezza vs formato):
- Tool Calling: Utilizza modelli della famiglia Qwen2.5-Instruct. L'obiettivo è generare chiamate a funzioni corrette (correctness reward) rispettando un formato JSON rigoroso (format reward).
- Math Reasoning: Utilizza dataset di ragionamento matematico (tipicamente varianti di GSM8K o MATH, riferiti nel paper come task per raggiungere l'"aha moment"). Qui le ricompense multiple includono la correttezza della risposta finale, il formato del ragionamento (chain-of-thought) e vincoli sui numeri interi.
- Coding & Length Constraints: Esperimenti con DeepSeek-R1 per generare codice o risposte che non solo siano corrette, ma rispettino vincoli di brevità (conciseness), dimostrando che GDPO gestisce meglio il trade-off tra accuratezza e verbosità.
GDPO: Licenze
Il codice GDPO rilasciato da NVLabs (NVIDIA) su GitHub segue licenza Apache 2.0.