Vamos a entender los 4 puntos del FFN desde otro ángulo, con visualizaciones interactivas y analogías concretas.
Antes de zambullirte en los detalles, este es el panorama completo. Si solo leés esta sección, ya entendiste el 80%:
Para que cada token procese su información después de que la atención mezcló datos entre tokens. Es la fase de "pensar individualmente" sobre lo recibido.
Dos cosas que la atención no puede dar:
1) No-linealidad (vía ReLU) → aprender patrones complejos.
2) Capacidad de cómputo (vía la expansión) — de hecho, el FFN concentra la mayoría de los parámetros del modelo.
Sin FFN, el Transformer:
a) Solo aprende patrones lineales (no podría modelar lenguaje).
b) Sus muchas capas se colapsarían a una sola (no podrías "apilar" para aprender más).
↓ A continuación, las visualizaciones que sustentan cada uno de estos puntos ↓
El argumento abstracto "operaciones lineales son limitadas" se entiende mejor con un ejemplo visual concreto. Vamos al problema clásico que demuestra esto: XOR.
Imaginá que tenés 4 puntos en una hoja, distribuidos así:
Tu tarea: trazar UNA línea recta que deje todos los ⭕ de un lado y todos los ❌ del otro.
Por más que muevas la línea, NO PODÉS separar los ⭕ de los ❌ con una sola recta. Esto se llama "no linealmente separable". Cualquier modelo que solo pueda dibujar líneas rectas nunca aprenderá este patrón.
Solo puede dibujar UNA línea recta. Imposible separar las 4 esquinas correctamente.
Puede "doblar" y crear regiones complejas. ¡Funciona!
Ya viste que ReLU(x) = max(0, x) aplasta los negativos. Pero la pregunta es: ¿para qué sirve aplastarlos? Acá viene la intuición clave.
Imaginá que el resultado de la multiplicación matricial es como una señal que llega a una neurona. Esa señal puede ser:
Cada neurona en la capa expandida es como un detector de un patrón específico. Si el patrón está → la neurona se enciende y contribuye. Si no está → la neurona se apaga y queda en silencio.
Cada barra de abajo es una "neurona" con su valor crudo (antes de ReLU). Mové los sliders y mirá cómo ReLU enciende las positivas y apaga las negativas:
🔥 = neurona "encendida" (la señal pasa) · 💤 = neurona "apagada" (señal bloqueada)
Antes de hablar de POR QUÉ lo hacemos, aclaremos QUÉ significa literalmente. Porque las palabras "expandir" y "contraer" suenan físicas, pero acá significan algo muy concreto.
Imaginá este vector chiquito de dim 2 (2 números):
input = [3, 5]
Quiero convertirlo en un vector de 4 números. Para eso multiplico por una matriz que tenga 4 columnas:
matriz expansora (2 filas × 4 columnas): col0 col1 col2 col3 fila0 [0.5, 0.2, 0.1, 0.3] fila1 [0.1, 0.4, 0.5, 0.2] Aplico la multiplicación (producto punto con cada columna): out[0] = (3 × 0.5) + (5 × 0.1) = 1.5 + 0.5 = 2.0 out[1] = (3 × 0.2) + (5 × 0.4) = 0.6 + 2.0 = 2.6 out[2] = (3 × 0.1) + (5 × 0.5) = 0.3 + 2.5 = 2.8 out[3] = (3 × 0.3) + (5 × 0.2) = 0.9 + 1.0 = 1.9 vector expandido = [2.0, 2.6, 2.8, 1.9] ← AHORA TIENE 4 NÚMEROS
Empecé con 2 números, terminé con 4. Eso es "expandir".
Ahora quiero volver de 4 números a 2. Para eso multiplico por una matriz que tenga 2 columnas:
matriz contraedora (4 filas × 2 columnas): col0 col1 fila0 [0.2, 0.3] fila1 [0.4, 0.1] fila2 [0.1, 0.5] fila3 [0.3, 0.2] Aplico la multiplicación con el vector expandido [2.0, 2.6, 2.8, 1.9]: out[0] = (2.0×0.2) + (2.6×0.4) + (2.8×0.1) + (1.9×0.3) = 0.40 + 1.04 + 0.28 + 0.57 = 2.29 out[1] = (2.0×0.3) + (2.6×0.1) + (2.8×0.5) + (1.9×0.2) = 0.60 + 0.26 + 1.40 + 0.38 = 2.64 vector contraído = [2.29, 2.64] ← VOLVIÓ A TENER 2 NÚMEROS
Empecé con 4 números, terminé con 2. Eso es "contraer".
| Matriz | Input | Output | ¿Qué hizo? |
|---|---|---|---|
| 2 × 4 | dim 2 | dim 4 | expandió 2→4 |
| 4 × 2 | dim 4 | dim 2 | contrajo 4→2 |
| 4 × 8 | dim 4 | dim 8 | expandió 4→8 (caso FFN) |
| 8 × 4 | dim 8 | dim 4 | contrajo 8→4 (caso FFN) |
Regla rápida: la cantidad de columnas de la matriz = la dimensión del output. Si la matriz tiene más columnas que filas → expandís. Si tiene menos columnas que filas → contraés.
Vector de "perro" (dim 4): [+0.5, +1.1, +0.7, +0.8] │ │ multiplicar por W₁ │ (matriz 4×8 → produce 8 números) ↓ Vector "expandido" (dim 8): [+0.65, -0.12, +0.40, -0.30, +0.18, +0.20, -0.15, +0.50] │ │ aplicar ReLU │ (NO cambia la cantidad de números, │ solo aplasta los negativos) ↓ Vector "activado" (dim 8): [+0.65, 0.00, +0.40, 0.00, +0.18, +0.20, 0.00, +0.50] │ │ multiplicar por W₂ │ (matriz 8×4 → produce 4 números) ↓ Vector "contraído" (dim 4): [+0.7, +0.0, +0.8, +0.7]
Empezás con 4 números, los expandís a 8 (más espacio de trabajo), ReLU filtra cuáles "se encienden", y finalmente contraés de vuelta a 4. Es un viaje de ida y vuelta en la cantidad de números.
Ya que entendiste qué pasa mecánicamente, ahora vamos al "para qué". La razón clave es que en el espacio expandido tenés más capacidad.
Cada celda del vector expandido (cada "neurona") con ReLU agrega UN pliegue a la función que la red puede aprender. Con pocas neuronas, podés hacer pocas "esquinas". Con muchas neuronas, podés aproximar cualquier curva.
Línea azul: la función "objetivo" que queremos aprender. Línea naranja: lo que la red puede aproximar con N neuronas ReLU. Con pocas neuronas → aproximación cruda. Con muchas → casi perfecta.
Imaginá que tenés que viajar y solo entran 4 cosas en tu mochila. Pero antes de meterlas, necesitás clasificarlas y decidir qué empacar.
Resultado: tenés 4 prendas en la mochila (mismo tamaño que el espacio disponible), pero son las 4 MEJORES porque tuviste un "espacio de trabajo" más grande en el medio para decidir.
Si hubieras saltado del cajón directo a la mochila sin sacar nada sobre la cama, no habrías podido evaluar bien qué prendas convenían.
Imaginá un juicio. El input es "la evidencia del caso" (un vector pequeño). El veredicto final también es chico ("culpable" o "inocente"). Pero en el medio, hay 12 jurados que cada uno evalúa la evidencia desde su propia perspectiva. Después se reúnen y combinan sus votos en el veredicto.
El FFN es eso: el input se "abre" a muchos detectores en el medio (cada neurona = un jurado), y después se "combinan" en el output final.
Para entender FFN en contexto, necesitás ver el "bloque" completo del Transformer y los dos sub-bloques que lo componen:
El rol: "qué información tomar de los otros tokens". Es la fase donde "perro" averigua que "come" es relevante para entenderse en esta frase.
Limitación: las operaciones son lineales. La atención puede pesar y combinar, pero no puede "transformar" la información a algo cualitativamente distinto.
El rol: "qué hacer con la información que ya tiene cada token". Es la fase donde "perro" (ya con info de toda la frase) la procesa para extraer significado más profundo.
Aporta lo que atención no puede: no-linealidad + más capacidad de cómputo (vía la expansión).
Este bloque (attention + FFN) se llama una "capa" del Transformer y se apila muchas veces. GPT-2 small tiene 12 capas. GPT-3 tiene 96 capas. En cada nueva capa, el modelo puede extraer patrones más abstractos:
Sin FFN entre cada atención, esas capas serían matemáticamente equivalentes a una sola. FFN es lo que permite que apilar capas realmente agregue capacidad.
Una percepción común equivocada: "atención es el corazón del Transformer, el FFN es un agregado menor". Falso. Mirá la distribución real de parámetros en modelos famosos:
| Modelo | % en atención | % en FFN |
|---|---|---|
| GPT-2 small | ~33% | ~67% |
| GPT-3 | ~33% | ~67% |
| LLaMA-2 7B | ~28% | ~72% |
Dicho de otra forma: en GPT-3 (175 mil millones de parámetros), más de 100 mil millones viven en los FFN. La atención decide "qué mirar", pero el FFN es donde realmente se procesa y almacena la mayor parte del conocimiento aprendido.
Ahora que recorriste todas las visualizaciones, podés releer el "at-a-glance" del principio con perspectiva completa. Acá lo refresco con un nivel más de detalle:
FFN procesa la información dentro de cada token, después de que la atención mezcló información ENTRE tokens. Si atención es "escuchar lo que dicen los demás", FFN es "pensar individualmente sobre lo que escuchaste". Cada token recibe el FFN de forma independiente, pero todos usan las mismas matrices W₁ y W₂.
Dos cosas críticas que la atención no puede aportar:
Si removieras los FFN del Transformer, pasarían dos cosas muy graves:
En otras palabras: sin FFN, no hay LLM posible. El Transformer sería un truco matemático bonito pero incapaz de aprender lenguaje.
Cuando esto te resulte claro, volvé al archivo principal del paso 6 para ver los cálculos matemáticos con esta nueva perspectiva.