📖 Teoría

Transformers

Desde la atención en RNNs hasta "Attention Is All You Need": la arquitectura que revolucionó el deep learning. Positional encoding, multi-head attention, encoder-decoder, entrenamiento con warmup y teacher forcing, código completo en PyTorch y TensorFlow, BERT vs GPT, T5, LLMs, Vision Transformers, Whisper, series temporales, DiT y más.

¿Qué es un Transformer?

Un Transformer es una arquitectura de red neuronal basada enteramente en mecanismos de atención, sin recurrencia ni convoluciones. Fue propuesta en 2017 por Vaswani et al. en el paper "Attention Is All You Need" y ha revolucionado prácticamente todos los campos del deep learning: procesamiento de lenguaje natural, visión por computador, generación de audio, series temporales, y más.

💡 En una frase: Un Transformer procesa toda la secuencia de entrada en paralelo usando atención, en lugar de recorrerla token a token como una RNN. Esto lo hace mucho más rápido de entrenar y capaz de capturar dependencias a larga distancia.

📐 Idea central

El Transformer se basa en un mecanismo llamado self-attention (autoatención): cada elemento de la secuencia puede «mirar» a todos los demás elementos y decidir cuánta atención prestar a cada uno. Matemáticamente:

$$\text{Attention}(Q, K, V) = \text{softmax}\!\left(\frac{QK^\top}{\sqrt{d_k}}\right) V$$

donde \(Q\) (queries), \(K\) (keys) y \(V\) (values) son proyecciones lineales de la entrada, y \(d_k\) es la dimensión de las keys.

Pero para entender por qué el Transformer fue tan revolucionario, necesitamos entender lo que había antes: las RNNs, sus limitaciones, y cómo surgió la idea de la atención.

El camino hacia la atención: de las RNNs al Transformer

La historia del Transformer es la historia de cómo el deep learning aprendió a prestar atención. Antes de 2017, el paradigma dominante para procesar secuencias (texto, audio, series temporales) eran las Redes Neuronales Recurrentes (RNNs).

El problema de las RNNs

Las RNNs procesan la secuencia paso a paso, manteniendo un estado oculto \(h_t\) que se actualiza en cada timestep. Esto tiene dos problemas fundamentales:

🐌
Procesamiento secuencial
Como cada paso depende del anterior, no se puede paralelizar. Entrenar una RNN con secuencias largas es extremadamente lento.
📉
Vanishing gradients
La información de los primeros tokens se «diluye» al pasar por muchos pasos. Las dependencias a larga distancia se pierden.
🧠
Cuello de botella
En seq2seq (encoder-decoder), toda la información de la secuencia de entrada debe comprimirse en un único vector de contexto \(c\).
PROBLEMA: CUELLO DE BOTELLA EN SEQ2SEQ ENCODER h₁ h₂ h₃ h₄ El gato come pescado c (vector) ⚠️ TODO comprimido aquí DECODER s₁ s₂ s₃ s₄ The cat eats fish Toda la información de «El gato come pescado» debe pasar por un único vector c → Funciona mal con secuencias largas. Se pierde información del principio.

Las LSTMs y GRUs mitigaron parcialmente el problema de vanishing gradients con gates, pero el cuello de botella y la falta de paralelismo seguían siendo fundamentales.

El nacimiento de la atención (Bahdanau, 2014)

La idea que cambió todo fue simple pero brillante: en lugar de comprimir toda la secuencia en un único vector, permitir que el decoder mire directamente a cada posición del encoder en cada paso de generación.

🧠 La intuición de Bahdanau: Cuando traduces una frase, no memorizas toda la frase en un bloque y luego la traduces. En cada palabra que generas, vuelves a mirar las partes relevantes de la frase original. Eso es la atención.

Bahdanau, Cho & Bengio (2014) propusieron un mecanismo de atención aditiva para modelos seq2seq de traducción automática. En cada paso del decoder \(t\), se calcula un score de atención \(e_{t,i}\) entre el estado del decoder \(s_t\) y cada estado del encoder \(h_i\):

$$e_{t,i} = v^\top \tanh(W_s s_{t-1} + W_h h_i)$$
$$\alpha_{t,i} = \frac{\exp(e_{t,i})}{\sum_{j=1}^{n} \exp(e_{t,j})} \qquad c_t = \sum_{i=1}^{n} \alpha_{t,i} \, h_i$$

Los pesos \(\alpha_{t,i}\) indican cuánta atención presta el decoder al token \(i\) cuando genera el token \(t\). El vector de contexto \(c_t\) es ahora diferente en cada paso: ya no hay cuello de botella.

SOLUCIÓN: ATENCIÓN (Bahdanau et al. 2014) h₁ h₂ h₃ h₄ El gato come pescado α=0.05 α=0.10 α=0.65 α=0.20 s₃ "eats" c₃ = Σ αᵢ hᵢ contexto dinámico Al generar "eats", el decoder presta más atención a "come" (α=0.65) que a "El" (α=0.05)

Este paper fue un punto de inflexión. De repente, los modelos de traducción mejoraron drásticamente, y la idea de «atención» se convirtió en una herramienta fundamental en el toolkit del deep learning.

Atención multiplicativa (Luong, 2015)

Poco después, Luong et al. (2015) propusieron una variante más simple y eficiente: la atención multiplicativa (dot-product attention), que calcula la similitud directamente con un producto escalar:

$$e_{t,i} = s_t^\top h_i \qquad \text{(o bien } s_t^\top W h_i \text{ para la versión general)}$$
Tipo Fórmula del score Complejidad Ref
Aditiva (Bahdanau) \(v^\top \tanh(W_s s + W_h h)\) O(d) params extra arXiv:1409.0473
Multiplicativa (Luong) \(s^\top W h\) Más eficiente arXiv:1508.04025
Scaled Dot-Product \(\frac{q^\top k}{\sqrt{d_k}}\) La del Transformer arXiv:1706.03762

La atención multiplicativa de Luong tiene la misma capacidad que la aditiva de Bahdanau, pero es más eficiente computacionalmente. La scaled dot-product attention del Transformer es una evolución directa de esta idea.

Self-Attention: el salto conceptual

Hasta 2016, la atención siempre era cross-attention: el decoder mira al encoder. Pero la pregunta clave que llevó al Transformer fue:

💡 ¿Y si cada token pudiera prestar atención a todos los demás tokens de su propia secuencia? Es decir, ¿y si eliminamos las RNNs por completo y usamos solo atención para construir representaciones contextuales?

Esta idea — la self-attention o autoatención — fue la revolución. En lugar de procesar la secuencia paso a paso (RNN) o con filtros locales (CNN), cada token computa una representación que depende de toda la secuencia, ponderada por relevancia.

