¿Por qué los modelos de difusión incondicionales generan imágenes borrosas?

Un modelo de difusión incondicional aprende a generar imágenes de la distribución completa de entrenamiento. Si entrenamos con millones de fotografías, el modelo aprende a producir cualquier fotografía plausible. Eso suena impresionante, pero viene con un problema: la distribución es enormemente amplia. Cuando el modelo comienza a eliminar ruido a partir de ruido aleatorio, tiene que elegir una dirección — ¿perro? ¿paisaje? ¿retrato? — y si nada restringe esa elección, el modelo puede cubrirse las espaldas derivándose hacia un promedio borroso de muchas imágenes posibles en lugar de comprometerse con una específica y nítida.

Añadir un prompt de texto ("un golden retriever jugando en la nieve") estrecha la distribución, pero el modelo podría aún no comprometerse lo suficiente con la dirección condicionada. La predicción condicional apunta hacia imágenes de perro en nieve, mientras que el prior incondicional apunta hacia el promedio amplio de todas las imágenes. Si el modelo solo sigue la señal condicional a su intensidad predeterminada, el resultado puede ser descolorido o genérico.

Lo que necesitamos es una forma de amplificar la confianza del modelo en la dirección condicionada por texto: dirigir más fuertemente hacia lo que el texto pide, y alejarse del promedio genérico. Eso es exactamente lo que hace la guía. Gira una perilla que controla qué tan agresivamente el proceso de eliminación de ruido sigue el prompt de texto — el mismo tipo de compromiso calidad-diversidad que la temperatura controla en los modelos de lenguaje.

Guía por clasificador (el predecesor)

El primer enfoque de difusión guiada vino de (Dhariwal & Nichol, 2021) . Su artículo, "Diffusion Models Beat GANs on Image Synthesis", mostró que los modelos de difusión podían superar a las GANs en calidad de imagen — pero solo con guía. La idea: entrenar un clasificador separado $p(y|x_t)$ que pueda mirar una imagen ruidosa $x_t$ en cualquier paso de tiempo y predecir a qué clase $y$ pertenece. Luego usar el gradiente de este clasificador para empujar cada paso de eliminación de ruido hacia la clase deseada.

Formalmente, queremos muestrear de la distribución condicional $p(x_t | y)$ — imágenes que pertenecen a la clase $y$. Por la regla de Bayes, el score (gradiente de la log-densidad) se descompone como:

$$\nabla_{x_t} \log p(x_t | y) = \nabla_{x_t} \log p(x_t) + s \cdot \nabla_{x_t} \log p(y | x_t)$$

Cada término tiene un rol claro:

  • $\nabla_{x_t} \log p(x_t)$: el score incondicional — la dirección en la que el modelo de difusión eliminaría ruido sin información de clase. Este es simplemente el paso estándar de eliminación de ruido.
  • $\nabla_{x_t} \log p(y | x_t)$: el gradiente del clasificador — la dirección que aumenta la confianza del clasificador en que la imagen pertenece a la clase $y$. Se calcula retropropagando a través del clasificador con respecto a la imagen ruidosa $x_t$.
  • $s$: la escala de guía — un escalar que controla qué tan fuertemente el clasificador empuja el proceso de eliminación de ruido. Mayor $s$ significa una dirección más agresiva hacia la clase $y$.

Cuando $s = 0$, recuperamos la generación incondicional pura (el clasificador se ignora). Cuando $s = 1$, obtenemos condicionamiento bayesiano estándar. Cuando $s > 1$, sobre-amplificamos la señal del clasificador — produciendo imágenes más nítidas de la clase $y$ a costa de diversidad. Esto fue un avance: mostró que la guía es el ingrediente clave para la generación condicional de alta calidad.

Pero la guía por clasificador tiene una limitación práctica dolorosa: necesitas entrenar un clasificador separado que funcione en imágenes ruidosas en cada nivel de ruido. Los clasificadores estándar de ImageNet solo ven imágenes limpias, así que necesitas un modelo especializado entrenado en los estados intermedios ruidosos del proceso de difusión. Eso es entrenamiento extra, cómputo extra, ingeniería extra — y solo funciona para etiquetas de clase, no para prompts de texto libre.

