Modelos y plataformas de IA
Optimización de Preferencias Directa: Una Guía Completa
Alinear los grandes modelos de lenguaje (LLM) con los valores y preferencias humanos es un desafío. Los métodos tradicionales, como el Aprendizaje de Refuerzo a partir de Retroalimentación Humana (RLHF), han sentado las bases al integrar las entradas humanas para refinar las salidas del modelo. Sin embargo, el RLHF puede ser complejo y exigente en términos de recursos, requiriendo una gran cantidad de poder computacional y procesamiento de datos. La Optimización de Preferencias Directa (DPO) emerge como un enfoque novedoso y más simplificado, ofreciendo una alternativa eficiente a estos métodos tradicionales. Al simplificar el proceso de optimización, la DPO no solo reduce la carga computacional sino que también mejora la capacidad del modelo para adaptarse rápidamente a las preferencias humanas
En esta guía, profundizaremos en la DPO, explorando sus fundamentos, implementación y aplicaciones prácticas.
La necesidad de alineación de preferencias
Para entender la DPO, es crucial comprender por qué alinear los LLM con las preferencias humanas es tan importante. A pesar de sus impresionantes capacidades, los LLM entrenados en vastos conjuntos de datos pueden producir salidas que son inconsistentes, sesgadas o no alineadas con los valores humanos. Esta falta de alineación puede manifestarse de diversas maneras:
- Generar contenido inseguro o perjudicial
- Proporcionar información inexacta o engañosa
- Exhibir sesgos presentes en los datos de entrenamiento
Para abordar estos problemas, los investigadores han desarrollado técnicas para ajustar los LLM utilizando la retroalimentación humana. El enfoque más prominente de estos ha sido el RLHF.
Entendiendo el RLHF: El precursor de la DPO
El Aprendizaje de Refuerzo a partir de Retroalimentación Humana (RLHF) ha sido el método principal para alinear los LLM con las preferencias humanas. Veamos el proceso del RLHF para entender sus complejidades:
a) Ajuste fino supervisado (SFT): El proceso comienza ajustando un LLM preentrenado en un conjunto de datos de respuestas de alta calidad. Este paso ayuda al modelo a generar salidas más relevantes y coherentes para la tarea objetivo.
b) Modelado de recompensa: Se entrena un modelo de recompensa separado para predecir las preferencias humanas. Esto implica:
- Generar pares de respuestas para prompts dados
- Hacer que los humanos califiquen qué respuesta prefieren
- Entrenar un modelo para predecir estas preferencias
c) Aprendizaje de refuerzo: El LLM ajustado se optimiza aún más utilizando aprendizaje de refuerzo. El modelo de recompensa proporciona retroalimentación, guiando al LLM para generar respuestas que se alineen con las preferencias humanas.
Aquí hay un pseudocódigo de Python simplificado para ilustrar el proceso del RLHF:
Aunque es efectivo, el RLHF tiene varias desventajas:
- Requiere entrenar y mantener múltiples modelos (SFT, modelo de recompensa y modelo optimizado con RL)
- El proceso de RL puede ser inestable y sensible a los hiperparámetros
- Es computacionalmente costoso, requiriendo muchas pasadas hacia adelante y hacia atrás a través de los modelos
Estas limitaciones han motivado la búsqueda de alternativas más simples y eficientes, lo que ha llevado al desarrollo de la DPO.
Optimización de Preferencias Directa: Conceptos básicos
Esta imagen contrasta dos enfoques distintos para alinear las salidas de los LLM con las preferencias humanas: Aprendizaje de Refuerzo a partir de Retroalimentación Humana (RLHF) y Optimización de Preferencias Directa (DPO). El RLHF se basa en un modelo de recompensa para guiar la política del modelo de lenguaje a través de bucles de retroalimentación iterativos, mientras que la DPO optimiza directamente las salidas del modelo para coincidir con las respuestas preferidas por los humanos utilizando datos de preferencia. Esta comparación destaca las fortalezas y posibles aplicaciones de cada método, proporcionando perspectivas sobre cómo los futuros LLM podrían ser entrenados para alinearse mejor con las expectativas humanas.
Ideas clave detrás de la DPO:
a) Modelado de recompensa implícito: La DPO elimina la necesidad de un modelo de recompensa separado al tratar al modelo de lenguaje en sí como una función de recompensa implícita.
b) Formulación basada en política: En lugar de optimizar una función de recompensa, la DPO optimiza directamente la política (modelo de lenguaje) para maximizar la probabilidad de respuestas preferidas.
c) Solución en forma cerrada: La DPO aprovecha una idea matemática que permite una solución en forma cerrada para la política óptima, evitando la necesidad de actualizaciones de RL iterativas.
Implementando la DPO: Un recorrido práctico por el código
La imagen a continuación muestra un fragmento de código que implementa la función de pérdida de la DPO utilizando PyTorch. Esta función desempeña un papel crucial en la refinación de cómo los modelos de lenguaje priorizan las salidas en función de las preferencias humanas. A continuación, se presenta un desglose de los componentes clave:
- Firma de la función: La función
dpo_losstoma varios parámetros, incluyendo logaritmos de probabilidades de la política (pi_logps), logaritmos de probabilidades del modelo de referencia (ref_logps) e índices que representan las completaciones preferidas y no preferidas (yw_idxs,yl_idxs). Además, un parámetrobetacontrola la fuerza de la penalización de divergencia de KL. - Extracción de logaritmos de probabilidades: El código extrae los logaritmos de probabilidades para las completaciones preferidas y no preferidas de ambos el modelo de política y el modelo de referencia.
- Cálculo de la relación logarítmica: Se calcula la diferencia entre los logaritmos de probabilidades para las completaciones preferidas y no preferidas para ambos el modelo de política y el modelo de referencia. Esta relación es crucial para determinar la dirección y magnitud de la optimización.
- Cálculo de la pérdida y la recompensa: La pérdida se calcula utilizando la función
logsigmoid, mientras que las recompensas se determinan escalando la diferencia entre los logaritmos de probabilidades del modelo de política y el modelo de referencia porbeta.
Sumérjamonos en las matemáticas detrás de la DPO para entender cómo logra estos objetivos.
Las matemáticas de la DPO
La DPO es una reformulación astuta del problema de aprendizaje de preferencias. A continuación, se presenta un desglose paso a paso:
a) Punto de partida: Maximización de recompensa con restricción de KL
El objetivo original del RLHF se puede expresar como:
- πθ es la política (modelo de lenguaje) que estamos optimizando
- r(x,y) es la función de recompensa
- πref es una política de referencia (generalmente el modelo SFT inicial)
- β controla la fuerza de la restricción de divergencia de KL
b) Forma de política óptima: Se puede demostrar que la política óptima para este objetivo tiene la forma:
π_r(y|x) = 1/Z(x) * πref(y|x) * exp(1/β * r(x,y))Donde Z(x) es una constante de normalización.
c) Dualidad recompensa-política: La idea clave de la DPO es expresar la función de recompensa en términos de la política óptima:
r(x,y) = β * log(π_r(y|x) / πref(y|x)) + β * log(Z(x))d) Modelo de preferencia Asumiendo que las preferencias siguen el modelo de Bradley-Terry, se puede expresar la probabilidad de preferir y1 sobre y2 como:
p*(y1 ≻ y2 | x) = σ(r*(x,y1) - r*(x,y2))Donde σ es la función logística.
e) Objetivo de la DPO Sustituyendo nuestra dualidad recompensa-política en el modelo de preferencia, llegamos al objetivo de la DPO:
L_DPO(πθ; πref) = -E_(x,y_w,y_l)~D [log σ(β * log(πθ(y_w|x) / πref(y_w|x)) - β * log(πθ(y_l|x) / πref(y_l|x)))]Este objetivo se puede optimizar utilizando técnicas de descenso de gradiente estándar, sin la necesidad de algoritmos de RL.
Implementando la DPO
Ahora que entendemos la teoría detrás de la DPO, veamos cómo implementarla en la práctica. Utilizaremos Python y PyTorch para este ejemplo:
import torch
import torch.nn.functional as F
<p>class DPOTrainer:
def __init__(self, model, ref_model, beta=0.1, lr=1e-5):
self.model = model
self.ref_model = ref_model
self.beta = beta
self.optimizer = torch.optim.AdamW(self.model.parameters(), lr=lr)</p>
<p>def compute_loss(self, pi_logps, ref_logps, yw_idxs, yl_idxs):
"""
pi_logps: logaritmos de probabilidades de la política, forma (B,)
ref_logps: logaritmos de probabilidades del modelo de referencia, forma (B,)
yw_idxs: índices de completaciones preferidas en [0, B-1], forma (T,)
yl_idxs: índices de completaciones no preferidas en [0, B-1], forma (T,)
beta: temperatura que controla la fuerza de la penalización de KL</p>
<p>Cada par de (yw_idxs[i], yl_idxs[i]) representa los índices de un par de preferencia único.
"""</p>
<p># Extraer logaritmos de probabilidades para las completaciones preferidas y no preferidas
pi_yw_logps, pi_yl_logps = pi_logps[yw_idxs], pi_logps[yl_idxs]
ref_yw_logps, ref_yl_logps = ref_logps[yw_idxs], ref_logps[yl_idxs]</p>
<p># Calcular logaritmos de razones
pi_logratios = pi_yw_logps - pi_yl_logps
ref_logratios = ref_yw_logps - ref_yl_logps</p>
<p># Computar la pérdida de la DPO
losses = -F.logsigmoid(self.beta * (pi_logratios - ref_logratios))
rewards = self.beta * (pi_logps - ref_logps).detach()</p>
return losses.mean(), rewards
<p>def train_step(self, batch):
x, yw_idxs, yl_idxs = batch
self.optimizer.zero_grad()</p>
<p># Computar logaritmos de probabilidades para el modelo y el modelo de referencia
pi_logps = self.model(x).log_softmax(-1)
ref_logps = self.ref_model(x).log_softmax(-1)</p>
<p># Computar la pérdida
loss, _ = self.compute_loss(pi_logps, ref_logps, yw_idxs, yl_idxs)
loss.backward()
self.optimizer.step()</p>
return loss.item()
<p># Uso
model = TuModeloDeLenguaje() # Inicializa tu modelo
ref_model = TuModeloDeLenguaje() # Carga el modelo de referencia preentrenado
trainer = DPOTrainer(model, ref_model)</p>
<p>for batch in dataloader:
loss = trainer.train_step(batch)
print(f"Pérdida: {loss}")
Desafíos y direcciones futuras
Aunque la DPO ofrece ventajas significativas sobre los enfoques tradicionales de RLHF, todavía existen desafíos y áreas para investigación adicional:
a) Escalabilidad a modelos más grandes:
A medida que los modelos de lenguaje siguen creciendo en tamaño, aplicar eficientemente la DPO a modelos con cientos de miles de millones de parámetros sigue siendo un desafío abierto. Los investigadores están explorando técnicas como:
- Métodos de ajuste fino eficientes (por ejemplo, LoRA, ajuste de prefijo)
- Optimizaciones de entrenamiento distribuido
- Puntos de control de gradiente y entrenamiento de precisión mixta
Ejemplo de uso de LoRA con DPO:
<p>from peft import LoraConfig, get_peft_model</p> <p>class DPOTrainerWithLoRA(DPOTrainer): def __init__(self, model, ref_model, beta=0.1, lr=1e-5, lora_rank=8): lora_config = LoraConfig( r=lora_rank, lora_alpha=32, target_modules=["q_proj", "v_proj"], lora_dropout=0.05, bias="none", task_type="CAUSAL_LM" ) self.model = get_peft_model(model, lora_config) self.ref_model = ref_model self.beta = beta self.optimizer = torch.optim.AdamW(self.model.parameters(), lr=lr)</p> <p># Uso base_model = TuGranModeloDeLenguaje() dpo_trainer = DPOTrainerWithLoRA(base_model, ref_model)
b) Adaptación multi-tarea y de pocos disparos:
Desarrollar técnicas de DPO que puedan adaptarse eficientemente a nuevas tareas o dominios con datos de preferencia limitados es un área activa de investigación. Se están explorando enfoques como:
- Marcos de aprendizaje de meta para adaptación rápida
- Ajuste fino basado en prompts para DPO
- Aprendizaje de transferencia desde modelos de preferencia generales a dominios específicos
c) Manejo de preferencias ambiguas o conflictivas:
Los datos de preferencia del mundo real a menudo contienen ambigüedades o conflictos. Mejorar la robustez de la DPO ante tales datos es crucial. Soluciones potenciales incluyen:
- Modelado de preferencia probabilístico
- Aprendizaje activo para resolver ambigüedades
- Agregación de preferencia multi-agente
Ejemplo de modelado de preferencia probabilístico:
<p>class ProbabilisticDPOTrainer(DPOTrainer): def compute_loss(self, pi_logps, ref_logps, yw_idxs, yl_idxs, preference_prob): # Computar logaritmos de razones pi_yw_logps, pi_yl_logps = pi_logps[yw_idxs], pi_logps[yl_idxs] ref_yw_logps, ref_yl_logps = ref_logps[yw_idxs], ref_logps[yl_idxs]</p> <p>log_ratio_diff = pi_yw_logps.sum(-1) - pi_yl_logps.sum(-1) loss = -(preference_prob * F.logsigmoid(self.beta * log_ratio_diff) + (1 - preference_prob) * F.logsigmoid(-self.beta * log_ratio_diff)) return loss.mean()</p> <p># Uso trainer = ProbabilisticDPOTrainer(model, ref_model) loss = trainer.compute_loss(pi_logps, ref_logps, yw_idxs, yl_idxs, preference_prob=0.8) # 80% de confianza en la preferencia
d) Combinación de la DPO con otras técnicas de alineación:
Integrar la DPO con otros enfoques de alineación podría conducir a sistemas más robustos y capaces:
- Principios de IA constitucional para satisfacción explícita de restricciones
- Debate y modelado de recompensa recursivo para la elicación compleja de preferencias
- Aprendizaje de refuerzo inverso para inferir funciones de recompensa subyacentes
Ejemplo de combinación de la DPO con IA constitucional:
<p>class ConstitutionalDPOTrainer(DPOTrainer): def __init__(self, model, ref_model, beta=0.1, lr=1e-5, constraints=None): super().__init__(model, ref_model, beta, lr) self.constraints = constraints or []</p> <p>def compute_loss(self, pi_logps, ref_logps, yw_idxs, yl_idxs): base_loss = super().compute_loss(pi_logps, ref_logps, yw_idxs, yl_idxs)</p> <p>constraint_loss = 0 for constraint in self.constraints: constraint_loss += constraint(self.model, pi_logps, ref_logps, yw_idxs, yl_idxs)</p> return base_loss + constraint_loss <p># Uso def safety_constraint(model, pi_logps, ref_logps, yw_idxs, yl_idxs): # Implementar lógica de verificación de seguridad unsafe_score = compute_unsafe_score(model, pi_logps, ref_logps) return torch.relu(unsafe_score - 0.5) # Penalizar si la puntuación de seguridad > 0.5</p> <p>constraints = [safety_constraint] trainer = ConstitutionalDPOTrainer(model, ref_model, constraints=constraints)</p>
Consideraciones prácticas y mejores prácticas
Al implementar la DPO para aplicaciones del mundo real, considere los siguientes consejos:
a) Calidad de los datos: La calidad de tus datos de preferencia es crucial. Asegúrate de que tu conjunto de datos:
- Cubra una amplia gama de entradas y comportamientos deseados
- Tenga anotaciones de preferencia consistentes y confiables
- Equilibre diferentes tipos de preferencias (por ejemplo, factualidad, seguridad, estilo)
b) Ajuste de hiperparámetros: Aunque la DPO tiene menos hiperparámetros que el RLHF, el ajuste es aún importante:
- β (beta): Controla el equilibrio entre la satisfacción de la preferencia y la divergencia del modelo de referencia. Comienza con valores alrededor de 0.1-0.5.
- Tasa de aprendizaje: Utiliza una tasa de aprendizaje más baja que la de ajuste fino estándar, generalmente en el rango de 1e-6 a 1e-5.
- Tamaño del lote: Los tamaños de lote más grandes (32-128) suelen funcionar bien para el aprendizaje de preferencias.
c) Refinamiento iterativo: La DPO se puede aplicar de manera iterativa:
- Entrena un modelo inicial utilizando la DPO
- Genera nuevas respuestas utilizando el modelo entrenado
- Recopila nuevos datos de preferencia sobre estas respuestas
- Vuelve a entrenar utilizando el conjunto de datos expandido
Esta imagen muestra el rendimiento de los LLM como GPT-4 en comparación con los juicios humanos en varias técnicas de entrenamiento, incluyendo la Optimización de Preferencias Directa (DPO), Ajuste Fino Supervisado (SFT) y Optimización de Política Proximal (PPO). La tabla revela que las salidas de GPT-4 están cada vez más alineadas con las preferencias humanas, especialmente en tareas de resumen. El nivel de acuerdo entre GPT-4 y los evaluadores humanos demuestra la capacidad del modelo para generar contenido que resuena con los evaluadores humanos, casi tan cercanamente como el contenido generado por humanos.
Casos de estudio y aplicaciones
Para ilustrar la efectividad de la DPO, veamos algunas aplicaciones y variantes del mundo real:
- DPO iterativa: Desarrollada por Snorkel (2023), esta variante combina muestreo de rechazo con la DPO, permitiendo un proceso de selección de datos de entrenamiento más refinado. Al iterar sobre varias rondas de muestreo de preferencias, el modelo puede generalizar mejor y evitar sobreajustarse a preferencias ruidosas o sesgadas.
- IPO (Optimización de Preferencia Iterativa): Presentada por Azar et al. (2023), el IPO agrega un término de regularización para prevenir el sobreajuste, un problema común en la optimización basada en preferencias. Esta extensión permite a los modelos mantener un equilibrio entre adherirse a las preferencias y preservar las capacidades de generalización.
- KTO (Optimización de Transferencia de Conocimiento): Una variante más reciente de Ethayarajh et al. (2023), el KTO prescinde de las preferencias binarias por completo. En su lugar, se centra en transferir conocimiento desde un modelo de referencia al modelo de política, optimizando para una alineación más suave y consistente con los valores humanos.
- DPO multi-modal para aprendizaje trans-dominio por Xu et al. (2024): Un enfoque donde la DPO se aplica a través de diferentes modalidades—texto, imagen y audio—demostrando su versatilidad para alinear modelos con preferencias humanas en una variedad de tipos de datos. Esta investigación destaca el potencial de la DPO en la creación de sistemas de IA más comprehensivos capaces de manejar tareas complejas y multi-modales.
