🔑 Self-attention vs Cross-attention

  • Self-attention: Q, K, V vienen de la misma secuencia. Cada token de la frase mira a todos los demás tokens de la misma frase.
  • Cross-attention: Q viene del decoder, K y V del encoder. El decoder mira a la secuencia de entrada.

El paper "Attention Is All You Need" demostró que con self-attention apilada en varias capas, más normalización y conexiones residuales, se podía superar a las RNNs en traducción automática, y entrenar órdenes de magnitud más rápido gracias a la paralelización.

Historia del Transformer

2014
Seq2Seq + Atención (Bahdanau) — Primer mecanismo de atención para traducción con RNNs. El decoder puede «mirar» a cada posición del encoder. 📄 arXiv:1409.0473 — Bahdanau, Cho & Bengio
2015
Atención multiplicativa (Luong) — Variante más eficiente de la atención con dot-product. 📄 arXiv:1508.04025 — Luong, Pham & Manning
2017 (jun)
Attention Is All You Need — Vaswani et al. (Google Brain / Google Research) proponen el Transformer: un modelo encoder-decoder basado enteramente en self-attention. 📄 arXiv:1706.03762 — Vaswani, Shazeer, Parmar et al.
2018 (jun)
GPT-1 (OpenAI) — Decoder-only Transformer pre-entrenado con language modeling. Demuestra el poder del pre-training + fine-tuning. 📄 Radford et al. — "Improving Language Understanding by Generative Pre-Training"
2018 (oct)
BERT (Google) — Encoder-only Transformer pre-entrenado con Masked Language Model (MLM). Revoluciona el NLP con transfer learning bidireccional. 📄 arXiv:1810.04805 — Devlin, Chang, Lee & Toutanova
2019
GPT-2, T5, XLNet, RoBERTa — Explosión de modelos Transformer. T5 unifica todas las tareas NLP como text-to-text. 📄 arXiv:1910.10683 (T5) — Raffel et al.
2020
GPT-3 (175B params), ViT — GPT-3 demuestra el scaling de los LLMs. Vision Transformer (ViT) lleva los Transformers a visión por computador. 📄 arXiv:2005.14165 (GPT-3) · arXiv:2010.11929 (ViT)
2022-23
ChatGPT, LLaMA, Whisper, DiT — Los Transformers dominan: chatbots (ChatGPT), open-source (LLaMA), audio (Whisper), y generación de imágenes (DiT en difusión). 📄 arXiv:2302.13971 (LLaMA) · arXiv:2212.09748 (DiT)
2024+
GPT-4o, Gemini, Claude, Sora, Mamba — Transformers multimodales (texto+imagen+audio+vídeo). Se exploran alternativas (Mamba, State Space Models), pero el Transformer sigue siendo la arquitectura dominante.

El paper: "Attention Is All You Need"

El paper de Vaswani et al. (2017) es uno de los más citados en la historia de la IA (>130.000 citas). Propone una arquitectura radicalmente simple que prescinde de toda recurrencia y convolución:

🏗️
Encoder-Decoder
6 capas en el encoder y 6 en el decoder. Cada capa tiene self-attention + feed-forward network.
👁️
Multi-Head Attention
8 «cabezas» de atención que aprenden relaciones diferentes en paralelo.
📍
Positional Encoding
Funciones sinusoidales para codificar la posición de cada token (sin recurrencia).
Paralelización total
Toda la secuencia se procesa simultáneamente. Entrenamiento masivamente más rápido.
📊
Resultados BLEU
41.8 BLEU en EN→DE (WMT 2014), superando a todos los modelos seq2seq previos.
💰
Eficiencia
Entrenado en solo 3.5 días en 8 GPUs P100. Un orden de magnitud más rápido que RNNs equivalentes.
🧭 Hoja de ruta: En las siguientes secciones desgranamos cada componente del Transformer en detalle: embeddings y positional encoding, la arquitectura encoder-decoder, el mecanismo de atención (con widgets interactivos), entrenamiento práctico con código, y finalmente las aplicaciones que han conquistado el mundo (BERT, GPT, ViT, Whisper, etc.).

Visión general de la arquitectura

El Transformer original es un modelo encoder-decoder. El encoder procesa la secuencia de entrada completa y genera representaciones contextuales. El decoder genera la secuencia de salida token a token, usando tanto su propia secuencia parcial (self-attention con máscara) como la salida del encoder (cross-attention).

ARQUITECTURA DEL TRANSFORMER (Vaswani et al. 2017) ENCODER (×N) Input Embedding + Positional Encoding Multi-Head Self-Attention Q, K, V ← misma entrada Add & Layer Norm residual Feed-Forward Network 2 capas lineales + ReLU Add & Layer Norm output encoder "El gato come pescado" DECODER (×N) Output Embedding + Positional Encoding Masked Multi-Head Self-Attention causal mask: no ve el futuro Add & Layer Norm Multi-Head Cross-Attention Q ← decoder, K,V ← encoder K, V Add & Layer Norm Feed-Forward Network 2 capas lineales + ReLU Add & Layer Norm Linear → Softmax → Prob(next token) "The cat eats" (shifted right) N = 6 en el paper original · d_model = 512 · h = 8 cabezas · d_ff = 2048

Input Embeddings

El primer paso es convertir cada token (palabra, subpalabra, o carácter) en un vector denso de dimensión \(d_{\text{model}}\). Esto se hace con una capa de embedding aprendida:

$$\mathbf{e}_i = \text{Embedding}(x_i) \in \mathbb{R}^{d_{\text{model}}}$$

En el paper original, \(d_{\text{model}} = 512\). Los embeddings se multiplican por \(\sqrt{d_{\text{model}}}\) para escalar su magnitud relativa al positional encoding:

$$\mathbf{e}_i' = \mathbf{e}_i \cdot \sqrt{d_{\text{model}}}$$
📝 Tokenización: El Transformer no trabaja con palabras enteras sino con subpalabras (BPE, WordPiece, SentencePiece). Esto le permite manejar vocabularios de cualquier idioma, incluyendo palabras nunca vistas, dividiéndolas en partes más pequeñas.

Positional Encoding: ¿dónde está cada token?

Como el Transformer procesa toda la secuencia en paralelo (sin recurrencia), no tiene noción inherente de orden. Para que sepa que «El gato» es diferente de «gato El», se añade un positional encoding a cada embedding.

El paper original usa funciones sinusoidales con frecuencias diferentes para cada dimensión:

$$PE_{(pos, 2i)} = \sin\!\left(\frac{pos}{10000^{2i / d_{\text{model}}}}\right)$$
$$PE_{(pos, 2i+1)} = \cos\!\left(\frac{pos}{10000^{2i / d_{\text{model}}}}\right)$$

donde \(pos\) es la posición del token en la secuencia e \(i\) es la dimensión. Las dimensiones bajas varían rápidamente (alta frecuencia), las altas varían lentamente (baja frecuencia), creando un patrón único para cada posición.

