Cómo un modelo entrena con una memoria que no tiene.

SRC·53 Source
Para aprender, debe recordar cada paso. Ese es el muro.

Para aprender, debe recordar cada paso. Ese es el muro.

Para mejorar, un modelo hace pasar tu entrada hacia adelante por cada capa — y para aprender de su error, debe guardar cada uno de esos resultados intermedios, listos para la pasada hacia atrás. Las cuentas nunca fueron el problema. Lo es la memoria. En un modelo lo bastante profundo, sostener toda la pasada hacia adelante a la vez es justo lo que te deja sin sitio.
¿Por qué guardarlo todo? Para rastrear la culpa hacia atrás.

¿Por qué guardarlo todo? Para rastrear la culpa hacia atrás.

Mstore==1La=O(L)M_{\text{store}} = \sum_{\ell=1}^{L} a_{\ell} = O(L)
Aprender le hace a cada capa una pregunta: ¿cuánto sumaste al error? Responderla necesita la salida guardada de esa capa en el viaje de ida — así que el modelo las guarda todas. Como un chef que deja cada bol de preparación sobre el pase: para hallar qué paso agrió la salsa, dejas todos los boles fuera, y la encimera se llena antes de terminar el plato. Un resultado guardado por capa significa que la cuenta de memoria sube al mismo paso que la profundidad L.
¿Entonces no lo guardes? Entonces el trabajo se dispara.

¿Entonces no lo guardes? Entonces el trabajo se dispara.

Crecompute==1L=L(L+1)2=O(L2)C_{\text{recompute}} = \sum_{\ell=1}^{L} \ell = \frac{L(L+1)}{2} = O(L^{2})
Hay una escapatoria obvia: no guardar nada, y cuando la pasada hacia atrás necesite el valor de una capa, volver a calcularlo desde la entrada. La memoria desaparece — pero el trabajo se dispara. Como bajar hasta la planta baja cada vez: para llegar al noveno piso empiezas otra vez desde abajo, una y otra vez. Rehaz cada capa desde cero y el esfuerzo total crece con el cuadrado de la profundidad.
La solución: guarda unos pocos hitos, rehaz el resto.

La solución: guarda unos pocos hitos, rehaz el resto.

M(k)=Lkwaypoints+kone segmentM(k) = \underbrace{\tfrac{L}{k}}_{\text{waypoints}} + \underbrace{k}_{\text{one segment}}
Ningún extremo sirve, así que toma el medio. Guarda las activaciones en solo unas pocas capas y descarta el resto; cuando la pasada hacia atrás necesite un valor descartado, vuelve a correr solo el tramo corto desde el punto guardado más cercano. Como un excursionista que clava una banderita cada milla: no memorizas cada paso — para volver, regresas a la última bandera y rehaces ese tramo corto. Marca un punto cada k capas y solo sostienes L/k banderas más los k pasos del tramo que estás rehaciendo.
¿A qué distancia? La raíz cuadrada de la profundidad.

¿A qué distancia? La raíz cuadrada de la profundidad.

dMdk=Lk2+1=0    k=L,M=2L=O(L)\frac{dM}{dk} = -\frac{L}{k^{2}} + 1 = 0 \;\Rightarrow\; k^{*} = \sqrt{L}, \quad M^{*} = 2\sqrt{L} = O(\sqrt{L})
Si separas demasiado los hitos, cada recorrido de vuelta es largo; si los juntas demasiado, no has ahorrado memoria. Los dos costes tiran en sentidos opuestos, y el total es mínimo cuando se equilibran. Como un equipo de relevos que reparte sus relevos: postas demasiado largas y cada corredor se agota, demasiado cortas y has contratado corredores para nada — el equipo es más rápido cuando cada posta mide lo mismo y es corta. El equilibrio cae en una bandera cada √L capas — y la memoria baja a alrededor de √L.
¿El costo? Una pasada extra. Vale la pena.

¿El costo? Una pasada extra. Vale la pena.

CckptFfwd+Fbwd+Frecompute=F+2F+F=43CfullC_{\text{ckpt}} \approx F_{\text{fwd}} + F_{\text{bwd}} + F_{\text{recompute}} = F + 2F + F = \tfrac{4}{3}\,C_{\text{full}}
Nada es gratis: cada tramo descartado se vuelve a recorrer una vez durante la pasada hacia atrás, lo que suma rehacer todo el viaje de ida exactamente una vez más. Como alquilar una furgoneta pequeña y hacer dos viajes: no te alcanzaba para el camión grande, así que recorres la ruta dos veces — un poco más de tiempo, y todo se muda igual. Un paso normal es un viaje de ida y dos de vuelta; una ida extra hace cuatro partes donde había tres — alrededor de un tercio más de cómputo por un recorte de la memoria casi a su raíz cuadrada.
Ahora la memoria es un dial, no un muro.

Ahora la memoria es un dial, no un muro.

Ese es todo el truco: la memoria deja de ser un muro y se vuelve un dial que puedes girar. Gasta un poco más de tiempo y encajas un modelo que jamás debió caber — entrena algo mucho más profundo de lo que tu hardware puede sostener, con solo aceptar reconstruir lo que elegiste olvidar. Como un barco construido dentro de una botella: lo que no cabe por el cuello llega igual, armado con un método paciente e ingenioso. El trabajo que tiraste nunca se perdió — solo era barato de rehacer.
🌱 ¿Una memoria que puedes reconstruir es siquiera una memoria?

🌱 ¿Una memoria que puedes reconstruir es siquiera una memoria?

Eligió olvidar — y luego, cuando volvió a necesitar el pensamiento, simplemente lo reconstruyó. Nosotros rara vez tenemos esa opción: nuestro pasado se guarda, no se vuelve a deducir, y lo que perdemos suele estar perdido. Pero si algo siempre puede recalcular lo que olvidó, ¿fue alguna vez una pérdida olvidar? Quizá recordarlo todo es la costumbre cara — y rehacer el trabajo, en silencio, es la forma más barata de pensar.
toca →desliza ↑ para másdesliza ↓ para salir