Guía sin clasificador (CFG)

¿Qué pasaría si pudiéramos obtener el mismo efecto de guía sin ningún clasificador externo? (Ho & Salimans, 2022) propusieron una solución elegante en "Classifier-Free Diffusion Guidance": usar el propio modelo de difusión para proporcionar tanto la señal condicional como la incondicional.

El truco ocurre durante el entrenamiento . Con alguna probabilidad (típicamente 10–20% del tiempo), la condición de texto $c$ se reemplaza con un token nulo $\varnothing$ (un embedding vacío o cero). Esto significa que el mismo modelo aprende a predecir ruido en dos modos: condicionado en texto ($\epsilon_\theta(x_t, c)$) e incondicionado ($\epsilon_\theta(x_t, \varnothing)$). No se necesita un modelo separado — solo una red que ha visto ambos regímenes.

Durante la inferencia , ejecutamos el modelo dos veces por paso de eliminación de ruido — una con el prompt de texto, otra sin — y combinamos las salidas:

$$\tilde{\epsilon}_\theta = \epsilon_\theta(x_t, \varnothing) + w \cdot (\epsilon_\theta(x_t, c) - \epsilon_\theta(x_t, \varnothing))$$

Desglosemos cada componente:

  • $\epsilon_\theta(x_t, c)$: la predicción de ruido con la condición de texto $c$. Es la mejor estimación del modelo de qué ruido eliminar, dado el prompt de texto.
  • $\epsilon_\theta(x_t, \varnothing)$: la predicción de ruido sin ninguna condición (la línea base incondicional). Es hacia donde el modelo eliminaría ruido si no tuviera ninguna guía de texto.
  • $(\epsilon_\theta(x_t, c) - \epsilon_\theta(x_t, \varnothing))$: la dirección del texto — la diferencia entre las predicciones condicional e incondicional. Este vector captura exactamente lo que el texto contribuye más allá del prior incondicional genérico. Es la "señal pura del texto".
  • $w$: la escala de guía (a veces llamada escala CFG o peso de guía). Multiplicamos la dirección del texto por $w$ para amplificarla o atenuarla.
💡 La fórmula se puede reorganizar como $\tilde{\epsilon}_\theta = (1 - w) \cdot \epsilon_\theta(x_t, \varnothing) + w \cdot \epsilon_\theta(x_t, c)$. En esta forma, es una interpolación ponderada (o extrapolación cuando $w > 1$) entre las predicciones incondicional y condicional. Cuando $w > 1$, estamos extrapolando más allá de la predicción condicional en la dirección opuesta a la incondicional.

Ahora el análisis de límites — ¿qué sucede con diferentes valores de $w$?

  • $w = 0$: $\tilde{\epsilon} = \epsilon_\theta(x_t, \varnothing)$. Generación incondicional pura. El prompt de texto se ignora completamente, y el modelo genera de la distribución completa de entrenamiento — cualquier imagen es igualmente probable.
  • $w = 1$: $\tilde{\epsilon} = \epsilon_\theta(x_t, c)$. Generación condicional estándar sin amplificación. El modelo usa el texto tal cual, ni más ni menos. Esto es lo que obtendrías sin ninguna guía.
  • $w = 7.5$: el valor predeterminado típico para Stable Diffusion. La dirección del texto se amplifica 7.5$\times$, produciendo imágenes que coinciden fuertemente con el prompt con buena calidad visual. Este es el punto óptimo que la mayoría de los practicantes usan.
  • $w > 15$: territorio de sobresaturación. Los colores se vuelven antinaturalmente vívidos, los detalles se exageran, y aparecen artefactos. El modelo "se esfuerza demasiado" para coincidir con el texto, empujando los valores de píxeles a rangos extremos. La calidad se degrada notablemente.
  • $w < 0$: guía negativa . La dirección del texto se invierte — el modelo se dirige activamente lejos de la descripción textual. Este es el mecanismo detrás de los prompts negativos, que cubriremos en la siguiente sección.

