Secuencias y memoria
¿Cómo procesa una red algo que ocurre en orden, como una frase?
Lección completa
Si quieres:
Mira esta frase: «Las flores que compré en el mercado están marchitas». Para acertar con «están» y no «está», hay que recordar «flores», que quedó seis palabras atrás.
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.
Modo revisiónComentar este pasoTerminé la lección
Qué lograrás
- Explicar cómo una red recurrente lee una secuencia paso a paso y qué guarda su estado oculto.
- Predecir qué le pasa a la culpa del error al retroceder por muchos pasos, y por qué se apaga o se vuelve errática.
- Describir qué hacen las compuertas de una LSTM (olvidar, escribir, leer) y qué límites siguen en pie.
Ideas clave
- Una secuencia es un dato cuyo orden importa y cuyo largo varía. Una red recurrente la lee paso a paso con la misma celda y pasa de un paso al siguiente un estado oculto: su memoria.
- Desenrollada en el tiempo, una RNN es una red profunda con una capa por paso y los mismos pesos en todas. Entrenarla es retropropagar a través del tiempo.
- La culpa del error se multiplica por un factor en cada paso que retrocede. Con factores menores que uno se desvanece y lo lejano no se aprende; con pesos grandes se vuelve errática y el estado se satura.
- La LSTM agrega una cinta de memoria y tres compuertas aprendidas (olvido, entrada y salida, con valores entre cero y uno). Con la de olvido cerca de uno, la culpa viaja casi intacta por la cinta.
- Aun así, la LSTM va en fila (los pasos no se calculan a la vez), comprime todo en un vector de tamaño fijo y su memoria útil sigue siendo corta: esos límites motivan la atención.
Lo que mucha gente cree
Creencia común Una red recurrente recuerda toda la frase palabra por palabra, como un cuaderno.
Lo correcto Guarda un resumen de tamaño fijo, un puñado de números que se reescribe en cada paso, y lo temprano se desvanece. La LSTM alarga esa memoria con compuertas, pero sigue siendo corta.
Compruébalo
Cuatro preguntas. Sin nota ni cuenta: sirven para ver si la idea quedó.
Por dentroPara quien quiere las fórmulas y el código. No hace falta para seguir el curso.
La celda recurrente
Con una entrada y un estado , la RNN de Elman calcula
con , y . Son parámetros, los mismos en todos los pasos: no crecen con el largo de la frase. Para predecir la palabra siguiente se agrega una capa de salida, (lección 19). En la lección, , , sin sesgo ( parámetros) y con pesos al azar sin entrenar: solo se ve la mecánica.
La culpa a través del tiempo
La pérdida total es . La culpa que llega al estado desde el paso es la regla de la cadena (lección 8) aplicada a lo largo del tiempo:
Es un producto de matrices. La escena muestra el tamaño de ese producto, (la ganancia típica ante un empujón en una dirección al azar; = no se pierde nada). Como , si la norma de (su mayor valor singular) es , el producto cae como una exponencial: . Con una sigmoide el techo de la derivada es y todo cae más rápido (lección 8). En general, Pascanu, Mikolov y Bengio (2013) muestran, para una no linealidad con ( para tanh, para sigmoide), que **basta** para que la contribución lejana se desvanezca y que es necesario para que explote (: el autovalor mayor en valor absoluto de ).
Con no hay garantía de explosión: la tanh se satura () y apaga unidades, como se ve en la escena, donde con pesos grandes la culpa se vuelve errática, enorme en unas frases y casi nula en otras. Dos remedios clásicos: recortar la norma del gradiente contra la explosión (Pascanu et al., 2013) y rediseñar la celda contra el desvanecimiento. Bengio, Simard y Frasconi (1994) añaden un dilema: para guardar un dato de forma estable ante el ruido hace falta que la dinámica contraiga, y eso hace que los gradientes de largo plazo se desvanezcan.
La LSTM
Con compuertas , un candidato y el producto elemento a elemento :
La cinta se actualiza por suma, no por reescritura. A lo largo de ella, (más caminos indirectos por ), de modo que la culpa se multiplica solo por la compuerta de olvido: con llega casi intacta, el «carrusel de error constante» del artículo de 1997. La LSTM original tenía compuertas de entrada y de salida; la de olvido la añadieron Gers, Schmidhuber y Cummins (2000). Un truco práctico: iniciar el sesgo cerca de para que la cinta empiece abierta (Jozefowicz et al., 2015). Una capa tiene parámetros: cuatro veces los de la RNN. Con son . Las LSTM apiladas llegaron lejos: el sistema de traducción neuronal de Google (Wu et al., 2016) usaba ocho capas LSTM en el codificador y ocho en el decodificador, con atención y conexiones residuales.
En la lección las compuertas son números fijos y hay una sola celda: , , donde son pistas de número gramatical ilustrativas (plural para «flores», singular para «mercado») y en la palabra clave. Una red entrenada calcula e de la palabra y del estado. En 2019, Lakretz et al. hallaron que, en una LSTM entrenada como modelo de lenguaje, la información de número de largo alcance la manejan sobre todo dos «unidades de número», justo lo que hace nuestra celda de juguete.
En código
import numpy as np
def influencia(g, pasos):
"""Cuánto de un empujón en el estado inicial sobrevive tras `pasos` pasos (RNN de 2 unidades con tanh)."""
c, s = np.cos(0.8), np.sin(0.8)
Wh = g * np.array([[c, -s], [s, c]]) # un giro de 0,8 rad, escalado por g
x = np.array([0.5, -0.3]) # la «palabra» que llega en cada paso
h, P = np.zeros(2), np.eye(2)
for _ in range(pasos):
h = np.tanh(Wh @ h + x)
P = ((1 - h**2)[:, None] * Wh) @ P # P = J_t · P, con J_t = diag(1 − h²) · Wh
return np.linalg.norm(P) / np.sqrt(2)
for g in (0.5, 0.9, 1.5, 2.0):
print(g, [round(float(influencia(g, n)), 4) for n in (1, 5, 10, 20)])
# 0.5 [0.4266, 0.0083, 0.0001, 0.0]
# 0.9 [0.7679, 0.0989, 0.0152, 0.0004]
# 1.5 [1.2798, 0.8562, 1.218, 1.154]
# 2.0 [1.7064, 2.2703, 2.4696, 1.3574]
Con o el empujón se apaga; con se amplifica; en torno a y con esta entrada fija hay una ventana estrecha en que se mantiene. Basta moverse un poco para salir de ella.
import math
pistas = [0, 1.2, 0.3, -0.5, 0.2, -0.1, -0.9] # pista de número de cada palabra (ilustrativa)
def celda(f, i, o):
c = 0.0
for t, v in enumerate(pistas, start=1):
entrada = 1.0 if t == 2 else i # «flores» abre la compuerta de entrada
c = f * c + entrada * math.tanh(v) # la cinta: olvidar un poco, escribir un poco
return o * math.tanh(c) # lo que se lee al final (positivo = plural)
print(round(celda(0.6, 0.8, 1.0), 3)) # -0.5 (la pista se pierde y gana «mercado»: singular)
print(round(celda(1.0, 0.1, 1.0), 3)) # 0.638 (plural)
print(round(0.97 ** 5, 2)) # 0.86 (culpa que llega a «flores» por la cinta)
Lo que viene
La RNN y la LSTM leen en fila y comprimen todo en un vector; la atención (lección 21) deja que cada palabra mire directamente a las demás, en paralelo. Antes, la lección 13 cuenta por qué el deep learning despegó hacia 2012: datos, GPUs y algunos trucos, entre ellos las conexiones residuales, que en profundidad cumplen un papel parecido al de la cinta de la LSTM.
Lente de decisión
Qué significa esta idea si tu trabajo es decidir, no programar.
- Memoria teórica no es memoria útil. Cuando un proveedor diga que su modelo «recuerda todo el contexto», pide una prueba con textos tan largos como los tuyos: en modelos de lenguaje LSTM se midió que usaban unas doscientas palabras de contexto.
- Lo que va en fila cuesta tiempo. Una arquitectura recurrente procesa los pasos de una secuencia uno tras otro: el tiempo de entrenamiento y de respuesta crece con el largo del texto y la GPU se aprovecha mal. Pregunta cómo escala la latencia con la longitud.
- Los modelos de secuencia siguen siendo razonables en problemas chicos: series de tiempo cortas, sensores, equipos con poco cómputo. Si te proponen una LSTM, pregunta por qué esa y no otra arquitectura, y con qué datos se comparó.
- El síntoma de una memoria corta es acertar lo reciente y fallar lo que dependía de algo lejano: concordancias, referencias, una cláusula del inicio. Diseña pruebas que pongan el dato clave lejos de la pregunta.
Términos de la lección
- Modelo de secuencia Modelo que procesa datos cuyo orden importa y cuyo largo varía, como texto, audio o series de tiempo, normalmente leyéndolos paso a paso.
- Red recurrente (RNN) Red que procesa una secuencia paso a paso con la misma celda: en cada paso recibe la entrada actual y el estado oculto anterior, y produce un estado nuevo.
- Estado oculto Vector de números que una red recurrente lleva de un paso al siguiente: su memoria de lo leído hasta ahora. Se reescribe en cada paso.
- Gradiente que se desvanece Fenómeno por el que el gradiente (la culpa) se multiplica por factores menores que uno al retroceder por muchos pasos o capas y llega casi a cero, de modo que lo lejano no se aprende. Con factores mayores que uno ocurre lo contrario: el gradiente explota.
- LSTM (memoria larga a corto plazo) Celda recurrente con una cinta de memoria (estado de la celda) y tres compuertas aprendidas, de olvido, de entrada y de salida, que deciden qué se conserva, qué se escribe y qué se lee. Propuesta en 1997 por Hochreiter y Schmidhuber; la compuerta de olvido se añadió en 2000.
- Retropropagación Algoritmo que calcula el gradiente de la pérdida respecto de todos los pesos de una red en un solo recorrido hacia atrás, aplicando la regla de la cadena capa por capa. Calcula las culpas; no mueve los pesos (en el artículo de 1986, el nombre abarcaba todo el procedimiento de aprendizaje).
- Regla de la cadena Si una cantidad depende de otra a través de una cadena de pasos, su influencia total es el producto de la influencia de cada paso. Es la base de la retropropagación.
- Gradiente La lista de las pendientes del error, una por cada peso. Vista como flecha, apunta hacia donde el error sube más rápido.
- Sigmoide Función σ(z) = 1/(1 + e⁻ᶻ): convierte cualquier número en un valor entre 0 y 1, y vale 0.5 cuando z = 0.
- Función de activación Función que se aplica a la suma ponderada más el sesgo para producir la salida de la neurona. Ejemplos: el escalón y la sigmoide.
- Peso (w) En un modelo lineal, el número que multiplica a la entrada: la pendiente de la recta. Indica cuánto sube la predicción por cada unidad que aumenta la entrada.
- Vector Lista ordenada de números. En aprendizaje automático, cada ejemplo llega al modelo como un vector.
- Pase hacia delante Cálculo de la salida de una red: los números avanzan capa por capa, de la entrada a la salida.
- Capa Grupo de neuronas que reciben las mismas entradas y calculan a la vez. Una red es una cadena de capas: entrada, una o más ocultas, y salida.
- Kernel (filtro) La cuadrícula pequeña de pesos de una convolución. En una red convolucional, sus valores se aprenden durante el entrenamiento.
Transcripción completa
Fuentes
- Elman, J. L. (1990). Finding structure in time
- Hochreiter, S. (1991). Untersuchungen zu dynamischen neuronalen Netzen (tesis de diploma)
- Bengio, Y., Simard, P., Frasconi, P. (1994). Learning long-term dependencies with gradient descent is difficult
- Hochreiter, S., Schmidhuber, J. (1997). Long short-term memory
- Gers, F. A., Schmidhuber, J., Cummins, F. (2000). Learning to forget: continual prediction with LSTM
- Pascanu, R., Mikolov, T., Bengio, Y. (2013). On the difficulty of training recurrent neural networks
- Sutskever, I., Vinyals, O., Le, Q. V. (2014). Sequence to sequence learning with neural networks
- Cho, K., van Merriënboer, B., Bahdanau, D., Bengio, Y. (2014). On the properties of neural machine translation: encoder-decoder approaches
- Jozefowicz, R., Zaremba, W., Sutskever, I. (2015). An empirical exploration of recurrent network architectures
- Wu, Y., Schuster, M., Chen, Z., Le, Q. V., Norouzi, M., et al. (2016). Google’s neural machine translation system: bridging the gap between human and machine translation
- Khandelwal, U., He, H., Qi, P., Jurafsky, D. (2018). Sharp nearby, fuzzy far away: how neural language models use context
- Lakretz, Y., Kruszewski, G., Desbordes, T., Hupkes, D., Dehaene, S., Baroni, M. (2019). The emergence of number and syntax units in LSTM language models
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