🤔 ¿Por qué seno y coseno?

  • Cada posición tiene un vector único que la identifica.
  • Las distancias relativas se capturan: \(PE_{pos+k}\) puede expresarse como una función lineal de \(PE_{pos}\) para cualquier offset \(k\).
  • Se generaliza a longitudes no vistas: no requiere aprender un embedding para cada posición.

Una alternativa al PE sinusoidal es aprender los embeddings de posición como parámetros del modelo (como en GPT y BERT). Vaswani et al. encontraron que ambos enfoques producían resultados similares. En la práctica moderna:

TipoUsado enVentajaLimitación
Sinusoidal Transformer original Generaliza a cualquier longitud Patrón fijo, no adaptativo
Aprendido (absoluto) GPT, BERT Se adapta a la tarea Limitado a max_length visto
Relativo (Shaw et al.) Transformer-XL, T5 Captura relaciones relativas Más complejo
RoPE (Rotary) LLaMA, GPT-NeoX Combina absoluto + relativo, escalable Algo más costoso
ALiBi BLOOM, MPT Bias lineal, extrapolación a secuencias largas Menos expresivo
🧪 Widget: Más adelante podrás explorar interactivamente cómo se ve el positional encoding sinusoidal y cómo cambia con la posición y la dimensión.

El Encoder: apilar autoatención

El encoder consiste en \(N\) capas idénticas apiladas (N=6 en el original). Cada capa tiene exactamente dos subcapas:

1
Multi-Head Self-Attention: Cada token mira a todos los demás tokens de la misma secuencia. Las queries, keys y values vienen todos de la salida de la capa anterior (o del embedding + PE en la primera capa).
2
Feed-Forward Network (FFN): Dos transformaciones lineales con una ReLU en medio, aplicada posición por posición (idéntica para cada token):
$$\text{FFN}(x) = W_2 \cdot \text{ReLU}(W_1 x + b_1) + b_2$$
donde \(W_1 \in \mathbb{R}^{d_{\text{model}} \times d_{ff}}\) y \(W_2 \in \mathbb{R}^{d_{ff} \times d_{\text{model}}}\), con \(d_{ff} = 2048\).

Cada subcapa tiene una conexión residual y layer normalization:

$$\text{output} = \text{LayerNorm}(x + \text{Sublayer}(x))$$

Batch Normalization normaliza a lo largo del batch (estadísticas sobre todos los ejemplos del mini-batch). Funciona bien en CNNs, pero tiene problemas con secuencias de longitud variable.

Layer Normalization normaliza a lo largo de las features dentro de cada ejemplo. Es independiente del batch y funciona perfectamente con secuencias de cualquier longitud:

$$\text{LN}(x) = \frac{x - \mu}{\sigma + \epsilon} \cdot \gamma + \beta$$

donde \(\mu, \sigma\) se calculan sobre las dimensiones de cada vector individual, y \(\gamma, \beta\) son parámetros aprendidos.

El Decoder: generar token a token

El decoder también tiene \(N\) capas, pero cada capa tiene tres subcapas:

1
Masked Multi-Head Self-Attention: Igual que en el encoder, pero con una máscara causal que impide que cada token vea a los tokens futuros. Esto es esencial para la generación autoregresiva.
2
Multi-Head Cross-Attention: Las queries vienen del decoder, pero las keys y values vienen de la salida del encoder. Esto permite al decoder «mirar» la secuencia de entrada completa.
3
Feed-Forward Network: Idéntica a la del encoder.
🎭 La máscara causal: Es una matriz triangular inferior que se añade a los scores de atención antes del softmax. Las posiciones «futuras» reciben un valor de \(-\infty\) que, tras el softmax, se convierten en 0. Así, el token en la posición \(t\) solo puede atender a posiciones \(\leq t\).
$$\text{Mask} = \begin{pmatrix} 0 & -\infty & -\infty & -\infty \\ 0 & 0 & -\infty & -\infty \\ 0 & 0 & 0 & -\infty \\ 0 & 0 & 0 & 0 \end{pmatrix}$$

Capa de salida: Linear + Softmax

La salida del decoder pasa por una capa lineal que proyecta de \(d_{\text{model}}\) al tamaño del vocabulario \(V\), seguida de un softmax para obtener probabilidades:

$$P(\text{next token} = w_j) = \text{softmax}(W_o \cdot h_t + b_o)_j$$

🔄 Weight tying

Una técnica habitual (usada en el paper original) es compartir pesos entre la capa de embedding de entrada, la de salida del decoder, y la capa lineal final. Esto reduce el número de parámetros significativamente y mejora la generalización.

Hiperparámetros del Transformer original

Parámetro Símbolo Valor (base) Valor (big) Descripción
Capas \(N\) 6 6 Número de capas encoder/decoder
Dimensión del modelo \(d_{\text{model}}\) 512 1024 Dimensión de embeddings y representaciones
Cabezas de atención \(h\) 8 16 Número de heads en multi-head attention
Dimensión por head \(d_k = d_v\) 64 64 \(d_{\text{model}} / h\)
FFN dimensión interna \(d_{ff}\) 2048 4096 Hidden size del Feed-Forward Network
Dropout \(p\) 0.1 0.3 Aplicado en residuals, attention, FFN
Parámetros totales 65M 213M Pequeño para estándares actuales

Comparado con los modelos actuales (GPT-4 tiene ~1.7T parámetros estimados, LLaMA 3 tiene hasta 405B), el Transformer original era sorprendentemente pequeño. La arquitectura ha escalado verticalmente, pero los principios fundamentales son exactamente los mismos.

Widget: explorador de Positional Encoding

Visualiza cómo varían las funciones sinusoidales del positional encoding según la posición y la dimensión. Observa cómo las frecuencias bajas (dimensiones altas) varían lentamente, creando patrones únicos para cada posición.

🧪 Positional Encoding Sinusoidal

Scaled Dot-Product Attention

El bloque fundamental del Transformer es la Scaled Dot-Product Attention. Cada token genera tres vectores: una query (\(Q\)), una key (\(K\)) y un value (\(V\)), obtenidos multiplicando la entrada por matrices de pesos aprendidas:

$$Q = XW^Q, \quad K = XW^K, \quad V = XW^V$$

La atención se calcula como:

$$\text{Attention}(Q, K, V) = \text{softmax}\!\left(\frac{QK^\top}{\sqrt{d_k}}\right) V$$

🔑 Intuición Q, K, V

Piensa en una búsqueda en una base de datos:

  • Query (Q): «¿Qué estoy buscando?» — La pregunta que hace cada token.
  • Key (K): «¿Qué tengo para ofrecer?» — La etiqueta de cada token.
  • Value (V): «¿Qué información contiene?» — El contenido real de cada token.