El código a continuación demuestra CFG con números concretos. Simulamos dos predicciones de ruido (condicional e incondicional) y mostramos cómo diferentes escalas de guía transforman la salida final.

import json, js

# Simulated noise predictions for a single pixel/dimension
eps_uncond = 0.3   # unconditional prediction
eps_cond   = 0.7   # conditional prediction (with text)

# The "text direction" is the difference
text_dir = eps_cond - eps_uncond  # = 0.4

# CFG formula: eps_guided = eps_uncond + w * (eps_cond - eps_uncond)
w_values = [0, 0.5, 1.0, 3.0, 5.0, 7.5, 10.0, 15.0, 20.0]
guided   = [eps_uncond + w * text_dir for w in w_values]

plot_data = [
    {
        "title": "CFG Output vs Guidance Scale w",
        "x_label": "Guidance Scale (w)",
        "y_label": "Guided Noise Prediction",
        "x_data": [str(w) for w in w_values],
        "lines": [
            {"label": "CFG output", "data": [round(g, 2) for g in guided], "color": "#6366f1"},
            {"label": "Unconditional (w=0)", "data": [round(eps_uncond, 2)] * len(w_values), "color": "#94a3b8"},
            {"label": "Conditional (w=1)", "data": [round(eps_cond, 2)] * len(w_values), "color": "#f59e0b"},
        ]
    }
]
js.window.py_plot_data = json.dumps(plot_data)

print(f"Unconditional prediction: {eps_uncond}")
print(f"Conditional prediction:   {eps_cond}")
print(f"Text direction:           {text_dir}")
print()
for w, g in zip(w_values, guided):
    label = ""
    if w == 0:   label = " (pure unconditional)"
    if w == 1:   label = " (standard conditional)"
    if w == 7.5: label = " (typical SD default)"
    print(f"  w={w:5.1f} => guided={g:.2f}{label}")

Observa cómo en $w = 7.5$ la predicción guiada (3.3) se ha movido mucho más allá de la predicción condicional (0.7) — estamos extrapolando, no interpolando. Esta extrapolación es lo que produce imágenes nítidas y fieles al texto, pero si empujas $w$ demasiado alto, los valores explotan, causando artefactos de saturación.

Esta es también la razón por la que Stable Diffusion es lento : cada paso de eliminación de ruido requiere dos pases hacia adelante a través de la U-Net (uno condicional, uno incondicional). Con 20–50 pasos de eliminación de ruido, eso son 40–100 evaluaciones de red neuronal por imagen. Técnicas como la destilación (entrenar un modelo estudiante para aproximar la salida guiada por CFG en un solo pase) son un área activa de investigación para reducir este costo.

💡 La analogía con la temperatura en modelos de lenguaje es útil. En un modelo de lenguaje, temperatura baja agudiza la distribución de probabilidad sobre tokens (más confianza, menos diversidad); temperatura alta la aplana (más aleatorio, más diversidad). En difusión, alta escala de guía $w$ agudiza la distribución sobre imágenes hacia el prompt de texto (más fiel al texto, menos diversidad); baja $w$ produce imágenes más variadas pero menos adherentes al prompt. Ver el artículo de temperatura para la conexión formal: la temperatura del softmax controla la entropía de una distribución categórica de la misma manera que $w$ controla qué tan ajustadamente la trayectoria de difusión sigue la señal de texto.

Prompts negativos y cómo funcionan

Si has usado Stable Diffusion, probablemente has visto un campo de "prompt negativo" donde la gente escribe cosas como "borroso, baja calidad, deformado, feo". ¿Cómo funciona esto realmente? Resulta que los prompts negativos son una modificación simple de la fórmula CFG — en lugar de usar el token nulo vacío $\varnothing$ como línea base incondicional, lo reemplazamos con una condición negativa $c_{\text{neg}}$ que describe lo que queremos evitar:

$$\tilde{\epsilon}_\theta = \epsilon_\theta(x_t, c_{\text{neg}}) + w \cdot (\epsilon_\theta(x_t, c_{\text{pos}}) - \epsilon_\theta(x_t, c_{\text{neg}}))$$

