092 — Control estructural y edición generativa

← Clase anterior · Índice de la parte · Clase siguiente →

Parte: 07 — IA generativa para texto, imagen, audio, video y 3D
Nivel: avanzado · Horas estimadas: 6
Laboratorio: generation · Estado: EXECUTABLE_CORE

🎯 Propósito

Comprender control estructural y edición generativa dentro de la evolución de la inteligencia artificial, implementar un experimento mínimo verificable y distinguir qué parte constituye evidencia frente a una afirmación todavía no comprobada.

📚 Resultados de aprendizaje

Al finalizar podrás:

  1. Explicar control estructural y edición generativa usando los conceptos inpainting, control, pose, depth.
  2. Ejecutar el laboratorio con una semilla explícita y revisar su contrato JSON.
  3. Identificar al menos un supuesto, una limitación y un riesgo de aplicación.
  4. Comparar el enfoque con la etapa anterior de la ruta de aprendizaje.
  5. Producir una evidencia reproducible y una conclusión que no exceda los datos.

🧩 Conceptos centrales

inpainting, control, pose, depth

🗺️ Ubicación en el mapa de la IA

El texto (clase 091) especifica qué generar, pero no dónde ni cómo: un prompt no puede fijar la pose exacta de una figura ni el trazado de un edificio. Esta clase cubre las técnicas que dan control espacial sobre un modelo de difusión ya entrenado —ControlNet, img2img e inpainting— sin reentrenarlo desde cero. Son las que convirtieron los generadores en herramientas de edición profesional y anticipan el control por condiciones múltiples en video y 3D.

📖 Fundamentos

🎛️ ControlNet: una copia entrenable del encoder

ControlNet (Zhang, Rao y Agrawala, 2023) añade condiciones espaciales densas —mapas de bordes (Canny), pose (OpenPose), profundidad, segmentación— a un modelo de difusión congelado. La arquitectura:

