Recurrent Neural Network (RNN)
Una red neuronal recurrente (RNN) procesa una secuencia paso a paso y mantiene un estado oculto. Incluye su recurrencia, entrenamiento, variantes y código.
Una red neuronal recurrente (RNN) es una red neuronal que procesa una secuencia elemento a elemento mientras mantiene un estado oculto de un paso al siguiente, de modo que su salida en cualquier paso puede depender de todo lo que ha leído hasta ese momento. Se aplican los mismos pesos en cada paso, lo que permite que una red gestione secuencias de cualquier longitud, desde una frase hasta horas de lecturas de sensores. Las RNN fueron la arquitectura principal para el procesamiento del lenguaje natural (NLP), el reconocimiento del habla y el análisis de series temporales hasta que los transformers las sustituyeron en la mayoría de las tareas lingüísticas a finales de la década de 2010. Sus variantes con compuertas siguen siendo habituales en modelos de streaming y en el dispositivo, y la recurrencia ha vuelto con los modelos de espacio de estados (SSMs), como Mamba.
Cómo funciona una RNN#
Una RNN sencilla, también llamada red de Elman por el artículo de Jeffrey Elman de 1990, actualiza su estado oculto según hₜ = tanh(Wxₜ + Uhₜ₋₁ + b) y puede emitir una salida yₜ = Vhₜ + c en cada paso. El estado oculto es un vector de tamaño fijo que resume la secuencia hasta ese momento, y tanh mantiene sus valores entre −1 y 1 cuando se realimenta. Al dibujar una copia de la red por paso, el bucle se despliega en una red feedforward profunda cuyas capas comparten los mismos pesos:
El fragmento siguiente ejecuta nn.RNN de PyTorch sobre una secuencia y repite la misma recurrencia en un bucle sencillo:
import torch
from torch import nn
torch.manual_seed(0)
rnn = nn.RNN(input_size=3, hidden_size=4, batch_first=True)
x = torch.randn(1, 6, 3) # one sequence: 6 time steps, 3 features each
# PyTorch runs the whole sequence; output holds the hidden state after every step
output, h_n = rnn(x)
# The same recurrence by hand, reusing one set of weights at every step
h = torch.zeros(1, 4)
for t in range(x.shape[1]):
h = torch.tanh(x[:, t] @ rnn.weight_ih_l0.T + rnn.bias_ih_l0 + h @ rnn.weight_hh_l0.T + rnn.bias_hh_l0)
print(f"Output shape: {tuple(output.shape)}, final state shape: {tuple(h_n.shape)}")
print(f"Hand-written loop matches nn.RNN: {torch.allclose(h, h_n[0], atol=1e-6)}")Imprime Output shape: (1, 6, 4), final state shape: (1, 1, 4) y Hand-written loop matches nn.RNN: True. La salida contiene un estado oculto de 4 dimensiones por paso temporal, y el bucle reproduce el estado final con una sola matriz de pesos para la entrada y otra para el estado anterior.
Tareas con secuencias#
La misma recurrencia se adapta a tareas con longitudes de entrada y salida diferentes:
- Muchas a una: Lee una secuencia completa y la clasifica a partir del estado final, como en el análisis de sentimientos o al etiquetar una ventana de datos de sensores.
- Muchas a muchas: Emite una salida en cada paso, como al etiquetar cada palabra de una frase o cada fotograma de audio.
- Secuencia a secuencia: Una RNN codificadora lee la entrada y una RNN decodificadora genera una salida de longitud distinta; este diseño se empleó en la traducción automática neuronal inicial y en otros modelos de secuencia a secuencia.
- Una a muchas: Genera una secuencia a partir de una sola entrada, como una descripción a partir del vector de características de una imagen en los primeros modelos de descripción de imágenes.
Las RNN bidireccionales añaden una segunda RNN que lee la secuencia hacia atrás y combinan ambos estados en cada paso, de modo que cada salida ve el contexto pasado y futuro. Las RNN apiladas pasan los estados ocultos de una capa a la siguiente como secuencia de entrada.
Entrenamiento con retropropagación a través del tiempo#
Las RNN se entrenan mediante retropropagación a través del tiempo (BPTT): la red se despliega a lo largo de la secuencia, la pérdida se suma en todos los pasos y la retropropagación recorre el grafo desplegado. El gradiente que llega al paso t desde el paso T atraviesa T − t copias de la capa recurrente y se multiplica por U y por la derivada de tanh en cada una. Cuando esos factores son en su mayoría menores que 1, el gradiente disminuye geométricamente: es el problema del desvanecimiento del gradiente que Yoshua Bengio, Patrice Simard y Paolo Frasconi analizaron en 1994. Cuando son mayores que 1, crece geométricamente: es el problema de la explosión del gradiente. El fragmento siguiente mide cuánto afecta cada entrada de una secuencia de 50 pasos al estado oculto final:
import torch
from torch import nn
torch.manual_seed(0)
rnn = nn.RNN(input_size=8, hidden_size=32, batch_first=True)
x = torch.randn(1, 50, 8, requires_grad=True) # one 50-step sequence
# Backpropagate from the final hidden state to the input at every step
output, h_n = rnn(x)
h_n.sum().backward()
grad_norms = x.grad[0].norm(dim=1)
for distance in [0, 10, 20, 30, 40]:
print(f"Input {distance:>2} steps before the end: gradient {grad_norms[-1 - distance]:.1e}")Muestra los gradientes de 1.6e+00, 3.4e-03, 6.2e-06, 1.2e-08 y 1.1e-11 para las entradas 0, 10, 20, 30 y 40 pasos antes del final. Cada diez pasos, la magnitud se reduce aproximadamente en tres órdenes de magnitud, por lo que el entrenamiento apenas puede ajustar los pesos para utilizar una entrada de unas decenas de pasos atrás. El recorte de gradientes, analizado para las RNN por Razvan Pascanu y sus colaboradores en 2013, limita los gradientes explosivos, y la BPTT truncada restringe la retropropagación a una ventana fija para acotar la memoria. Los gradientes desvanecidos requieren un cambio de arquitectura, que es lo que aportan las compuertas de LSTM y GRU.
RNN frente a arquitecturas relacionadas#
- LSTM y GRU: RNN con compuertas y una actualización aditiva del estado que permite que la información y los gradientes pasen por muchos pasos. En la práctica, «RNN» suele referirse tanto a una de estas variantes como a la RNN simple.
- Transformer: Presta atención directamente a todas las posiciones anteriores en lugar de comprimir el historial en un único estado, y se entrena con todas las posiciones en paralelo. El coste de la atención aumenta con la longitud de la secuencia, mientras que una RNN consume la misma computación y memoria en cada nuevo paso.
- Red neuronal convolucional (CNN): Combina posiciones cercanas mediante filtros de tamaño fijo, tanto en el espacio de las imágenes como a lo largo del tiempo con convoluciones 1D, y su campo receptivo viene determinado por su profundidad.
- Modelos de espacio de estados: Las recurrencias lineales, como Mamba, se entrenan en paralelo con un recorrido y se ejecutan paso a paso como una RNN durante la inferencia. Las redes neuronales líquidas son RNN de tiempo continuo cuyas neuronas siguen ecuaciones diferenciales.
Aplicaciones#
- Predicción de texto en el teclado: El modelo de siguiente palabra de Gboard era una LSTM con compuerta de entrada y olvido acopladas, una variante más ligera de LSTM, entrenada mediante aprendizaje federado en los teléfonos de los usuarios, tal como describieron investigadores de Google en 2018.
- Previsión de la demanda: DeepAR de Amazon entrena una RNN autorregresiva con muchas series temporales relacionadas y genera una distribución de probabilidad para cada valor futuro.
- Audio en streaming: Los detectores de palabras de activación y los supresores de ruido procesan el audio fotograma a fotograma con pequeñas capas recurrentes, lo que mantiene constantes la memoria y la latencia en teléfonos y auriculares.
- Seguimiento de objetos: Un rastreador conserva el estado de cada objeto de un fotograma al siguiente, función que desempeña el estado oculto de una RNN. Todos los rastreadores integrados en el modo de seguimiento de YOLO26, desde ByteTrack y BoT-SORT hasta el TrackTrack predeterminado, actualizan ese estado con un filtro de Kalman, una recurrencia lineal con ecuaciones de velocidad constante definidas manualmente en lugar de pesos aprendidos.










