Phase 08 - Lesson 04
Conditional GANs & Pix2Pix
La GAN Condicional (Mirza & Osindero, 2014) agrega una condición c como entrada tanto para G como para D. Pix2Pix (Isola et al., 2017) especializó esto: la condición es una imagen de entrada completa, el generador es una U-Net, el discriminador es un clasificador basado en parches (PatchGAN) y la pérdida es adversarial + L1. Esa receta supera a los modelos de texto a imagen desde cero en dominios reducidos de imagen a imagen incluso en 2026 porque se entrena con datos emparejados, por lo que tienes exactamente la señal que necesitas.
El Concepto
G Condicional. G(x, z) → y. En Pix2Pix, z es dropout dentro de G (sin ruido de entrada; Isola descubrió que el ruido explícito se ignoraba).
D Condicional. D(x, y) → [0, 1]. La entrada es el par (condición, salida). Esta es la diferencia clave: D debe juzgar si y es consistente con x, no solo si y parece real.
Generador U-Net. Encoder-decoder con conexiones de salto (skip connections) a través del cuello de botella (bottleneck). Crítico para tareas donde la entrada y la salida comparten una estructura de bajo nivel (bordes, silueta). Sin los saltos, los detalles de alta frecuencia desaparecen.
Discriminador PatchGAN. En lugar de devolver una única puntuación de real/falso, D devuelve una cuadrícula de N×N donde cada celda juzga un campo receptivo de ~70×70 píxeles. Promediado. Esta es una suposición de campo aleatorio de Markov: el realismo es local. Mucho más rápido de entrenar, menos parámetros, salida más nítida.
Pérdida.
loss_G = -log D(x, G(x)) + λ · ||y - G(x)||_1
loss_D = -log D(x, y) - log (1 - D(x, G(x)))
El término L1 estabiliza el entrenamiento y empuja a G hacia el objetivo conocido. L1 genera bordes más nítidos que L2 (medianas, no medias). λ = 100 era el valor predeterminado de Pix2Pix.
CycleGAN — cuando no tienes parejas
Pix2Pix necesita datos emparejados (x, y). CycleGAN (Zhu et al., 2017) elimina este requisito a costa de una pérdida adicional: la pérdida de consistencia de ciclo (cycle consistency). Dos generadores G: X → Y and F: Y → X. Se entrenan de manera que F(G(x)) ≈ x y G(F(y)) ≈ y. Esto te permite traducir caballos en cebras, verano en invierno, sin ejemplos emparejados.
En 2026, la traducción de imagen a imagen no emparejada se realiza principalmente mediante difusión (ControlNet, IP-Adapter) en lugar de CycleGAN, pero la idea de consistencia de ciclo sobrevive en casi todos los artículos de adaptación de dominios no emparejados.
Constrúyelo
code/main.py implementa una GAN condicional pequeña en datos 1-D. La condición c es una etiqueta de clase (0 o 1). La tarea: producir una muestra de la distribución condicional para la clase dada.
Paso 1: agregar la condición a las entradas de G y D
def G(z, c, params):
return mlp(concat([z, one_hot(c)]), params)
def D(x, c, params):
return mlp(concat([x, one_hot(c)]), params)
La codificación one-hot es la forma más sencilla. Los modelos más grandes utilizan embeddings aprendidos, modulación FiLM o atención cruzada (cross-attention).
Paso 2: entrenar condicional
for step in range(steps):
x, c = sample_real_conditional()
noise = sample_noise()
update_D(x_real=x, x_fake=G(noise, c), c=c)
update_G(noise, c)
El generador debe coincidir con la distribución real para la condición dada, no con la marginal.
Paso 3: verificar la salida por clase
for c in [0, 1]:
samples = [G(noise, c) for noise in batch]
mean_c = mean(samples)
assert_near(mean_c, real_mean_for_class_c)
Dificultades
- Condición ignorada. G aprende a marginalizar, D nunca penaliza porque la señal de la condición es débil. Solución: condicionar D de manera más agresiva (capa temprana, no solo tardía), usar discriminador de proyección (Miyato & Koyama 2018).
- Peso L1 demasiado bajo. G se desvía hacia salidas realistas arbitrarias, no fieles. Comienza con λ≈100 para tareas tipo Pix2Pix.
- Peso L1 demasiado alto. G produce salidas borrosas porque L1 sigue siendo una norma L_p. Reduce gradualmente (anneal down) una vez que el entrenamiento se estabilice.
- Filtración de ground-truth en D. Concatena
(x, y)como entrada de D, no soloy. Sin esto, D no puede verificar la consistencia. - Colapso de modo por clase. Cada clase puede colapsar de forma independiente. Realiza comprobaciones de diversidad condicionales por clase.
Úsalo
Estado de las tareas de imagen a imagen en 2026:
| Tarea | Mejor enfoque |
|---|---|
| Boceto → foto, mismo dominio, datos emparejados | Pix2Pix / Pix2PixHD (sigue siendo rápido, sigue siendo nítido) |
| Boceto → foto, no emparejado | ControlNet con un modelo de condicionamiento Scribble |
| Seg semántica → foto | SPADE / GauGAN2 o SD + ControlNet-Seg |
| Transferencia de estilo | Difusión con IP-Adapter o LoRA; los métodos GAN son legados |
| Profundidad → foto | ControlNet-Depth sobre Stable Diffusion |
| Superresolución | Real-ESRGAN (GAN), ESRGAN-Plus o SD-Upscale (difusión) |
| Coloración | ColTran, colorizadores basados en difusión o Pix2Pix-color |
| Día → noche, estaciones, clima | Basado en CycleGAN o ControlNet |
Pix2Pix sigue siendo la herramienta adecuada cuando (a) tienes miles de ejemplos emparejados, (b) la tarea es estrecha y repetible, y (c) necesitas una inferencia rápida. En tareas genéricas de dominio abierto, gana la difusión.
Envíalo
Guarda outputs/skill-img2img-chooser.md. La Skill recibe una descripción de la tarea, disponibilidad de datos (emparejados vs no emparejados, N muestras) y presupuesto de latencia/calidad, luego genera: enfoque (Pix2Pix, CycleGAN, variante de ControlNet, SDXL + IP-Adapter), requisitos de datos de entrenamiento, costo de inferencia y protocolo de evaluación (LPIPS, FID, específico de la tarea).
Ejercicios
- Fácil. Modifica
code/main.pypara agregar una tercera clase. Confirma que G siga mapeando el ruido de cada clase al modo correcto. - Medio. Reemplaza L1 por una pérdida de tipo perceptual en el entorno 1-D (por ejemplo, un D pequeño y congelado que actúe como extractor de características). ¿Cambia la nitidez de la distribución condicional?
- Difícil. Dibuja un CycleGAN en el entorno 1-D: dos distribuciones, dos generadores, pérdida de ciclo. Muestra que aprende a mapear entre ellos sin datos emparejados.
Términos Clave
| Término | Lo que dice la gente | Lo que realmente significa |
|---|---|---|
| GAN Condicional | "GAN con etiquetas" | G(z, c), D(x, c). Ambas redes ven la condición. |
| Pix2Pix | "GAN de imagen a imagen" | cGAN emparejada con G U-Net y D PatchGAN + pérdida L1. |
| U-Net | "Encoder-decoder con saltos" | Red convolucional simétrica; los saltos preservan la alta frecuencia. |
| PatchGAN | "Clasificador de realismo local" | D genera una puntuación por parche en lugar de una puntuación global. |
| CycleGAN | "Traducción de imágenes no emparejadas" | Dos G + pérdida de consistencia de ciclo; sin datos emparejados. |
| SPADE | "GauGAN" | Normaliza las activaciones intermedias con el mapa semántico; de segmentación a imagen. |
| FiLM | "Modulación lineal por características" | Transformación afín por característica a partir de la condición; condicionamiento económico. |
Nota de producción: Pix2Pix como línea base limitada por la latencia
Cuando se tienen datos emparejados y una tarea estrecha (boceto → renderizado, mapa semántico → foto, día → noche), la inferencia de un solo disparo (one-shot) de Pix2Pix supera a la difusión por un orden de magnitud en latencia. La comparación en producción suele ser:
| Camino | Pasos | Latencia típica a 512² en una sola L4 |
|---|---|---|
| Pix2Pix (U-Net forward) | 1 | ~30 ms |
| SD-Inpaint o SD-Img2Img | 20 | ~1.2 s |
| SDXL-Turbo Img2Img | 1-4 | ~0.15-0.35 s |
| ControlNet + SDXL base | 20-30 | ~3-5 s |
Pix2Pix gana en rendimiento en lotes estáticos (cada solicitud consume los mismos FLOPs). La difusión gana en calidad y generalización. La estrategia moderna suele ser lanzar un modelo destilado al estilo Pix2Pix para la tarea estrecha y un respaldo (fallback) de difusión para entradas menos comunes (tail inputs).
Lectura Adicional
- Mirza & Osindero (2014). Conditional Generative Adversarial Nets — el artículo de cGAN.
- Isola et al. (2017). Image-to-Image Translation with Conditional Adversarial Networks — Pix2Pix.
- Zhu et al. (2017). Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks — CycleGAN.
- Wang et al. (2018). High-Resolution Image Synthesis with Conditional GANs — Pix2PixHD.
- Park et al. (2019). Semantic Image Synthesis with Spatially-Adaptive Normalization — SPADE / GauGAN.
- Miyato & Koyama (2018). cGANs with Projection Discriminator — el D de proyección.