18

De texto a imagen

¿Cómo entiende el modelo lo que le pides con palabras?

13 min

De texto a imagen

Con voz. Puedes pausar y saltar a cualquier paso.

Lección completa

Subtítulos

Escribes «un gato astronauta» y, en segundos, un programa te devuelve una imagen que nadie dibujó. ¿Cómo convierte una frase en una imagen?

Voz

Sin voz: la lección avanza sola con subtítulos.

La voz de esta lección está en preparación: por ahora avanza sola con subtítulos.

0:00 / 0:00

Qué lograrás

  • Explicar cómo CLIP entrena juntos un codificador de imágenes y uno de texto para que cada imagen quede cerca de su frase, leyendo la tabla de similitudes y su diagonal.
  • Describir cómo el vector de la frase condiciona la difusión y predecir qué pasa con la fidelidad y la variedad al subir la escala de guiado.
  • Reconocer los límites de estos modelos (sesgos que se amplifican, combinaciones nunca vistas, quién va con quién, contar y escribir) y los riesgos de derechos, suplantación y procedencia.

Ideas clave

  1. CLIP entrena juntos un codificador de imágenes y uno de texto. Ambos entregan vectores del mismo tamaño, que se comparan con la similitud coseno.
  2. El entrenamiento es contrastivo: en cada lote, la tabla de similitudes debe encender su diagonal (los pares correctos) y apagar el resto. No hacen falta etiquetas a mano, solo imágenes con su frase.
  3. Para generar desde texto, la red de difusión recibe una entrada extra: el vector de la frase. Eso es condicionar. El prompt es esa frase, y el modelo solo entiende las palabras que vio al entrenar.
  4. El guiado sin clasificador predice el ruido con la frase y sin ella, y exagera la diferencia según la escala de guiado: más escala, más fidelidad y menos variedad; demasiada, deforma.
  5. Los modelos heredan y amplifican los sesgos de sus datos, fallan más en lo nunca visto, pueden confundir quién va con quién y les cuesta contar y escribir. Sus datos plantean preguntas de derechos, y sus imágenes, de suplantación y procedencia.

Lo que mucha gente cree

Creencia común Un generador de imágenes entiende la frase como una persona: si las palabras están bien escritas, dibuja exactamente lo que pediste.

Lo correcto Convierte la frase en un vector aprendido de pares de imagen y texto, y la difusión se guía por ese vector. Lo que no estaba en sus datos (palabras, combinaciones, cantidades, letras) lo maneja mal, y lo frecuente en sus datos lo repite de más.

Compruébalo

Cuatro preguntas. Sin nota ni cuenta: sirven para ver si la idea quedó.

Concepto¿Qué aprende CLIP durante su entrenamiento?
ConceptoSubes la escala de guiado de uno a tres con el mismo prompt. ¿Qué esperas?
CálculoEn un paso, la red predice 0.2 sin frase y 0.5 con la frase. Con escala de guiado 3, ¿qué valor se usa?
AplicaciónTu equipo genera ilustraciones con el prompt «una enfermera atendiendo a un paciente» y casi todas muestran a una mujer joven. ¿Qué es lo más adecuado?

Por dentroPara quien quiere las fórmulas y el código. No hace falta para seguir el curso.

La pérdida contrastiva de CLIP

En un lote de NN pares, el codificador de imágenes ff y el de texto gg producen vectores unitarios ui=f(xi)u_i = f(x_i) y vj=g(tj)v_j = g(t_j). Su similitud coseno es Sij=ui⋅vjS_{ij} = u_i \cdot v_j. Se dividen entre una temperatura τ\tau (que también se aprende) y se pide, con entropía cruzada, que cada imagen elija su propia frase y que cada frase elija su propia imagen:

L=12N∑i=1N[−ln⁡eSii/τ∑jeSij/τ  −ln⁡eSii/τ∑jeSji/τ]\mathcal{L} = \frac{1}{2N}\sum_{i=1}^{N}\Big[-\ln\frac{e^{S_{ii}/\tau}}{\sum_j e^{S_{ij}/\tau}} \; - \ln\frac{e^{S_{ii}/\tau}}{\sum_j e^{S_{ji}/\tau}}\Big]