La similitud entre Q y K (dot product) determina cuánta atención prestar a cada V. Los tokens con keys más similares a la query reciben más peso.

¿Por qué dividir entre \(\sqrt{d_k}\)?

Cuando \(d_k\) es grande, los dot products \(q \cdot k\) crecen en magnitud, lo que empuja al softmax a regiones de gradientes muy pequeños (saturación). Dividir entre \(\sqrt{d_k}\) normaliza la varianza de los scores a 1, manteniendo los gradientes saludables:

$$\text{Var}(q \cdot k) = d_k \quad \Rightarrow \quad \text{Var}\!\left(\frac{q \cdot k}{\sqrt{d_k}}\right) = 1$$

Si \(q_i, k_i \sim \mathcal{N}(0, 1)\) son independientes, el producto \(q_i k_i\) tiene media 0 y varianza 1. La suma de \(d_k\) de estos productos:

$$q \cdot k = \sum_{i=1}^{d_k} q_i k_i \quad \Rightarrow \quad \text{Var}(q \cdot k) = d_k \cdot \text{Var}(q_i k_i) = d_k$$

Con \(d_k = 64\), los scores no escalados tienen una desviación estándar de \(\sqrt{64} = 8\), lo que empujaría al softmax a dar probabilidad ~1 al máximo y ~0 a todo lo demás. Dividir entre \(\sqrt{d_k}\) restabiliza los gradientes.

Multi-Head Attention

En lugar de calcular una única función de atención, el Transformer usa múltiples cabezas (heads) que operan en paralelo. Cada head aprende a prestar atención a un tipo diferente de relación:

$$\text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, \ldots, \text{head}_h) \, W^O$$
$$\text{head}_i = \text{Attention}(QW_i^Q,\; KW_i^K,\; VW_i^V)$$

Con \(h = 8\) cabezas y \(d_{\text{model}} = 512\), cada head trabaja con vectores de dimensión \(d_k = d_v = 512 / 8 = 64\). Los resultados de las 8 heads se concatenan y se proyectan con \(W^O \in \mathbb{R}^{hd_v \times d_{\text{model}}}\).

MULTI-HEAD ATTENTION (h=8) Input (Q, K, V) Head 1 Attn(QW₁ᵠ, KW₁ᵏ, VW₁ᵛ) Head 2 d_k=64 Head 3 d_k=64 ··· Head 6 d_k=64 Head 7 d_k=64 Head 8 d_k=64 Concat → Linear W_O (512×512) Output (d_model = 512)
💡 ¿Qué aprende cada head? Investigaciones empíricas han mostrado que diferentes heads aprenden relaciones distintas: una head puede capturar relaciones sintácticas (sujeto-verbo), otra relaciones posicionales (tokens cercanos), otra semánticas (sinónimos), etc. Esto es análogo a cómo diferentes filtros de una CNN aprenden features distintas.

Self-Attention: paso a paso con ejemplo

Veamos el cálculo completo de self-attention para la frase «El gato duerme» con \(d_k = 4\) (simplificado para visualización):

