Direct Preference Optimization
Se vi siete mai chiesti come fanno i vari ChatGPT, Claude eccetera a rispondere in modo sensato e, soprattutto, a non insultarvi ogni due per tre, allora siete nel posto giusto. Perché dietro c’è spesso un processo chiamato Reinforcement Learning from Human Feedback (RLHF), ovvero “Apprendimento per Rinforzo con Feedback Umano”. Sembra complicato, e in effetti lo è, ma cercherò di spiegarvelo senza farvi venire un’aneurisma.
RLHF
Immaginate di voler insegnare a un cane a fare il riporto. Come fate? Gli lanciate la pallina, se ve la riporta gli date un biscottino e gli dite “bravo!”. Se invece scappa col la pallina e se la va a sotterrare in giardino, lo sgridate (o magari tirate giù un porco, dipende da quanto siete incazzati). Ecco, l’RLHF è un po’ la stessa cosa, ma invece del cane abbiamo un modello linguistico gigante e invece dei biscottini e delle ciabatte abbiamo dei ricompense e delle penalità (in gergo tecnico si chiamano reward e punishment, ma siamo tra amici, quindi diciamo ricompense e penalità).
Il processo di RLHF, in parole povere, funziona così:
Fase 1: Supervised Fine-Tuning - SFT: Si parte da un modello linguistico pre-addestrato (tipo GPT, per intenderci). Questo modello è stato addestrato su una quantità di testo immane presa da internet, quindi sa già un sacco di cose, ma è un po’ come un adolescente: sa tante cose teoriche, ma poi nella pratica fa un casino. Quindi, in questa fase, gli si fa fare un po’ di pratica con esempi specifici, tipo “rispondi a questa domanda in modo conciso”, “scrivi un riassunto di questo testo”, eccetera. È come dargli dei compiti a casa, insomma. Questa fase si chiama Supervised Fine-Tuning (SFT), ovvero “Messa a Punto Supervisionata” (che schifo i nomi tradotti in italiano). Fin qui, tutto abbastanza facile.
Fase 2: Addestramento del Modello di Ricompensa (Reward Modeling - RM): Qui inizia il casino. Perché per usare l’apprendimento per rinforzo, abbiamo bisogno di una cosa fondamentale: un modello di ricompensa. Ma che cazzo è ’sto modello di ricompensa? È un altro modello (sì, un altro, perché le cose semplici non ci piacciono) che impara a valutare quanto è “buona” una risposta generata dal modello linguistico. “Buona” in che senso? Nel senso che è utile, pertinente, non offensiva, non tossica, eccetera eccetera. Insomma, tutte quelle cose che vogliamo da un chatbot che non sia un troll di internet.
Per addestrare questo benedetto modello di ricompensa, abbiamo bisogno di dati di preferenza umana. UMANA, mi piace come suona. UMANA. Cosa vuol dire UMANA? Vuol dire che dobbiamo far valutare a delle persone vere (i cosiddetti “annotatori umani”, in Kenya o in India di solito) delle coppie di risposte generate dal modello linguistico. Tipo, gli si fa vedere due risposte diverse alla stessa domanda e gli si chiede: “Quale di queste due risposte ti piace di più?”. E l’annotatore umano deve scegliere: “Quetta qui!”. Dopo aver raccolto un bel po’ di ’ste coppie di preferenze, si addestra il modello di ricompensa a predire queste preferenze. In pratica, il modello di ricompensa impara a dire: “Ah, questa risposta è meglio di quest’altra perché è più [… qualcosa]”.
Matematicamente, il modello di ricompensa spesso si basa sul modello di Bradley-Terry. E voi chiederete: che cazzo è il modello di Bradley-Terry? È un modello statistico che serve per modellare le probabilità di vittoria in competizioni a coppie. Immagina di fare un torneo di braccio di ferro. Il modello di Bradley-Terry cerca di capire, date le prestazioni passate dei partecipanti, qual è la probabilità che Tizio batta Caio. Nel nostro caso, la “competizione” è tra due risposte generate dal modello linguistico, e il “vincitore” è la risposta preferita dall’annotatore umano.
Se indichiamo con \(r_\theta(x, y)\) il punteggio (non normalizzato) che il modello di ricompensa \(\theta\) assegna alla risposta \(y\) data la domanda \(x\), allora il modello di Bradley-Terry dice che la probabilità che la risposta \(y_1\) sia preferita alla risposta \(y_2\) è data da:
\[P(y_1 \succ y_2 | x) = \sigma(r_\theta(x, y_1) - r_\theta(x, y_2))\]
dove \(\sigma(z) = \frac{1}{1 + e^{-z}}\) è la funzione sigmoide, che serve a schiacciare i valori tra 0 e 1, in modo da ottenere una probabilità. In pratica, più la differenza tra i punteggi \(r_\theta(x, y_1)\) e \(r_\theta(x, y_2)\) è grande, più è probabile che \(y_1\) sia preferita a \(y_2\). E viceversa. Il modello di ricompensa \(\theta\) viene addestrato per massimizzare la probabilità di predire correttamente le preferenze umane sui dati di addestramento.
Fase 3: Ottimizzazione della Politica con Apprendimento per Rinforzo (Reinforcement Learning Policy Optimization): Finalmente, arriviamo alla parte “rinforzo”. Ora che abbiamo ‘sto modello di ricompensa che ci dice quanto sono buone le risposte, possiamo usarlo per “guidare” il modello linguistico a generare risposte sempre migliori. Come? Usando un algoritmo di apprendimento per rinforzo, tipo Proximal Policy Optimization (PPO). PPO è un algoritmo un po’ complicato (non ci addentriamo nei dettagli, se no non ne usciamo più), ma l’idea di base è questa: si cerca di modificare il modello linguistico in modo da aumentare la ricompensa media ottenuta, senza però allontanarsi troppo dal modello linguistico originale (quello SFT). È come cercare di migliorare il cane nel riporto, ma senza fargli dimenticare tutto quello che ha imparato prima.
In questa fase, si definisce una funzione obiettivo che cerca di massimizzare la ricompensa, ma anche di mantenere il modello linguistico “vicino” a quello SFT. Una funzione obiettivo tipica per RLHF è tipo questa:
\[J_{RLHF}(\pi_\phi) = \mathbb{E}_{(x, y) \sim D_\pi} [r_\theta(x, y) - \beta \cdot KL(\pi_\phi(y|x) || \pi_{SFT}(y|x))]\]
Dove:
- \(\pi_\phi\) è la politica (policy) del modello linguistico che stiamo ottimizzando (parametri \(\phi\)). In pratica, è il modello linguistico stesso.
- \(D_\pi\) è la distribuzione dei dati generati dalla politica \(\pi_\phi\).
- \(r_\theta(x, y)\) è la ricompensa predetta dal modello di ricompensa \(\theta\) per la risposta \(y\) data la domanda \(x\).
- \(KL(\pi_\phi(y|x) || \pi_{SFT}(y|x))\) è la divergenza di Kullback-Leibler (KL) tra la politica attuale \(\pi_\phi\) e la politica SFT \(\pi_{SFT}\). La divergenza KL quantifica quanto sono diverse due distribuzioni di probabilità. In questo contesto, penalizza le politiche \(\pi_\phi\) che si discostano troppo da \(\pi_{SFT}\). Anche se spesso si semplifica dicendo che è una “misura della distanza” tra distribuzioni, tecnicamente non è una distanza vera e propria poiché non rispetta la simmetria (e quindi la commutatività) né la disuguaglianza triangolare. È più corretto considerarla una misura di “dissimilarità”: più è alta, più le due distribuzioni sono diverse.
- \(\beta\) è un iperparametro che controlla quanto vogliamo penalizzare l’allontanamento dalla politica SFT.
In pratica, stiamo dicendo: “Vogliamo che il modello linguistico generi risposte che ottengono una ricompensa alta dal modello di ricompensa, ma non vogliamo che si discosti troppo dal modo in cui rispondeva prima (quello SFT)”. È un compromesso tra migliorare la qualità delle risposte e mantenere una certa coerenza con il modello originale.
Problemi dell’RLHF:
Tutto figo, no? Sì, sulla carta. Ma l’RLHF ha un sacco di problemi, tipo:
- Complessità: Sono tre fasi separate, ognuna con i suoi casini.
- Instabilità: L’addestramento con RL è notoriamente instabile. Può succedere che la politica impazzisca e che la ricompensa parta in quinta.
- Costo: Raccogliere dati di preferenza umana costa un sacco di soldi e tempo.
- Subottimalità: Anche se tutto va bene, l’RLHF non è detto che trovi la politica ottimale. Perché? Perché stiamo ottimizzando una funzione obiettivo surrogata (quella roba di prima \(J_{RLHF}\)), che non è detto che corrisponda esattamente a quello che vogliamo veramente (ovvero, un chatbot che risponde bene).
Insomma, l’RLHF è un po’ come costruire un castello di carte: figo, ma rischia di crollare al primo soffio di vento.
DPO: La Figata che Semplifica Tutto (O Quasi)
Ed è qui che entra in gioco il Direct Preference Optimization (DPO). Il DPO è una figata perché elimina la necessità di addestrare esplicitamente un modello di ricompensa. Avete capito bene: niente più modello di ricompensa, niente più fase 2 dell’RLHF. Solo fase 1 (SFT) e poi si passa direttamente alla fase di ottimizzazione, ma in modo molto più semplice e diretto.
Come fa ’sta magia il DPO? Sfrutta una proprietà matematica del modello di Bradley-Terry. Si può dimostrare che la funzione obiettivo dell’RLHF (quella \(J_{RLHF}\) di prima) può essere riscritta in una forma molto più semplice, che dipende solo dalle preferenze umane e non dal modello di ricompensa.
In pratica, invece di massimizzare la ricompensa predetta dal modello di ricompensa, il DPO massimizza direttamente la probabilità di generare la risposta preferita, date le coppie di preferenze umane. La funzione obiettivo del DPO è questa:
\[J_{DPO}(\pi_\phi) = \mathbb{E}_{(x, y_w, y_l) \sim D_{pref}} [\log \sigma( \beta \log \frac{\pi_\phi(y_w|x)}{\pi_\phi(y_l|x)} )]\]
Dove:
- \((x, y_w, y_l)\) è una tripla di dati di preferenza: \(x\) è la domanda, \(y_w\) è la risposta preferita (“winner”), \(y_l\) è la risposta non preferita (“loser”).
- \(D_{pref}\) è il dataset di preferenze umane.
- \(\pi_\phi\) è la politica del modello linguistico che stiamo ottimizzando.
- \(\sigma(z) = \frac{1}{1 + e^{-z}}\) è la funzione sigmoide.
- \(\beta\) è un iperparametro (come prima).
Ma che cazzo significa ’sta roba? Significa che stiamo cercando di aumentare la probabilità di generare la risposta preferita (\(y_w\)) rispetto alla risposta non preferita (\(y_l\)), per ogni coppia di preferenze nel dataset \(D_{pref}\). E lo facciamo in modo “diretto”, senza passare per il modello di ricompensa. La funzione logaritmo e la sigmoide servono solo a rendere l’ottimizzazione più stabile e a controllare quanto vogliamo spingere per la risposta preferita.
Vantaggi del DPO:
- Semplicità: Molto più semplice dell’RLHF. Niente modello di ricompensa da addestrare, solo una funzione obiettivo da ottimizzare direttamente.
- Stabilità: Più stabile dell’RLHF. L’ottimizzazione è più diretta e meno soggetta a instabilità.
- Efficienza: Più efficiente dell’RLHF. Meno modelli da addestrare, meno risorse computazionali richieste.
- Performance comparabili (o migliori) all’RLHF: In molti casi, il DPO ottiene performance simili o addirittura migliori dell’RLHF, pur essendo molto più semplice.
Limiti
Ovviamente, anche il DPO non è la cura di tutti i mali. Ha anche lui, ahimé, i suoi limiti:
- Dipendenza dai dati di preferenza: Il DPO funziona bene solo se abbiamo dati di preferenza umana di alta qualità e in quantità sufficiente. Se i dati di preferenza sono di scarsa qualità, anche il chatbot addestrato con DPO sarà di scarsa qualità. “Garbage in, garbage out”, come dicono gli americani.
- Iperparametri: Anche il DPO ha i suoi iperparametri da sintonizzare (tipo \(\beta\)). Sintonizzare gli iperparametri può essere un casino, soprattutto perché non è detto che esista un valore ottimo per tutto il dataset.
- Non è una soluzione magica: Il DPO è un miglioramento rispetto all’RLHF, ma non risolve tutti i problemi dell’allineamento dei modelli linguistici. Ci sono ancora un sacco di sfide aperte, tipo come garantire che i chatbot siano veramente sicuri, affidabili, etici, eccetera eccetera.
Insomma, il DPO è una figata ma c’è ancora un sacco di lavoro da fare.
Quindi
Il Direct Preference Optimization (DPO) è una tecnica nuova e promettente per addestrare modelli linguistici che siano allineati con le preferenze umane. È più semplice, stabile ed efficiente dell’RLHF, e ottiene performance comparabili o migliori. Il DPO sta aprendo nuove possibilità per lo sviluppo di chatbot più fighi e accessibili a tutti.
La prossima volta che sentirete parlare di DPO, pensate a ’sta spiegazione (spero) non troppo incasinata, e ricordatevi che dietro ai chatbot che usate tutti i giorni c’è un sacco di matematica, sudore e, a volte, anche qualche parolaccia. E se qualcuno vi chiede “Ma che cazzo è ’sto DPO?” (per qualsiasi motivo questa cosa sia uscita durante una conversazione), mandategli questo articolo!