Es la pérdida simétrica del artículo de Radford y colaboradores (figura 3): sube la diagonal de la tabla SS y baja el resto de su fila y de su columna. CLIP usó lotes de 32 768 pares, es decir, tablas de más de mil millones de casillas en cada paso, y unos 400 millones de pares de imagen y texto reunidos de fuentes públicas de internet. La ficha del modelo es de enero de 2021.

En nuestro juguete, el codificador de imágenes recibe 720 números (12 × 12 píxeles, cada uno con 5 casillas one-hot de color) y tiene una capa oculta de 96; el de texto lee 5 posiciones de palabra, cada palabra con un vector de 16 más un vector de su posición, y tiene una capa oculta de 64. Ambos entregan D=32D = 32. Se entrenó 2 500 pasos con lotes de 96; la temperatura pasó de 1/τ≈14.31/\tau \approx 14.3 a 22.022.0. En el lote fijo de seis pares que muestra la escena, la diagonal termina entre 0.78 y 0.88. El error del lote no llega a cero con lotes de 96: muchas frases incompletas («círculo») se repiten dentro del mismo lote y no pueden distinguir a sus imágenes.

Condicionar y guiar

La red de difusión predice el ruido ϵθ(zt,t,c)\epsilon_\theta(z_t, t, c) de un latente ztz_t de 16 números, en el paso tt, dado el vector cc de la frase. Al entrenar, la frase se sustituye por la frase vacía ∅\varnothing el 10 % de las veces (como en Stable Diffusion v1-4). Al muestrear, con escala de guiado ss:

ϵ^=ϵθ(zt,t,∅)+s [ϵθ(zt,t,c)−ϵθ(zt,t,∅)]\hat\epsilon = \epsilon_\theta(z_t, t, \varnothing) + s\,\big[\epsilon_\theta(z_t, t, c) - \epsilon_\theta(z_t, t, \varnothing)\big]

Con s=0s = 0 la frase no cuenta; con s=1s = 1 es la red condicionada tal cual; con s>1s > 1 se exagera. Es la convención de la biblioteca diffusers (escala por omisión 7.5, «activa cuando es mayor que 1»). Ho y Salimans escriben lo mismo como (1+w) ϵc−w ϵ∅(1+w)\,\epsilon_c - w\,\epsilon_\varnothing, con w=s−1w = s - 1, y lo presentan como un equilibrio entre calidad de las muestras y diversidad. GLIDE (Nichol y colaboradores, 2021) ya lo usaba con texto, y los evaluadores humanos lo prefirieron al guiado con CLIP.

Nuestro muestreo sigue la receta de la lección 17: T=40T = 40 pasos, βt\beta_t lineal de 0.02 a 0.30 y varianza del paso inverso σt2=βt\sigma_t^2 = \beta_t. El latente sale de un VAE de 16 números y se decodifica al final. Stable Diffusion condiciona de otra manera (atención cruzada sobre los vectores de cada palabra del codificador de texto de CLIP); aquí, para que quepa en el navegador, el vector de la frase se pega a la entrada de una red de tres capas.

Lo que midió la escena

  • Escala de guiado con «círculo» (256 ruidos iniciales): círculos 36 % con s=0s = 0, 80 % con s=1s = 1, 95 % con s=2s = 2, 93 % con s=4s = 4 y 63 % con s=8s = 8. Las veinticuatro imágenes de la escena (semillas 1000 a 1023, prompt «círculo») dan 11, 19, 21 y 16 círculos con s=0,1,3,8s = 0, 1, 3, 8, y 18, 12, 7 y 7 combinaciones distintas de forma, color y fondo (con el prompt en inglés, «circle»: 11, 20, 23 y 13 círculos; 18, 11, 6 y 8 combinaciones).
  • Sesgo: en los datos, el 64.9 % de los círculos son magenta (una de cada dos imágenes lleva el color típico de su forma y la otra, uno al azar). Entre las veinticuatro imágenes, 15 son magenta con s=1s = 1 y 22 con s=3s = 3.
  • Lo nunca visto (diez combinaciones fuera del entrenamiento, 16 ruidos por combinación, s=3s = 3): 86.4 % correctas en las 70 combinaciones vistas y 75.6 % en las 10 nunca vistas. Con s=1s = 1 la diferencia es mayor: 85.6 % frente a 45.6 %.
  • Quién va con quién (60 parejas con los colores intercambiados, en los dos idiomas): el codificador que lee el orden elige la frase correcta el 100 % de las veces; la bolsa de palabras da exactamente el mismo vector a las dos frases (0 %: siempre empate).