1
Proyectar Q, K, V: Multiplicar la entrada \(X \in \mathbb{R}^{3 \times d_{\text{model}}}\) por las matrices de pesos \(W^Q, W^K, W^V\) para obtener queries, keys y values de cada token.
2
Calcular scores: \(S = QK^\top \in \mathbb{R}^{3 \times 3}\). Cada \(S_{ij}\) mide la compatibilidad entre el token \(i\) (como query) y el token \(j\) (como key).
3
Escalar: \(S' = S / \sqrt{d_k}\). Previene saturación del softmax.
4
Softmax por filas: \(\alpha = \text{softmax}(S')\). Cada fila suma 1 y contiene los pesos de atención.
5
Weighted sum de values: \(\text{output} = \alpha V\). Cada token obtiene una combinación ponderada de los values de todos los tokens.
EJEMPLO: MATRIZ DE ATENCIÓN (softmax(QKᵀ/√d_k)) Keys → El gato duerme Queries El gato duerme 0.50 0.30 0.20 0.15 0.55 0.30 0.10 0.40 0.50 ← "El" presta más atención a sí mismo (artículo) ← "gato" atiende mucho a sí mismo (sustantivo principal) ← "duerme" mira a "gato" (su sujeto) y a sí mismo Cada fila suma 1.0 · Los valores más altos (más oscuros) indican más atención

Cross-Attention: el puente encoder-decoder

En el decoder, además de la self-attention (masked), hay una capa de cross-attention donde:

  • Queries (\(Q\)) vienen de la capa anterior del decoder.
  • Keys (\(K\)) y Values (\(V\)) vienen de la salida del encoder.

Esto permite al decoder consultar la secuencia de entrada completa en cada paso de generación. Es el equivalente moderno del mecanismo de atención de Bahdanau, pero integrado en la arquitectura del Transformer sin RNNs.

🔄 Tres tipos de atención en un Transformer

TipoQ deK, V deDóndeMáscara
Self-Attention (encoder) Encoder Encoder Encoder layers Sin máscara
Masked Self-Attention Decoder Decoder Decoder layers Causal (triangular)
Cross-Attention Decoder Encoder output Decoder layers Sin máscara

Masked Self-Attention: no mirar al futuro

En el decoder, la self-attention debe ser causal: el token en la posición \(t\) solo puede atender a las posiciones \(1, 2, \ldots, t\). Esto se implementa sumando una máscara al score antes del softmax:

$$\text{MaskedAttn}(Q, K, V) = \text{softmax}\!\left(\frac{QK^\top}{\sqrt{d_k}} + M\right) V$$

donde \(M_{ij} = 0\) si \(j \leq i\), y \(M_{ij} = -\infty\) si \(j > i\). Tras el softmax, \(e^{-\infty} = 0\), así que los tokens futuros tienen peso cero.

MÁSCARA CAUSAL (4 tokens) t₁ t₂ t₃ t₄ -∞ -∞ -∞ -∞ -∞ -∞ t₁ t₂ t₃ t₄ t₁ solo se ve a sí mismo t₂ ve t₁ y t₂ t₃ ve t₁, t₂, t₃ t₄ ve todo

Complejidad computacional

La self-attention tiene complejidad \(O(n^2 \cdot d)\) donde \(n\) es la longitud de la secuencia y \(d\) es la dimensión. Esto es cuadrático en la longitud, lo que se vuelve problemático para secuencias muy largas.

Operación Complejidad por capa Longitud de secuencia Paralelización
Self-Attention \(O(n^2 \cdot d)\) \(O(1)\) path máximo \(O(1)\) — total ⚡
RNN \(O(n \cdot d^2)\) \(O(n)\) path máximo \(O(n)\) — secuencial 🐌
CNN (kernel k) \(O(k \cdot n \cdot d^2)\) \(O(\log_k(n))\) dilatada \(O(1)\) — paralela

La complejidad \(O(n^2)\) ha motivado mucha investigación en «efficient attention»:

  • Flash Attention (Dao et al., 2022): No cambia la complejidad computacional, pero optimiza el acceso a memoria GPU para ser 2-4× más rápido. Es el estándar en la práctica moderna.
  • Linear Attention (Katharopoulos et al., 2020): Reemplaza softmax por un kernel para lograr \(O(n \cdot d^2)\).
  • Sparse Attention (BigBird, Longformer): Solo atiende a un subconjunto de posiciones, logrando \(O(n \sqrt{n})\) o \(O(n)\).
  • Mamba / SSMs (Gu & Dao, 2023): Modelos de espacio de estados selectivos que logran \(O(n)\) con selectividad. Una alternativa al Transformer.

Widget: explorador de Self-Attention

Escribe una frase y visualiza cómo la self-attention asigna pesos entre tokens. Ajusta la temperatura (escala del softmax) para ver su efecto: valores bajos → atención más uniforme, valores altos → atención más concentrada.

🧪 Self-Attention Explorer

Función de pérdida: Cross-Entropy

El Transformer para traducción/generación se entrena con cross-entropy loss sobre el vocabulario de salida. En cada posición del decoder, el modelo predice una distribución de probabilidad sobre \(V\) tokens y la comparamos con el token correcto:

$$\mathcal{L} = -\frac{1}{T} \sum_{t=1}^{T} \log P_\theta(y_t \mid y_{

donde \(y_t\) es el token objetivo en la posición \(t\), \(y_{

El paper original usa label smoothing con \(\epsilon = 0.1\): en lugar de one-hot targets (1 para el token correcto, 0 para el resto), se usa:

$$y_{\text{smooth}} = (1 - \epsilon) \cdot y_{\text{one-hot}} + \frac{\epsilon}{V}$$

Esto penaliza al modelo por ser «demasiado seguro» de sus predicciones y mejora la generalización. El token correcto recibe probabilidad ~0.9 en lugar de 1.0, y los demás ~\(0.1 / V\) en lugar de 0.

Optimizador: Adam con warmup

El Transformer usa Adam con un esquema de learning rate especial que combina un warmup lineal con un decay proporcional a la raíz cuadrada inversa del paso:

$$lr = d_{\text{model}}^{-0.5} \cdot \min\!\left(\text{step}^{-0.5},\; \text{step} \cdot \text{warmup}^{-1.5}\right)$$

Con \(\text{warmup\_steps} = 4000\), el learning rate crece linealmente durante los primeros 4000 pasos y luego decrece proporcionalmente a \(1/\sqrt{\text{step}}\).

LEARNING RATE SCHEDULE (warmup=4000) 0 4000 steps warmup decay ∝ 1/√step lr
🤔 ¿Por qué warmup? Al inicio del entrenamiento, los pesos son aleatorios y los gradientes pueden ser muy grandes. El warmup permite que el modelo «se estabilice» antes de usar learning rates altos. Sin warmup, el entrenamiento de Transformers suele diverger.

Teacher Forcing

Durante el entrenamiento, el decoder recibe como entrada la secuencia objetivo desplazada una posición a la derecha (shifted right), en lugar de sus propias predicciones anteriores. Esto se llama teacher forcing:

1
Input del decoder: [BOS] The cat eats
2
Output esperado: The cat eats [EOS]
3
Gracias a la máscara causal, en cada posición el modelo solo ve los tokens anteriores, igual que en inferencia, pero se procesan todos en paralelo.

Implementación: Transformer simplificado

Veamos una implementación limpia del Transformer en PyTorch y TensorFlow. Incluye self-attention, multi-head attention, positional encoding, y el encoder completo.

import torch
import torch.nn as nn
import torch.nn.functional as F
import math

# ─── Positional Encoding (sinusoidal) ───
class PositionalEncoding(nn.Module):
    def __init__(self, d_model, max_len=5000, dropout=0.1):
        super().__init__()
        self.dropout = nn.Dropout(p=dropout)

        pe = torch.zeros(max_len, d_model)
        position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
        div_term = torch.exp(
            torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model)
        )
        pe[:, 0::2] = torch.sin(position * div_term)   # dimensiones pares
        pe[:, 1::2] = torch.cos(position * div_term)    # dimensiones impares
        pe = pe.unsqueeze(0)  # (1, max_len, d_model)
        self.register_buffer('pe', pe)

    def forward(self, x):
        # x: (batch, seq_len, d_model)
        x = x + self.pe[:, :x.size(1)]
        return self.dropout(x)

# ─── Scaled Dot-Product Attention ───
def scaled_dot_product_attention(Q, K, V, mask=None):
    """
    Q, K, V: (batch, heads, seq_len, d_k)
    mask: (batch, 1, 1, seq_len) or (1, 1, seq_len, seq_len) for causal
    """
    d_k = Q.size(-1)
    scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(d_k)

    if mask is not None:
        scores = scores.masked_fill(mask == 0, float('-inf'))

    attn_weights = F.softmax(scores, dim=-1)
    output = torch.matmul(attn_weights, V)
    return output, attn_weights

# ─── Multi-Head Attention ───
class MultiHeadAttention(nn.Module):
    def __init__(self, d_model, num_heads):
        super().__init__()
        assert d_model % num_heads == 0
        self.d_k = d_model // num_heads
        self.num_heads = num_heads

        self.W_q = nn.Linear(d_model, d_model)
        self.W_k = nn.Linear(d_model, d_model)
        self.W_v = nn.Linear(d_model, d_model)
        self.W_o = nn.Linear(d_model, d_model)

    def forward(self, Q, K, V, mask=None):
        batch_size = Q.size(0)

        # Linear projections + reshape to (batch, heads, seq, d_k)
        Q = self.W_q(Q).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
        K = self.W_k(K).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
        V = self.W_v(V).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)

        # Attention
        attn_output, attn_weights = scaled_dot_product_attention(Q, K, V, mask)

        # Concat heads + linear
        attn_output = attn_output.transpose(1, 2).contiguous().view(
            batch_size, -1, self.num_heads * self.d_k
        )
        return self.W_o(attn_output), attn_weights

# ─── Feed-Forward Network ───
class FeedForward(nn.Module):
    def __init__(self, d_model, d_ff, dropout=0.1):
        super().__init__()
        self.linear1 = nn.Linear(d_model, d_ff)
        self.linear2 = nn.Linear(d_ff, d_model)
        self.dropout = nn.Dropout(dropout)

    def forward(self, x):
        return self.linear2(self.dropout(F.relu(self.linear1(x))))

# ─── Encoder Layer ───
class EncoderLayer(nn.Module):
    def __init__(self, d_model, num_heads, d_ff, dropout=0.1):
        super().__init__()
        self.self_attn = MultiHeadAttention(d_model, num_heads)
        self.ffn = FeedForward(d_model, d_ff, dropout)
        self.norm1 = nn.LayerNorm(d_model)
        self.norm2 = nn.LayerNorm(d_model)
        self.dropout1 = nn.Dropout(dropout)
        self.dropout2 = nn.Dropout(dropout)

    def forward(self, x, mask=None):
        # Self-attention + residual + norm
        attn_out, _ = self.self_attn(x, x, x, mask)
        x = self.norm1(x + self.dropout1(attn_out))
        # FFN + residual + norm
        ffn_out = self.ffn(x)
        x = self.norm2(x + self.dropout2(ffn_out))
        return x

# ─── Encoder completo ───
class TransformerEncoder(nn.Module):
    def __init__(self, vocab_size, d_model=512, num_heads=8,
                 d_ff=2048, num_layers=6, dropout=0.1, max_len=5000):
        super().__init__()
        self.embedding = nn.Embedding(vocab_size, d_model)
        self.pos_encoding = PositionalEncoding(d_model, max_len, dropout)
        self.layers = nn.ModuleList([
            EncoderLayer(d_model, num_heads, d_ff, dropout)
            for _ in range(num_layers)
        ])
        self.d_model = d_model

    def forward(self, x, mask=None):
        # x: (batch, seq_len) of token ids
        x = self.embedding(x) * math.sqrt(self.d_model)
        x = self.pos_encoding(x)
        for layer in self.layers:
            x = layer(x, mask)
        return x

# ─── Uso ───
encoder = TransformerEncoder(vocab_size=32000)
tokens = torch.randint(0, 32000, (2, 50))  # batch=2, seq=50
output = encoder(tokens)
print(output.shape)  # torch.Size([2, 50, 512])
import tensorflow as tf
import numpy as np

# ─── Positional Encoding ───
def positional_encoding(max_len, d_model):
    positions = np.arange(max_len)[:, np.newaxis]
    dims = np.arange(d_model)[np.newaxis, :]
    angles = positions / np.power(10000, (2 * (dims // 2)) / d_model)
    angles[:, 0::2] = np.sin(angles[:, 0::2])
    angles[:, 1::2] = np.cos(angles[:, 1::2])
    return tf.cast(angles[np.newaxis, :, :], dtype=tf.float32)

# ─── Scaled Dot-Product Attention ───
def scaled_dot_product_attention(Q, K, V, mask=None):
    d_k = tf.cast(tf.shape(K)[-1], tf.float32)
    scores = tf.matmul(Q, K, transpose_b=True) / tf.math.sqrt(d_k)
    if mask is not None:
        scores += (mask * -1e9)
    weights = tf.nn.softmax(scores, axis=-1)
    return tf.matmul(weights, V), weights

# ─── Multi-Head Attention ───
class MultiHeadAttention(tf.keras.layers.Layer):
    def __init__(self, d_model, num_heads):
        super().__init__()
        self.num_heads = num_heads
        self.d_k = d_model // num_heads
        self.wq = tf.keras.layers.Dense(d_model)
        self.wk = tf.keras.layers.Dense(d_model)
        self.wv = tf.keras.layers.Dense(d_model)
        self.wo = tf.keras.layers.Dense(d_model)

    def split_heads(self, x, batch_size):
        x = tf.reshape(x, (batch_size, -1, self.num_heads, self.d_k))
        return tf.transpose(x, perm=[0, 2, 1, 3])

    def call(self, Q, K, V, mask=None):
        batch_size = tf.shape(Q)[0]
        Q = self.split_heads(self.wq(Q), batch_size)
        K = self.split_heads(self.wk(K), batch_size)
        V = self.split_heads(self.wv(V), batch_size)
        attn_out, attn_weights = scaled_dot_product_attention(Q, K, V, mask)
        attn_out = tf.transpose(attn_out, perm=[0, 2, 1, 3])
        attn_out = tf.reshape(attn_out, (batch_size, -1, self.num_heads * self.d_k))
        return self.wo(attn_out), attn_weights

# ─── Encoder Layer ───
class EncoderLayer(tf.keras.layers.Layer):
    def __init__(self, d_model, num_heads, d_ff, dropout_rate=0.1):
        super().__init__()
        self.mha = MultiHeadAttention(d_model, num_heads)
        self.ffn = tf.keras.Sequential([
            tf.keras.layers.Dense(d_ff, activation='relu'),
            tf.keras.layers.Dense(d_model)
        ])
        self.norm1 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
        self.norm2 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
        self.dropout1 = tf.keras.layers.Dropout(dropout_rate)
        self.dropout2 = tf.keras.layers.Dropout(dropout_rate)

    def call(self, x, mask=None, training=False):
        attn_out, _ = self.mha(x, x, x, mask)
        x = self.norm1(x + self.dropout1(attn_out, training=training))
        ffn_out = self.ffn(x)
        x = self.norm2(x + self.dropout2(ffn_out, training=training))
        return x

# ─── Uso ───
encoder_layer = EncoderLayer(d_model=512, num_heads=8, d_ff=2048)
sample = tf.random.uniform((2, 50, 512))
output = encoder_layer(sample)
print(output.shape)  # (2, 50, 512)

Trucos de entrenamiento

🔥
Warmup
Imprescindible. Sin warmup, el Transformer diverge. 4000 pasos es típico, pero se escala con el tamaño del modelo.
📏
Gradient Clipping
Clip the gradient norm to 1.0 para evitar explosiones, especialmente al inicio del entrenamiento.
🏷️
Label Smoothing
ε=0.1 mejora la generalización. El modelo no se sobreajusta a ser «100% seguro».
💧
Dropout
Dropout=0.1 en residuals, attention weights y FFN. En modelos grandes, a veces se reduce o elimina.
Mixed Precision
FP16/BF16 para reducir memoria y acelerar. Imprescindible para modelos grandes. BF16 preferido por estabilidad.
📦
Gradient Accumulation
Simular batches grandes acumulando gradientes durante varios micro-batches antes de hacer el update.
Hiperparámetro Paper original Modelos modernos (GPT-3+) Notas
Optimizer Adam (β₁=0.9, β₂=0.98) AdamW (weight decay) AdamW separa weight decay de lr
LR Schedule Warmup + inverse sqrt Cosine annealing Cosine suele funcionar mejor
Batch size ~25k tokens ~1-4M tokens Batch size grande = más estable
Precisión FP32 BF16 + loss scaling Necesario para escalar
Paralelismo 8 GPUs (data parallel) Tensor + Pipeline + Data parallel Miles de GPUs para GPT-4

Inferencia: generación autoregresiva

En inferencia, el decoder genera un token a la vez. En cada paso, toma toda la secuencia generada hasta el momento, pasa por el decoder, y predice el siguiente token:

1
Inicializar con [BOS] (beginning of sequence).
2
Pasar por el decoder → obtener logits para el siguiente token.
3
Aplicar estrategia de decodificación (greedy, beam search, sampling, top-k, top-p/nucleus).
4
Añadir token al output y repetir desde el paso 2.
5
Parar al generar [EOS] o alcanzar la longitud máxima.
EstrategiaDescripciónProsContras
Greedy Elegir siempre el token más probable Rápido, determinista Repetitivo, no óptimo globalmente
Beam Search Mantener los \(k\) mejores candidatos Mejor calidad que greedy Lento, poco diverso
Temperature Sampling Muestrear de \(P^\tau\) (τ > 1 = más aleatorio) Diverso, creativo Puede generar basura con τ alto
Top-k Solo considerar los \(k\) tokens más probables Buen balance \(k\) fijo no se adapta al contexto
Top-p (Nucleus) Tokens cuya probabilidad acumulada ≤ \(p\) Adaptativo, muy usado Requiere ajustar \(p\)
⚡ KV-Cache: En inferencia, re-computar toda la atención en cada paso es costoso. El KV-cache almacena las keys y values computadas en pasos anteriores y solo computa la nueva query, reduciendo la complejidad de \(O(n^2)\) por paso a \(O(n)\). Es fundamental para la velocidad de los LLMs modernos.

El éxito del Transformer en NLP

La arquitectura Transformer transformó (literalmente) el procesamiento de lenguaje natural. La idea clave fue el pre-training a gran escala: entrenar un Transformer enorme con cantidades masivas de texto, y luego fine-tunear para tareas específicas. Esto dio lugar a dos paradigmas fundamentales:

📖
Encoder-Only (BERT)
Pre-entrenado con Masked Language Model (MLM): predecir palabras enmascaradas. Bidireccional: cada token ve toda la secuencia.

Ideal para: clasificación, NER, QA, embedding de texto.
✍️
Decoder-Only (GPT)
Pre-entrenado con Causal Language Model (CLM): predecir el siguiente token. Unidireccional: cada token solo ve los anteriores.

Ideal para: generación de texto, chatbots, code completion.

Y existe un tercer paradigma que combina ambos:

🔄
Encoder-Decoder (T5, BART)
Usa el Transformer completo (encoder + decoder). El encoder procesa la entrada bidireccionalmente; el decoder genera la salida autoregressivamente.

Ideal para: traducción, resumen, text-to-text en general.

BERT: Bidirectional Encoder Representations from Transformers

BERT (Devlin et al., 2018) fue el primer modelo que demostró el poder del pre-training bidireccional. Solo usa el encoder del Transformer.

🎯 Pre-entrenamiento de BERT

BERT se pre-entrena con dos objetivos:

  1. Masked Language Model (MLM): Se enmascara el 15% de los tokens (reemplazándolos por [MASK]) y el modelo debe predecirlos. Esto fuerza representaciones bidireccionales.
  2. Next Sentence Prediction (NSP): Dado un par de frases, predecir si la segunda sigue a la primera en el texto original.
BERT — ENCODER-ONLY [CLS] El [MASK] come pescado [SEP] Transformer Encoder × 12 (BERT-base) / × 24 (BERT-large) Self-Attention BIDIRECCIONAL → cada token ve TODA la secuencia → "gato" [CLS] → clasificar
ModeloCapasd_modelHeadsParams
BERT-base1276812110M
BERT-large24102416340M

GPT: Generative Pre-trained Transformer

GPT (Radford et al., 2018) toma el camino opuesto a BERT: usa solo el decoder del Transformer con masked self-attention (causal), entrenado para predecir el siguiente token.

GPT — DECODER-ONLY (CAUSAL) El gato come pescado ??? Transformer Decoder × 12 (GPT-1) / × 96 (GPT-3) Masked Self-Attention → cada token solo ve los ANTERIORES → P(next)
ModeloAñoCapasd_modelParamsContexto
GPT-1201812768117M512
GPT-220194816001.5B1024
GPT-320209612288175B2048
GPT-4 (est.)2023~120~?~1.7T (MoE)128k

BERT vs GPT: dos filosofías

Aspecto BERT (Encoder) GPT (Decoder)
Dirección Bidireccional Unidireccional (izq→der)
Pre-training MLM + NSP Causal LM (next token)
Uso principal Comprensión (clasificar, extraer) Generación (escribir, chatear)
Fine-tuning Añadir cabeza de clasificación Prompt engineering / RLHF
Atención Completa (ve todo) Causal (solo pasado)
Escala moderna ~340M (limitado) ~1.7T (escala extrema)
Herederos RoBERTa, ALBERT, DeBERTa, ModernBERT GPT-4, LLaMA, Claude, Gemini
🔮 En la práctica (2024+): Los decoder-only (estilo GPT) han ganado la carrera: escalan mejor, son más versátiles (pueden hacer clasificación y generación), y se benefician de in-context learning y prompting. BERT sigue siendo usado para tareas de embeddings y clasificación donde la bidireccionalidad importa.

T5: Text-to-Text Transfer Transformer

T5 (Raffel et al., 2019) unifica todas las tareas NLP bajo un mismo formato: text-to-text. Usa el Transformer completo (encoder-decoder) y trata cada tarea como una traducción entre textos:

🔄
Traducción
Input: translate English to German: The cat
Output: Die Katze
📝
Resumen
Input: summarize: [texto largo]
Output: [resumen]
QA
Input: question: ... context: ...
Output: [respuesta]
🏷️
Clasificación
Input: sentiment: Great movie!
Output: positive

LLMs: Large Language Models

Un Large Language Model (LLM) es un Transformer (generalmente decoder-only) entrenado con cantidades masivas de texto. A partir de cierta escala (~10B+ parámetros), emergen capacidades que no existían en modelos más pequeños:

💬
In-Context Learning
Aprender de ejemplos dados en el prompt, sin reentrenamiento.
🧠
Razonamiento
Chain-of-thought: resolver problemas paso a paso.
🛠️
Tool Use
Usar APIs, ejecutar código, buscar información.
🌐
Multilingüe
Traducir, entender y generar en decenas de idiomas.
💻
Código
Generar, completar y depurar código en múltiples lenguajes.
📚 Más en el submódulo de LLMs: Los LLMs tienen un submódulo propio donde cubrimos GPT en detalle, RLHF, fine-tuning, prompt engineering, RAG, y más. → Ir al submódulo de LLMs

Widget: visualizador de atención en traducción

Explora cómo funciona la cross-attention en un modelo de traducción. La matriz muestra cuánta atención presta cada token de salida (decoder) a cada token de entrada (encoder). Selecciona un par de frases y ajusta los parámetros.

🧪 Visualizador de Atención en Traducción

Transformers más allá del NLP

Lo que empezó como una arquitectura para traducción de texto se ha convertido en la columna vertebral de toda la IA moderna. La idea clave —procesar secuencias con self-attention en paralelo— funciona igual de bien con píxeles, ondas de audio, series temporales o combinaciones multimodales.

Transformer Self-Attention 👁️ Visión (ViT) 🎵 Audio (Whisper) 📈 Series temp. 🎨 Difusión (DiT) 🌐 Multimodal 📝 NLP (origen)

Vision Transformers (ViT)

ViT (Dosovitskiy et al., 2020) fue la primera demostración contundente de que los Transformers pueden competir con las CNNs en visión. La idea es radical por su simplicidad:

1
Divide la imagen en parches (e.g. 16×16 píxeles). Una imagen 224×224 produce 14×14 = 196 parches.
2
Proyecta cada parche a un embedding de dimensión d (proyección lineal: aplana el parche y multiplica por una matriz).
3
Añade un token [CLS] al inicio (como BERT) + positional embeddings aprendidos.
4
Pasa por un Transformer Encoder estándar. Self-attention entre parches: cada parche atiende a todos los demás.
5
Clasifica con el token [CLS] (MLP head sobre la representación final del token [CLS]).
ModeloAñoInnovación claveResultado
ViT2020 Parches → Transformer puro Competitivo con CNNs (necesita mucho dato)
DeiT2021 Data-efficient: distillation token ViT entrenado solo con ImageNet
Swin2021 Ventanas desplazadas (shifted windows) Complejidad lineal; backbone universal
DINO / DINOv22021/23 Self-supervised ViT con self-distillation Features visuales universales sin etiquetas
SAM2023 ViT para segmentación universal (Meta) Segmentar cualquier objeto con un click
📐 ViT vs CNN: ¿qué ventajas tiene?
  • Receptive field global: Self-attention ve toda la imagen desde la primera capa. Una CNN necesita muchas capas para campo receptivo amplio.
  • Sin sesgo inductivo local: El ViT no asume que píxeles cercanos están relacionados — lo aprende de los datos. Esto hace que escale mejor con más datos.
  • Arquitectura unificada: Mismo Transformer para texto, imagen, audio… facilita modelos multimodales.
  • Desventaja: Necesita muchos más datos que las CNNs (que tienen locality bias). DeiT y Swin mitigan esto.

Transformers para audio: Whisper

Whisper (Radford et al., 2022, OpenAI) es un Transformer encoder-decoder entrenado con 680.000 horas de audio (weakly supervised) que puede:

🎤
ASR
Transcripción de voz a texto en 100+ idiomas
🌍
Traducción
Traducción directa de audio (X→English)
🏷️
Detección
Detección de idioma, timestamps

🔊 ¿Cómo procesa el audio?

  1. Convierte el audio a un espectrograma mel-log (80 canales, ventanas de 25ms)
  2. El encoder procesa el espectrograma con convoluciones 1D + Transformer
  3. El decoder genera texto autoregressivamente con cross-attention sobre el encoder

Es el mismo patrón encoder-decoder del Transformer original, pero con audio en lugar de texto en la entrada.

📄 Paper: Radford, A. et al. (2022). "Robust Speech Recognition via Large-Scale Weak Supervision". arXiv:2212.04356  |  GitHub

Transformers para series temporales

Las series temporales son secuencias — el dominio natural del Transformer. Varios modelos adaptan self-attention para capturar dependencias temporales complejas:

ModeloAñoInnovación
Informer2020 ProbSparse attention: reduce complejidad a \(O(n \log n)\). Self-attention solo calcula los queries más informativos.
Autoformer2021 Auto-Correlation mechanism: reemplaza attention por correlación de series + descomposición estacional-tendencia.
PatchTST2023 Parches temporales (como ViT): agrupa timestamps en parches y los trata como tokens. Channel-independence para multivariable.
iTransformer2023 Invierte la atención: aplica attention sobre las variables (canales) en lugar de timestamps.
TimesFM2024 Foundation model de Google: pre-entrenado en 100B+ timesteps. Zero-shot forecasting.
⏰ ¿Y las RNNs? ¿Están muertas?

No del todo. Modelos como Mamba (State Space Models, 2023) demuestran que arquitecturas recurrentes con complejidad lineal pueden competir con Transformers. La ventaja de Mamba: \(O(n)\) en lugar de \(O(n^2)\) de self-attention, con inferencia más rápida y sin KV-cache.

En la práctica, la comunidad investiga híbridos: combinar attention con SSMs para obtener lo mejor de ambos mundos (Jamba, Zamba, etc.).

DiT: Diffusion Transformer

DiT (Peebles & Xie, 2023) reemplaza la U-Net de los modelos de difusión por un Transformer. La idea: en lugar de aplicar convoluciones para predecir el ruido, usar self-attention sobre parches del latent space.

1
Patchify: Divide el latent (e.g. 32×32×4 de un VAE) en parches y crea tokens.
2
Conditioning: El timestep y la etiqueta de clase se inyectan vía adaptive layer norm (adaLN-Zero) — no como cross-attention.
3
Transformer blocks: Self-attention estándar entre los parches del latent.
4
Decode: Linear + reshape → latent denoised → VAE decoder → imagen.
🎨 DALL-E 3, Stable Diffusion 3, Sora, Flux... todos usan variantes de DiT. El Transformer ha reemplazado a la U-Net como backbone de difusión de referencia (2024+). → Ver submódulo de difusión
📄 Paper: Peebles, W. & Xie, S. (2023). "Scalable Diffusion Models with Transformers". arXiv:2212.09748  |  GitHub

Transformers multimodales

La misma arquitectura puede procesar múltiples modalidades simultáneamente: tokenizar cada modalidad, concatenar o intercalar, y dejar que self-attention aprenda las relaciones cross-modal.

ModeloModalidadesMétodo
CLIP (2021) Imagen + Texto Contrastive: alinea embeddings de ViT y Transformer de texto en un espacio compartido.
Flamingo (2022) Imagen + Texto Perceiver Resampler + gated cross-attention para inyectar features visuales en un LLM congelado.
GPT-4V / Gemini (2023) Imagen + Texto + Audio Tokenización nativa de imagen y texto en un único decoder.
ImageBind (2023) 6 modalidades Alineación contrastiva de imagen, texto, audio, depth, thermal, IMU.

Papers y recursos fundamentales

PaperAñoContribuciónLink
Attention Is All You Need2017 Transformer original arXiv
BERT2018 Pre-training bidireccional arXiv
GPT-22019 Language models are unsupervised multitask learners PDF
T52019 Text-to-text framework unificado arXiv
ViT2020 An Image is Worth 16×16 Words arXiv
Whisper2022 Robust speech recognition arXiv
DiT2023 Scalable Diffusion with Transformers arXiv
Flash Attention 22023 Atención eficiente IO-aware arXiv

📚 Recursos adicionales

🧪 Herramientas interactivas
🏭 Casos de uso