20 · RNN vs ANN: manejo de secuencias
Los MLPs y CNNs fallan con secuencias de longitud variable; la RNN resuelve ambos problemas realimentando su propia salida como entrada en cada paso temporal.
Una RNN realimenta su salida como entrada — en cada paso temporal ve el token actual Y un estado oculto que resume todo lo anterior.
Sin esto:
Los MLPs y CNNs no pueden manejar secuencias de longitud variable con memoria; las RNNs fueron la primera arquitectura capaz de hacerlo.
Cada arquitectura que has construido hasta ahora — MLP, CNN — comparte una suposición silenciosa: la entrada tiene una forma fija. Un MLP que espera 784 números no puede recibir 800 sin rediseñar las matrices de pesos. Una CNN entrenada en imágenes de 32×32 se atraganta con entradas de 64×64 sin reentrenamiento.
El lenguaje no funciona así. Un tweet tiene 5 palabras; un documento legal tiene 50,000. Una expresión hablada dura 0.3 segundos; una conferencia dura 3,600 segundos. Los datos de series temporales — precios de acciones, señales EEG, flujos de sensores — llegan en fragmentos de longitud impredecible.
Hay un segundo problema: la memoria. Si procesas una oración palabra por palabra con un MLP, cada palabra se procesa de forma independiente — la red no tiene forma de recordar que "no" apareció tres palabras atrás cuando ve "bueno". Los MLPs no tienen noción del tiempo.
La Red Neuronal Recurrente fue diseñada para resolver exactamente estos dos problemas. En su núcleo es sorprendentemente simple: después de procesar el token t, la red guarda un estado oculto h_t — un vector que resume todo lo que ha visto hasta ahora. En el siguiente token, usa tanto la nueva entrada como ese estado oculto. Ese estado oculto se reemplaza a sí mismo: h_t alimenta el paso t+1, que produce h_{t+1}, y así sucesivamente.
Las mismas matrices de pesos se reutilizan en cada paso temporal. Esto es lo que hace que una RNN sea independiente de la longitud de la secuencia: podrías, en principio, alimentarle 1 millón de tokens con un conteo de parámetros fijo. La recurrencia es la memoria; los pesos compartidos son la invarianza.
La recurrencia de la RNN: h_t = tanh(W_xh @ x_t + W_hh @ h_{t-1} + b)
Python (in browser)
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Comparativa de arquitecturas: MLP vs CNN vs RNN
Read-along de PyTorch: interfaz nn.RNN
¿Por qué una RNN comparte pesos en todos los pasos temporales?
- La recurrencia RNN h_t = tanh(W_xh @ x_t + W_hh @ h_{t-1} + b) da memoria temporal con un conteo de parámetros fijo.
- Tres patrones de uso: muchos-a-uno (sentimiento), muchos-a-muchos (NER/traducción), uno-a-muchos (subtitulado).
- Las RNNs no pueden paralelizar en la dimensión temporal — esa es la razón fundamental por la que los Transformers las reemplazaron.
El reconocimiento de voz, la traducción automática, el modelado del lenguaje y la predicción de series temporales — todos estuvieron dominados por RNNs hasta que llegaron los Transformers. Las RNNs todavía se usan en dispositivos edge con recursos limitados donde el conteo pequeño de parámetros y la baja latencia de inferencia importan más que el paralelismo.
Si lo quitas: Saltarías directamente a LSTMs o Transformers sin entender el mecanismo de memoria sobre el que están construidos. El estado de celda de LSTM, la puerta de GRU y la codificación posicional del transformer cobran sentido en contraste con la recurrencia simple de la RNN.