Phase 09 - Lesson 08
Proximal Policy Optimization (PPO)
This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.
A2C descarta cada rollout después de una actualización. PPO envuelve el gradiente de la política en una relación de importancia recortada (clipped importance ratio) para que puedas hacer más de 10 épocas con los mismos datos sin que la política explote. Schulman et al. (2017). Sigue siendo el algoritmo de gradiente de política por defecto en 2026.
Tipo: Build Idiomas: Python Prerrequisitos: Phase 9 · 06 (REINFORCE), Phase 9 · 07 (Actor-Critic) Tiempo: ~75 minutos
El Problema
A2C (Lección 07) es on-policy: el gradiente E_{π_θ}[A · ∇ log π_θ] requiere datos muestreados de la π_θ actual. Realiza una actualización y π_θ cambiará; los datos que utilizaste ahora son off-policy. Reutilízalos y tu gradiente estará sesgado.
Los rollouts son costosos. En Atari, un solo rollout en 8 envs × 128 pasos = 1024 transiciones y una docena de segundos de tiempo de entorno. Descartar eso después de un solo paso de gradiente es un desperdicio.
La optimización de política por región de confianza (Trust Region Policy Optimization - TRPO, Schulman 2015) fue la primera solución: restringir cada actualización para que la divergencia KL entre la política vieja y la nueva permanezca por debajo de δ. Teóricamente limpio, pero requiere resolver un gradiente conjugado por actualización. Nadie ejecuta TRPO en 2026.
PPO (Schulman et al. 2017) reemplaza la restricción estricta de la región de confianza con un objetivo recortado simple. Una línea de código adicional. Diez épocas por rollout. Sin gradientes conjugados. Garantías teóricas lo suficientemente buenas. Nueve años después, sigue siendo el algoritmo de gradiente de política predeterminado para todo, desde MuJoCo hasta RLHF.
El Concepto
La relación de importancia.
r_t(θ) = π_θ(a_t | s_t) / π_{θ_old}(a_t | s_t)
Esta es la relación de verosimilitud (likelihood ratio) de la nueva política frente a la política que recopiló los datos. r_t = 1 significa que no hay cambios. r_t = 2 significa que la nueva política tiene el doble de probabilidades de tomar a_t que la anterior.
El sustituto recortado (clipped surrogate).
L^{CLIP}(θ) = E_t [ min( r_t(θ) A_t, clip(r_t(θ), 1-ε, 1+ε) A_t ) ]
Dos términos:
- Si la ventaja
A_t > 0y la relación intenta crecer más allá de1 + ε, el recorte (clip) aplana el gradiente: no empujes una buena acción más allá de+εpor encima de la probabilidad anterior. - Si la ventaja
A_t < 0y la relación intenta crecer más allá de1 - ε(lo que significa que haríamos una mala acción más probable en comparación con su reducción recortada), el recorte limita el gradiente: no empujes una mala acción por debajo de-ε.
El min maneja la otra dirección: si la relación se ha movido en la dirección beneficiosa, aún obtienes el gradiente (sin recorte en el lado que te perjudicaría).
ε = 0.2 típico. Grafica el objetivo en función de r_t: una función lineal a trozos con un techo plano en el "lado bueno" y un piso plano en el "lado malo".
La pérdida completa de PPO.
L(θ, φ) = L^{CLIP}(θ) - c_v · (V_φ(s_t) - V_t^{target})² + c_e · H(π_θ(·|s_t))
Misma estructura de actor-critic que A2C. Tres coeficientes, generalmente c_v = 0.5, c_e = 0.01, ε = 0.2.
El bucle de entrenamiento.
- Recopila
N × Ttransiciones enNentornos paralelos duranteTpasos cada uno. - Calcula las ventajas (GAE), congélalas como constantes.
- Congela
π_{θ_old}como una captura (snapshot) de laπ_θactual. - Para
Képocas, para cada minibatch de(s, a, A, V_target, log π_old(a|s)):- Calcula
r_t(θ) = exp(log π_θ(a|s) - log π_old(a|s)). - Aplica
L^{CLIP}+ pérdida de valor + entropía. - Paso de gradiente.
- Calcula
- Descarta el rollout. Regresa al paso 1.
K = 10 y minibatches de 64 es un conjunto estándar de hiperparámetros. PPO es robusto: los números exactos rara vez importan dentro de un rango de ±50%.
Variante de penalización KL. El artículo original propuso una alternativa utilizando una penalización KL adaptativa: L = L^{PG} - β · KL(π_θ || π_old) con β ajustado en función del KL observado. La versión recortada se volvió dominante; la variante KL sobrevive en RLHF (donde la KL con respecto a la política de referencia es una restricción independiente que siempre se desea de todos modos).
Desarrollándolo (Build It)
Paso 1: capturar log π_old(a | s) en el momento del rollout
for step in range(T):
probs = softmax(logits(theta, state_features(s)))
a = sample(probs, rng)
s_next, r, done = env.step(s, a)
buffer.append({
"s": s, "a": a, "r": r, "done": done,
"v_old": value(w, state_features(s)),
"log_pi_old": log(probs[a] + 1e-12),
})
s = s_next
La captura se realiza una vez, en el momento del rollout. No cambia durante las épocas de actualización.
Paso 2: calcular las ventajas GAE (Lección 07)
Igual que A2C. Normalizar en todo el lote (batch).
Paso 3: actualización del sustituto recortado (clipped surrogate)
for _ in range(K_EPOCHS):
for mb in minibatches(buffer, size=64):
for rec in mb:
x = state_features(rec["s"])
probs = softmax(logits(theta, x))
logp = log(probs[rec["a"]] + 1e-12)
ratio = exp(logp - rec["log_pi_old"])
adv = rec["advantage"]
surrogate = min(
ratio * adv,
clamp(ratio, 1 - EPS, 1 + EPS) * adv,
)
# backprop -surrogate, add value loss, subtract entropy
grad_logpi = onehot(rec["a"]) - probs
if (adv > 0 and ratio >= 1 + EPS) or (adv < 0 and ratio <= 1 - EPS):
pg_grad = 0.0 # clipped
else:
pg_grad = ratio * adv
for i in range(N_ACTIONS):
for j in range(N_FEAT):
theta[i][j] += LR * pg_grad * grad_logpi[i] * x[j]
El patrón "recortado → gradiente cero" es el corazón de PPO. Si la nueva política ya se ha desviado demasiado en la dirección beneficiosa, la actualización se detiene.
Paso 4: valor y entropía
Agrega MSE estándar al objetivo del crítico y una bonificación de entropía en el actor, igual que A2C.
Paso 5: diagnósticos
Tres cosas a monitorear en cada actualización:
- KL medio (Mean KL)
E[log π_old - log π_θ]. Debe permanecer en[0, 0.02]. Si supera0.1, reduceK_EPOCHSo la tasa de aprendizaje (LR). - Fracción de recorte (Clip fraction) — la fracción de muestras cuya relación se encuentra fuera de
[1-ε, 1+ε]. Debe ser~0.1-0.3. Si ésto es~0, el recorte nunca se activa → aumentaLRoK_EPOCHS. Si es~0.5+, estás sobreajustando (overfitting) el rollout → disminúyelos. - Varianza explicada (Explained variance)
1 - Var(V_target - V_pred) / Var(V_target). Métrica de calidad del crítico. Debe subir hacia 1 a medida que el crítico aprende.
Armadillas (Pitfalls)
- Coeficiente de recorte (clip coefficient) mal ajustado.
ε = 0.2es el estándar de facto. Ir a0.1hace que las actualizaciones sean demasiado tímidas;0.3+invita a la inestabilidad. - Demasiadas épocas.
K > 20desestabiliza habitualmente porque la política se desvía demasiado deπ_old. Limita las épocas, especialmente para redes grandes. - Sin normalización de recompensas. Las escalas de recompensa grandes consumen el rango de recorte. Normaliza las recompensas (desviación estándar móvil) antes de calcular las ventajas.
- Olvidar la normalización de ventajas. La normalización de media cero y desviación estándar de la unidad por lote es estándar. Omitirla arruina PPO en la mayoría de las pruebas de rendimiento (benchmarks).
- Tasa de aprendizaje no disminuida. PPO se beneficia de un decaimiento lineal de la LR a cero. Una LR constante suele ser peor.
- Errores matemáticos en la relación de importancia. Utiliza siempre
exp(log_new - log_old)para estabilidad numérica, nonew / old. - Signo del gradiente incorrecto. Maximizar el sustituto = minimizar
-L^{CLIP}. Un signo invertido es el error más común en PPO.
Cómo Usarlo (Use It)
PPO es el algoritmo de RL predeterminado de 2026 en una cantidad sorprendente de dominios:
| Caso de uso | Variante de PPO |
|---|---|
| MuJoCo / control de robótica | PPO con política Gaussiana, GAE(0.95) |
| Atari / juegos discretos | PPO con política categórica, rollouts continuos de 128 pasos |
| RLHF para LLMs | PPO con penalización KL para el modelo de referencia, recompensa del RM al final de la respuesta |
| Agentes de juego a gran escala | IMPALA + PPO (AlphaStar, OpenAI Five) |
| LLMs de razonamiento | GRPO (Lección 12) — variante de PPO sin crítico |
| Datos de preferencia únicamente | DPO — colapso en forma cerrada de PPO+KL, sin muestreo online |
La forma de la pérdida de PPO — sustituto recortado + valor + entropía — es el andamiaje para DPO, GRPO y casi todos los pipelines de RLHF.
Envíalo (Ship It)
Guarda como outputs/skill-ppo-trainer.md:
---
name: ppo-trainer
description: Produce a PPO training config and a diagnostic plan for a given environment.
version: 1.0.0
phase: 9
lesson: 8
tags: [rl, ppo, policy-gradient]
---
Given an environment and training budget, output:
1. Rollout size. `N` envs × `T` steps.
2. Update schedule. `K` epochs, minibatch size, LR schedule.
3. Surrogate params. `ε` (clip), `c_v`, `c_e`, advantage normalization on.
4. Advantage. GAE(`λ`) with explicit `γ` and `λ`.
5. Diagnostics plan. KL, clip fraction, explained variance thresholds with alerts.
Refuse `K > 30` or `ε > 0.3` (unsafe trust region). Refuse any PPO run without advantage normalization or KL/clip monitoring. Flag clip fraction sustained above 0.4 as drift.
Ejercicios
- Fácil. Ejecuta PPO en GridWorld de 4×4 con
ε=0.2, K=4. Compara la eficiencia de muestras con A2C (una época por rollout) con los mismos pasos de entorno. - Medio. Realiza un barrido de
K ∈ {1, 4, 10, 30}. Grafica el retorno frente a los pasos de entorno y realiza un seguimiento de la KL media por actualización. ¿Con quéKexplota la KL en esta tarea? - Difícil. Reemplaza el sustituto recortado con una penalización KL adaptativa (duplica
βsiKL > 2·target, divídelo a la mitad siKL < target/2). Compara el retorno final, la estabilidad y la ausencia de recortes.
Términos Clave
| Término | Lo que dice la gente | Lo que realmente significa |
|---|---|---|
| Relación de importancia | "r_t(θ)" | `π_θ(a |
| Sustituto recortado | "El truco principal de PPO" | min(r·A, clip(r, 1-ε, 1+ε)·A); gradiente plano después del recorte en el lado beneficioso. |
| Región de confianza | "Intento de TRPO / PPO" | Limitar la KL de cada actualización para garantizar una mejora monótona. |
| Penalización KL | "Región de confianza suave" | PPO alternativo: `L - β · KL(π_θ |
| Fracción de recorte | "Con qué frequência se activa el recorte" | Diagnóstico — debe ser 0.1-0.3; fuera de esto significa desajustado. |
| Entrenamiento multi-época | "Reutilización de datos" | K épocas en cada rollout; costo de varianza intercambiado por eficiencia de muestras. |
| Estilo on-policy | "Mayormente on-policy" | PPO es nominalmente on-policy, pero las épocas K>1 utilizan datos ligeramente off-policy de forma segura. |
| PPO-KL | "El otro PPO" | Variante con penalización KL; se utiliza en RLHF donde la KL con respecto a la referencia ya es una restricción. |
Lecturas Adicionales
- Schulman et al. (2017). Proximal Policy Optimization Algorithms — el artículo.
- Schulman et al. (2015). Trust Region Policy Optimization — TRPO, el predecesor de PPO.
- Andrychowicz et al. (2021). What Matters In On-Policy RL? A Large-Scale Empirical Study — todos los hiperparámetros de PPO ablatados.
- Ouyang et al. (2022). Training language models to follow instructions with human feedback — InstructGPT; la receta de PPO en RLHF.
- OpenAI Spinning Up — PPO — exposición moderna y limpia con PyTorch.
- CleanRL PPO implementation — implementación de PPO en un solo archivo de referencia utilizada por muchos artículos.
- Hugging Face TRL — PPOTrainer — la receta de producción para PPO en modelos de lenguaje; léase junto con la Lección 09 (RLHF).
- Engstrom et al. (2020). Implementation Matters in Deep Policy Gradients — el artículo sobre las "37 optimizaciones a nivel de código"; qué trucos de PPO soportan la carga y cuáles son folclore.