Concepto clave
La comparación entre RLHF (Reinforcement Learning from Human Feedback) y DPO (Direct Preference Optimization) representa un cambio fundamental en cómo ajustamos modelos de lenguaje. Imagina que RLHF es como entrenar a un atleta con un equipo completo de entrenadores, nutricionistas y fisioterapeutas: es poderoso pero complejo y costoso. DPO, en cambio, es como tener un entrenador personalizado que optimiza directamente los movimientos clave: más eficiente, menos pasos intermedios.
RLHF funciona en tres fases: primero entrenas un modelo de recompensa con preferencias humanas, luego usas aprendizaje por refuerzo (como PPO) para optimizar el modelo principal, y finalmente ajustas con regularización. DPO elimina el modelo de recompensa y el bucle de RL, reformulando el problema como una optimización directa donde el modelo aprende a preferir respuestas ganadoras sobre perdedoras mediante una función de pérdida matemáticamente equivalente pero computacionalmente más simple.
"DPO no es solo una simplificación de RLHF, es una reformulación teórica que evita la inestabilidad del RL manteniendo la capacidad de alineación." - Investigación original de DPO, 2023
Cómo funciona en la práctica
Veamos un ejemplo paso a paso con datos concretos. Supongamos que tenemos un dataset de preferencias con 1000 pares (respuesta preferida, respuesta rechazada) para consultas sobre programación Python.
Paso 1: Preparación de datos
- Dataset: 1000 ejemplos en formato JSON
- Cada ejemplo: {"query": "¿Cómo ordenar una lista en Python?", "chosen": "Puedes usar sorted(lista) o lista.sort()", "rejected": "Utiliza el método ordenar()"}
- Preprocesamiento: Tokenización con el mismo tokenizer del modelo base
Paso 2: Configuración DPO vs RLHF
| Aspecto | RLHF | DPO |
|---|---|---|
| Componentes | Modelo base + Modelo recompensa + Optimizador RL | Solo modelo base |
| Hiperparámetros clave | Tasa aprendizaje RL: 1e-6, β KL: 0.1 | β DPO: 0.1, Tasa aprendizaje: 5e-5 |
| Memoria GPU | ~3x modelo base (2 modelos + buffers) | ~1.5x modelo base |
| Tiempo entrenamiento | 20-30 horas para 1000 ejemplos | 5-8 horas para 1000 ejemplos |
Paso 3: Implementación concreta
Con DPO, la función de pérdida se implementa así en pseudocódigo:
def dpo_loss(policy_chosen_logps, policy_rejected_logps, reference_chosen_logps, reference_rejected_logps, beta):
log_ratios = (policy_chosen_logps - reference_chosen_logps) - (policy_rejected_logps - reference_rejected_logps)
losses = -F.logsigmoid(beta * log_ratios)
return losses.mean()Caso de estudio
Proyecto: Ajuste de Llama-3-8B para respuestas técnicas en español
Objetivo: Mejorar la precisión y claridad en explicaciones de machine learning
Dataset: 2,500 pares de preferencias de Stack Overflow en español etiquetados por expertos
Comparación RLHF vs DPO:
| Métrica | RLHF (PPO) | DPO | Mejora |
|---|---|---|---|
| Exactitud humana | 78% | 82% | +4% |
| Diversidad léxica | 0.65 | 0.72 | +10.8% |
| KL vs referencia | 2.1 bits | 1.8 bits | -14.3% |
| Horas entrenamiento | 42h | 15h | -64% |
| Memoria pico | 48GB | 24GB | -50% |
Análisis: DPO logró mejor rendimiento con menos recursos porque evita la inestabilidad del PPO y la aproximación del modelo de recompensa. La divergencia KL más baja indica que DPO mantiene mejor las capacidades del modelo base mientras se alinea con preferencias.
Errores comunes
- Beta mal configurado: Usar β=1.0 cuando debería ser 0.1-0.5. Esto causa sobreajuste o subajuste. Solución: Hacer sweep en [0.01, 0.1, 0.5, 1.0] con 100 ejemplos de validación.
- Dataset desbalanceado: Preferencias sesgadas hacia cierto tipo de respuestas. Solución: Analizar distribución de características (longitud, tono, complejidad) y balancear.
- No guardar checkpoints: DPO puede diverger después de ciertas épocas. Solución: Guardar checkpoint cada 25% del entrenamiento y evaluar con métricas automáticas.
- Ignorar el modelo de referencia: Usar referencia incorrecta o no congelada. Solución: Siempre usar el modelo base preentrenado como referencia congelada.
- Batch size muy pequeño: Menos de 4 ejemplos por batch causa estimaciones ruidosas del gradiente. Solución: Usar al menos batch size 8, acumular gradientes si hay limitación de memoria.
Checklist de dominio
- ✓ Entiendo la equivalencia matemática entre la función objetivo de RLHF y DPO
- ✓ Puedo calcular manualmente la pérdida DPO para un par de respuestas
- ✓ Sé configurar β óptimo para mi dataset específico
- ✓ Implementé pipeline completo de DPO con evaluación automática
- ✓ Comparé resultados RLHF vs DPO en al menos un proyecto real
- ✓ Identifico cuándo usar DPO (datos limitados, recursos limitados) vs RLHF (máxima calidad, recursos abundantes)
- ✓ Debuggeo problemas comunes de entrenamiento DPO (divergencia, sobreajuste)
Implementación comparativa RLHF vs DPO en dataset real
Objetivo
Implementar y comparar RLHF y DPO en un dataset de preferencias real, midiendo rendimiento y complejidad.
Materiales necesarios
- Acceso a GPU con al menos 16GB VRAM
- Python 3.9+, PyTorch 2.0+
- Dataset: HuggingFace "Anthropic/hh-rlhf" (subset español)
- Modelo base: "meta-llama/Llama-3.1-8B" (o similar)
Pasos detallados
- Preparación del entorno:
Instala transformers, trl, peft y datasets. Crea entorno virtual con requirements.txt. - Preprocesamiento de datos:
Carga 1000 ejemplos del dataset. Divide en 800 entrenamiento/200 validación. Tokeniza con el tokenizer de Llama. - Implementación DPO:
Configura DPO Trainer con β=0.1, learning_rate=5e-5, batch_size=8. Entrena por 3 épocas. Guarda checkpoints y métricas cada 100 steps. - Implementación RLHF (baseline):
Usa el mismo modelo base. Entrena modelo de recompensa con los mismos datos (2 épocas). Configura PPO con KL penalty=0.1, learning_rate=1e-6. Entrena por 1000 steps. - Evaluación comparativa:
Para ambos modelos ajustados: a) Mide exactitud en set de validación (preferencias humanas), b) Calcula perplexity en 100 ejemplos aleatorios, c) Mide tiempo y memoria de entrenamiento, d) Evalúa con métrica automática (BERTScore). - Análisis de resultados:
Crea tabla comparativa. Identifica trade-offs. Documenta conclusiones sobre cuándo preferir cada método.
Entrega esperada
Script Python completo, logs de entrenamiento, tabla de resultados, y análisis de 1 página con recomendaciones prácticas.
Pistas- Para el modelo de recompensa en RLHF, usa una cabeza de clasificación simple sobre el último hidden state
- En DPO, monitorea la diferencia entre logprobabilidades de chosen vs rejected - si se hace muy grande, reduce β
- Usa gradient accumulation si tienes limitación de memoria, especialmente en RLHF
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.