Esto es estructuralmente idéntico al CFG estándar. El único cambio es intercambiar $\varnothing$ por $c_{\text{neg}}$. Pero el efecto es poderoso: la dirección del texto $(\epsilon_\theta(x_t, c_{\text{pos}}) - \epsilon_\theta(x_t, c_{\text{neg}}))$ ahora apunta lejos de la descripción negativa y hacia la positiva. Como amplificamos esta dirección por $w$, el modelo se dirige simultáneamente hacia lo que quieres y lejos de lo que no quieres.

Tracemos los casos límite para la fórmula del prompt negativo:

  • $w = 0$: $\tilde{\epsilon} = \epsilon_\theta(x_t, c_{\text{neg}})$. El modelo genera imágenes que coinciden con el prompt negativo . Esto es lo opuesto a lo que quieres — obtendrías imágenes borrosas y de baja calidad.
  • $w = 1$: $\tilde{\epsilon} = \epsilon_\theta(x_t, c_{\text{pos}})$. Generación condicional estándar con el prompt positivo. El prompt negativo no tiene efecto.
  • $w = 7.5$: el prompt positivo se amplifica y las características del prompt negativo se suprimen activamente. Este es el uso típico.

Los prompts negativos comunes incluyen "borroso, baja calidad, deformado, dedos extra, marca de agua". Funcionan porque el modelo de difusión ha visto tales imágenes durante el entrenamiento y puede predecir qué patrones de ruido conducen hacia ellas — así que sabe en qué dirección dirigirse lejos de . El prompt negativo no elimina características de una imagen; cambia la trayectoria de todo el proceso de eliminación de ruido desde el primer paso.

import json, js

# Simulated predictions for one dimension
eps_pos = 0.8   # conditional on positive prompt
eps_neg = 0.2   # conditional on negative prompt
eps_null = 0.4  # unconditional (null prompt)

w = 7.5

# Standard CFG (null baseline)
guided_null = eps_null + w * (eps_pos - eps_null)

# Negative prompt CFG
guided_neg = eps_neg + w * (eps_pos - eps_neg)

# Standard CFG pushes away from the generic average
# Negative prompt CFG pushes away from the negative description
rows = [
    ["Standard CFG (null baseline)", f"{eps_null}", f"{eps_pos}", f"{eps_pos - eps_null:.1f}", f"{guided_null:.1f}"],
    ["Negative prompt CFG", f"{eps_neg}", f"{eps_pos}", f"{eps_pos - eps_neg:.1f}", f"{guided_neg:.1f}"],
]

js.window.py_table_data = json.dumps({
    "headers": ["Mode", "Baseline", "Positive", "Text Direction", "Guided (w=7.5)"],
    "rows": rows
})

print("With a negative prompt, the text direction is LARGER")
print(f"  Null baseline direction:     {eps_pos - eps_null:.1f}")
print(f"  Negative prompt direction:   {eps_pos - eps_neg:.1f}")
print()
print("So the guided output is pushed further from the negative features")
💡 El prompt negativo reemplaza la línea base incondicional, por lo que la dirección del texto se vuelve más grande cuando el prompt negativo describe características lejanas al prompt positivo. Por eso los prompts negativos específicos ("borroso, manos deformadas") funcionan mejor que los vagos ("malo") — crean un vector de dirección más grande y más dirigido.

Codificadores de texto: CLIP vs T5

CFG controla qué tan fuertemente el modelo sigue el prompt de texto. Pero la calidad de esa señal de texto depende enteramente del codificador de texto — el modelo que convierte una cadena de palabras en el vector de embedding $c$ que condiciona el modelo de difusión. Dos arquitecturas dominan este rol, y sus fortalezas son complementarias.

CLIP (Radford et al., 2021) fue entrenado mediante aprendizaje contrastivo en 400 millones de pares imagen-texto. El objetivo de entrenamiento empujó pares imagen-texto coincidentes juntos en el espacio de embedding y pares no coincidentes aparte. Esto da a CLIP un fuerte sentido de qué imágenes "van con" qué descripciones. Stable Diffusion 1.x y 2.x usan CLIP como su codificador de texto.