Las cuentas de forma y color las hace un lector de reglas fijas, no aprendido: el fondo es el color más común en el borde, la figura es el resto, y la forma es la plantilla (círculo, cuadrado, triángulo o cruz, en varias posiciones y tamaños) que mejor se superpone; si ninguna supera 0.6 de intersección sobre unión, la imagen cuenta como «sin forma». Lee bien las 20 imágenes reales de la lección. Con los cuadrados es menos fiable: el modelo los dibuja a menudo con esquinas redondeadas y el lector los toma por círculos, por eso la escena no los usa para contar.

En código

import numpy as np

def perdida_contrastiva(U, V, tau=0.07):
    """U, V: vectores unitarios de N imágenes y N frases (fila i = par i)."""
    S = U @ V.T / tau
    S = S - S.max(axis=1, keepdims=True)
    filas = -np.mean(np.diag(S) - np.log(np.exp(S).sum(axis=1)))
    S2 = (U @ V.T / tau).T
    S2 = S2 - S2.max(axis=1, keepdims=True)
    cols = -np.mean(np.diag(S2) - np.log(np.exp(S2).sum(axis=1)))
    return (filas + cols) / 2

rng = np.random.default_rng(0)
U = rng.normal(size=(4, 8)); U /= np.linalg.norm(U, axis=1, keepdims=True)
V_azar = rng.normal(size=(4, 8)); V_azar /= np.linalg.norm(V_azar, axis=1, keepdims=True)
V_bien = U + 0.1 * rng.normal(size=(4, 8)); V_bien /= np.linalg.norm(V_bien, axis=1, keepdims=True)
print(round(perdida_contrastiva(U, V_azar), 3), round(perdida_contrastiva(U, V_bien), 6))

def guiado(e_sin, e_con, s):
    return e_sin + s * (e_con - e_sin)

e_sin, e_con = np.array([0.2, -0.4]), np.array([0.5, 0.1])
for s in (0, 1, 3):
    print(s, guiado(e_sin, e_con, s))
# 6.064 0.000141
# 0 [ 0.2 -0.4]
# 1 [0.5 0.1]
# 3 [1.1 1.1]

Con frases al azar el error es alto; con frases casi iguales a su imagen, la diagonal domina y el error cae a casi cero. La segunda función es toda la escala de guiado.

Lo que viene

Aquí el texto solo entraba: se convertía en un vector. En la lección 19 el texto sale: un modelo de lenguaje asigna probabilidades a la siguiente palabra y escribe una palabra tras otra.

Lente de decisión

Qué significa esta idea si tu trabajo es decidir, no programar.

  • Procedencia y derechos: pregunta con qué datos se entrenó el modelo, con qué licencias y qué cubre el proveedor si hay un reclamo. La Oficina de Derechos de Autor de Estados Unidos reportó en 2025 decenas de demandas pendientes sobre el uso de obras para entrenar; la respuesta legal aún no está fijada.
  • Suplantación: prohíbe en tu política generar imágenes de personas reales sin su consentimiento, revisa lo que se publica y no aceptes una imagen sola como prueba. Lo que tú publiques, márcalo: credenciales de contenido C2PA y, si el proveedor lo ofrece, marca de agua.
  • Sesgos: el modelo repite y, con guiado, exagera lo frecuente en sus datos. Audita con muchas imágenes por prompt (no con una), sobre todo cuando aparecen personas, y revisa a quién representa y cómo.
  • Control y reproducibilidad: guarda el prompt, la semilla y la escala de guiado de cada imagen que uses. Más guiado no siempre es mejor: reduce la variedad y, si se exagera, deforma.

Términos de la lección

Transcripción completa
ComentariosConversación pública de esta lección: dudas, datos por revisar, ideas.

Los comentarios viven en GitHub Discussions, en el repositorio público del curso; para escribir se necesita una cuenta de GitHub. Se cargan desde giscus.app al abrir esta sección. Las personas que revisan el curso los leen, y si un cambio se acepta, se aplica en los dos idiomas. Abrir el hilo en GitHub

Fuentes