salida_bloque = bloque_congelado(z_t)  +  Z(bloque_copiado(z_t + Z'(c_f)))
donde Z, Z' son convoluciones 1×1 con W = 0, b = 0 al inicio

Al comenzar el entrenamiento, Z(·) = 0, así que la red se comporta exactamente como el modelo original: el control se incorpora de forma gradual sin destruir el conocimiento previo. Aunque la salida inicial es 0, el gradiente respecto a los pesos de la zero-convolution NO es cero (∂(W·x)/∂W = x ≠ 0), de modo que sí aprende desde el primer paso.

🖼️ img2img: la fuerza de ruido decide cuánto se conserva

img2img (formalizado como SDEdit, Meng et al., 2022) parte de una imagen real en vez de ruido puro. El parámetro strength s ∈ [0, 1] controla el punto de entrada al proceso de difusión con T pasos totales:

1. z₀ = E(imagen_original)                  # encodificar al latente
2. t_inicio = round(s · T)                  # cuánto ruido añadir
3. z_{t_inicio} = √(ᾱ_t)·z₀ + √(1−ᾱ_t)·ε   # difusión hacia delante, un salto
4. denoising desde t_inicio hasta 0 con el prompt como condición

Con s pequeño, se añade poco ruido y quedan pocos pasos de denoising: el resultado conserva composición, colores y estructura del original. Con s → 1, el latente es casi ruido puro y el original apenas influye. El costo también escala: se ejecutan s·T pasos de U-Net, no T.

🎭 Inpainting: regenerar solo dentro de la máscara

El inpainting recibe una imagen y una máscara binaria m (1 = regenerar, 0 = preservar). La variante sin reentrenamiento (RePaint, Lugmayr et al., 2022) fuerza en cada paso las zonas conocidas a su valor verdadero ruidificado:

en cada paso t:
    z_conocido  = difusión_forward(z₀_original, t)     # zona fuera de la máscara
    z_generado  = paso_de_denoising(z_t)               # predicción del modelo
    z_{t−1} = (1 − m) ⊙ z_conocido + m ⊙ z_generado    # componer con la máscara

El modelo solo "inventa" dentro de la máscara, pero cada paso ve el contexto real circundante, lo que garantiza coherencia en los bordes. Los modelos de inpainting dedicados (SD-inpainting) van más lejos: se afinan recibiendo la máscara y la imagen enmascarada como canales extra de entrada de la U-Net.

🧮 Ejemplo trabajado

La fuerza de img2img con T = 50. Calcula el paso inicial y los pasos ejecutados:

s = 0.2  →  t_inicio = round(0.2 · 50) = 10  →  10 pasos de denoising
s = 0.5  →  t_inicio = round(0.5 · 50) = 25  →  25 pasos
s = 0.8  →  t_inicio = round(0.8 · 50) = 40  →  40 pasos
s = 1.0  →  t_inicio = 50 (ruido casi puro)  →  50 pasos = texto-a-imagen normal

Con s = 0.2 el latente retiene √(ᾱ₁₀) ≈ la mayor parte de la señal original: el modelo solo puede retocar texturas y estilo — la composición sobrevive. Con s = 0.8 queda poca señal original: el prompt domina y solo persisten rasgos globales (paleta, disposición aproximada de masas). Regla práctica: retoque de estilo s ≈ 0.3-0.5; reinterpretación fuerte s ≈ 0.7-0.9.

Gradiente de la zero-convolution en el primer paso. Sea la zero-conv y = W·x + b con W = 0, b = 0, y una feature de entrada x = 3.0. En el forward, y = 0: el ControlNet no altera al modelo congelado. En el backward, con gradiente entrante ∂L/∂y = g = 0.5:

∂L/∂W = g · x = 0.5 · 3.0 = 1.5   ≠ 0  → W se actualiza: W ← 0 − η·1.5
∂L/∂b = g     = 0.5               ≠ 0  → b se actualiza
∂L/∂x = g · W = 0.5 · 0   = 0          → el bloque copiado aún no recibe señal

Tras la primera actualización W ≠ 0, y a partir de ahí el gradiente también fluye hacia el interior de la copia entrenable: el control se "enciende" progresivamente.

📊 Propiedades y comparación

Técnica Qué controla ¿Requiere entrenamiento? Parámetros extra Límite principal
Prompt (clase 091) contenido semántico global no 0 sin control espacial preciso
img2img (SDEdit) composición global vía imagen inicial no 0 (solo s) trade-off rígido fidelidad/libertad
Inpainting (RePaint / SD-inpaint) región enmascarada no / fine-tuning ligero 0 / canales extra coherencia global si la máscara es grande
ControlNet estructura densa (pose, bordes, profundidad) sí (copia del encoder, ~50 % params de la U-Net) cientos de M un modelo por tipo de condición
LoRA (parte 06) estilo/sujeto aprendido sí (rango bajo) pocos M no es control espacial por imagen
flowchart TB
    subgraph Congelado["U-Net congelada"]
        E1["Encoder"] --> M1["Mid"] --> D1["Decoder"]
        E1 -.->|skips| D1
    end
    subgraph ControlNet["Copia entrenable"]
        CF["condición c_f (pose/bordes/profundidad)"] --> Z1["zero-conv Z'"]
        Z1 --> E2["Encoder copiado"]
        E2 --> Z2["zero-conv Z (init W=0)"]
    end
    ZT["z_t"] --> E1
    ZT --> E2
    Z2 -->|"suma a los skips"| D1
    D1 --> OUT["ε_θ(z_t, c, c_f)"]

⚠️ Errores conceptuales frecuentes

  1. "ControlNet reentrena el modelo base." No: la U-Net original queda congelada; solo se entrena la copia del encoder y las zero-convolutions. Por eso un ControlNet se acopla a cualquier checkpoint compatible del mismo modelo base.
  2. "Si la zero-convolution sale 0, no puede aprender." El gradiente respecto a sus pesos es proporcional a la entrada (no a la salida), así que es distinto de cero desde el primer paso — solo el gradiente hacia atrás a través de W es 0 inicialmente.
  3. "strength = 0.5 conserva el 50 % de los píxeles." La fuerza fija el nivel de ruido de partida, no una mezcla lineal de píxeles: lo que se conserva es información de baja frecuencia (composición), no píxeles concretos.
  4. "El inpainting solo mira dentro de la máscara." Al revés: en cada paso el modelo ve el contexto completo (la zona conocida ruidificada al nivel t); esa es la razón de que los bordes queden coherentes.
  5. "Más condiciones siempre dan mejor control." Condiciones contradictorias (una pose que no cabe en el mapa de profundidad) degradan el resultado; los pesos de cada ControlNet deben balancearse y el prompt sigue mandando en lo semántico.

🚀 Del aprendizaje a la operación

Para un flujo de edición real faltan: preprocesadores robustos que extraigan la condición (detector de pose, estimador de profundidad) con sus propios modos de fallo, política de derechos cuando la imagen de partida no es del usuario, trazabilidad de qué se editó (máscaras y semillas registradas, procedencia C2PA), evaluación con usuarios de si el control es suficiente para la tarea, y límites de uso que impidan ediciones de personas reales sin consentimiento.

🧪 Laboratorio

python lab.py

El laboratorio llama a ai_evolution.labs.run_lab("generation"). Esta decisión evita 183 implementaciones divergentes: cada clase tiene un entrypoint propio, pero los motores didácticos se prueban como una biblioteca común.

🔍 Evidencia esperada

📓 Notebooks

📝 Evaluación

Criterio Peso
Comprensión conceptual 25 %
Ejecución reproducible 25 %
Interpretación basada en evidencia 25 %
Riesgos, límites y mejora propuesta 25 %

Consulta assessment.md para preguntas y criterio de aceptación.

⚠️ Errores comunes

Síntoma Causa probable Corrección
El código corre, pero no hay conclusión Se confundió ejecución con aprendizaje Explica qué demuestra y qué no demuestra
El resultado cambia sin explicación No se registró semilla o configuración Conserva semilla, versión y parámetros
Se promete uso real Se extrapoló desde una demo educativa Declara entorno, datos, límites y revisión humana
Se copia una métrica aislada No existe baseline ni costo de error Añade comparación y criterio de decisión

❓ Preguntas frecuentes

¿Debo usar una API comercial?
No. El núcleo funciona localmente. Las extensiones LIVE se documentan por separado.

¿El laboratorio representa una implementación industrial?
No por sí solo. Enseña el contrato y el patrón; producción exige integración, seguridad, observabilidad, pruebas y operación.

¿Dónde profundizo?
Revisa las especializaciones enlazadas en el README raíz y la ruta siguiente.

🔗 Referencias


📜 Papers que fundamentan esta clase

Bloque generado por python scripts/link_papers_to_classes.py. La fuente es papers/catalog/papers.json.

Paper Año Qué desbloqueó Miniatura
P17 · Modelos probabilísticos de difusión con eliminación de ruido 2020 La generación deja de ser un salto en la oscuridad: se aprende a deshacer, paso a paso, un proceso de ruido conocido. notebook

Cada ficha explica el problema anterior, la matemática mínima, los límites y los errores de atribución más frecuentes. Para leerlas con método: cómo leer un paper de IA · anexos matemáticos.


📚 Bibliografía de apoyo

Bloque generado por python scripts/link_sources_to_classes.py. Cada obra lleva su localizador verificado en sources/bibliography.json.

Los papers dicen de dónde salió el mecanismo. Estas obras lo desarrollan con el espacio que una clase no tiene: teoría completa, demostraciones y ejercicios.

Obra Edición Localizador Papel en esta clase
Goodfellow, Ian, Bengio, Yoshua y Courville, Aaron — Deep Learning 2016 ISBN 9780262035613 · web de la obra obra de referencia de la parte 07 · capítulos de modelos generativos

⬅️ Clase anterior

091 — Texto a imagen y condicionamiento

➡️ Siguiente clase

093 — Generación musical y de audio


📝 Evaluación completa

❓ Preguntas

  1. Define control estructural y edición generativa sin usar una marca o framework como definición.
  2. Explica la relación entre inpainting, control, pose, depth.
  3. Ejecuta lab.py dos veces con la misma semilla. ¿Qué debe conservarse?
  4. Identifica una afirmación permitida y una afirmación exagerada sobre el resultado.
  5. Propón una prueba negativa o un caso límite.

🏆 Reto verificable

Amplía el resultado del laboratorio con una clave student_extension que incluya:

✅ Criterio de aceptación