Pero CLIP tiene limitaciones. Su pérdida contrastiva optimiza para coincidencia global (¿esta leyenda describe esta imagen?) en lugar de comprensión composicional fina. Tiene dificultades con relaciones espaciales ("un cubo rojo a la izquierda de una esfera azul"), negación ("una habitación sin muebles"), y conteo ("exactamente tres gatos"). También tiene un límite duro de 77 tokens, truncando prompts más largos.

T5 (Raffel et al., 2020) es un transformer puro de texto a texto entrenado en un corpus masivo de texto (C4). Nunca fue entrenado en imágenes, pero entiende el lenguaje profundamente: gramática, composicionalidad, dependencias de largo alcance e instrucciones complejas. Crucialmente, no tiene límite fijo de tokens para propósitos prácticos y codifica estructura lingüística mucho más rica que CLIP.

(Saharia et al., 2022) demostraron un hallazgo sorprendente en su artículo de Imagen: escalar el codificador de texto importa más que escalar el propio modelo de difusión. Cambiar CLIP por T5-XXL (un codificador de texto de 4.6B parámetros) produjo una alineación texto-imagen dramáticamente mejor, especialmente para prompts complejos, incluso cuando la U-Net de difusión se mantuvo del mismo tamaño. El cuello de botella en la generación de texto a imagen no era el generador de imágenes — era la comprensión del texto.

La tendencia en las arquitecturas más nuevas refleja este hallazgo:

  • Stable Diffusion 1.x/2.x: solo CLIP (OpenCLIP ViT-L o ViT-H). Bueno para coincidir con descripciones estéticas pero débil en prompts composicionales.
  • Stable Diffusion 3 / SD 3.5: usa tres codificadores de texto simultáneamente — dos modelos CLIP (OpenCLIP ViT-G y CLIP ViT-L) más T5-XXL. Los codificadores CLIP proporcionan embeddings alineados con imágenes mientras T5 maneja la comprensión compleja del lenguaje.
  • Flux: usa CLIP ViT-L más T5-XXL, combinando ambas fortalezas. T5 maneja el trabajo pesado para la comprensión de prompts.
  • Imagen / Imagen 2: solo T5-XXL. Demostró que un codificador de texto poderoso por sí solo es suficiente.

Para el mecanismo CFG, la elección del codificador de texto determina la calidad del embedding condicional $c$ en $\epsilon_\theta(x_t, c)$. Un mejor codificador de texto significa que la predicción condicional refleja más precisamente el prompt, lo que significa que la dirección del texto $(\epsilon_\theta(x_t, c) - \epsilon_\theta(x_t, \varnothing))$ es más precisa. En la práctica, esto se traduce en necesitar escalas de guía más bajas con mejores codificadores de texto — la señal es más limpia, así que se necesita menos amplificación. Los modelos Flux, por ejemplo, frecuentemente usan $w = 3.5$ en lugar del $w = 7.5$ de Stable Diffusion.

💡 El embedding del codificador de texto típicamente se inyecta en el modelo de difusión vía capas de atención cruzada: las características de la imagen ruidosa atienden a los tokens de salida del codificador de texto (no solo a un único vector agrupado) para que diferentes regiones espaciales de la imagen puedan atender a diferentes partes del prompt. Por eso las representaciones de texto a nivel de token (de T5) son más útiles que un único embedding de oración.

Quiz

Pon a prueba tu comprensión de la guía sin clasificador, los prompts negativos y los codificadores de texto.

En la fórmula CFG $\tilde{\epsilon}_\theta = \epsilon_\theta(x_t, \varnothing) + w \cdot (\epsilon_\theta(x_t, c) - \epsilon_\theta(x_t, \varnothing))$, ¿qué sucede cuando $w = 1$?

¿Por qué la guía sin clasificador requiere dos pases hacia adelante por paso de eliminación de ruido?

¿Cómo funcionan los prompts negativos en Stable Diffusion?

Según el artículo de Imagen (Saharia et al., 2022), ¿qué tiene más impacto en la calidad de texto a imagen?