Retropropagación
¿Cómo se reparte la culpa del error entre miles de pesos?
Lección completa
Si quieres:
Ya sabemos corregir un peso restándole su pendiente. Pero una red tiene miles de pesos, en capas, y casi ninguno toca la salida. ¿Cómo sabe cada uno cuánto error le toca?
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
- Calcular, paso a paso y con números reales, el pase hacia delante, la pérdida y las culpas (gradientes) de una red pequeña.
- Explicar la regla de la cadena como multiplicar la influencia de cada eslabón, y por qué la culpa de una capa se reutiliza hacia atrás.
- Distinguir lo que calcula la retropropagación (el gradiente) de lo que hace el descenso del gradiente (mover los pesos).
Ideas clave
- El error final de una red se reparte entre miles de pesos escondidos en capas. Saber cuánta culpa tiene cada uno es el problema de la asignación de crédito.
- La regla de la cadena dice que la influencia total de un peso sobre el error es el producto de la influencia de cada eslabón del camino.
- La retropropagación recorre la red de la salida hacia la entrada, calcula la culpa de cada neurona y la reutiliza para la capa anterior: obtiene todo el gradiente en un solo viaje.
- La retropropagación solo calcula el gradiente. Quien corrige los pesos es el descenso del gradiente: w ← w − η · culpa.
- Es barata (en redes grandes, del orden de un par de pases hacia delante), pero exige guardar los valores del pase hacia delante, y la culpa puede atenuarse al cruzar muchas capas.
Lo que mucha gente cree
Creencia común La retropropagación es el mecanismo con el que la red corrige sus pesos.
Lo correcto En el uso actual, solo calcula cuánta culpa tiene cada peso (el gradiente), con un viaje hacia atrás. Mover los pesos es trabajo del descenso del gradiente (u otro optimizador), que usa esos números.
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.
Las ecuaciones de la red
La red de la lección tiene entradas , dos neuronas ocultas, una de salida, activación sigmoide y no usa sesgos:
Con , y resulta y . Los pesos de partida se eligieron de modo que cada cuenta mostrada con tres decimales se pueda repetir a mano, con las cifras ya redondeadas, sin discrepancias (el script verify-data.ts de la lección lo comprueba, y compara el gradiente con diferencias finitas).
La regla de la cadena, paso a paso
Si depende de , este de y este de , la derivada de respecto de es el producto de las derivadas de cada eslabón:
La derivada de la sigmoide es , así que se calcula con la activación que ya se guardó. Los dos primeros factores forman la culpa de la neurona . Hacia atrás, capa por capa:
Con los números de la lección: ; ; y . Como , sale con signo contrario (). Observa que las culpas y no suman : cada peso recibe la culpa de la neurona multiplicada por su propia señal, no una parte de ella.
En capas y en forma de matriz
Con la matriz que lleva a , las mismas ideas se escriben para cualquier número de capas:
Cada se calcula una vez a partir de la capa siguiente: eso es lo que hace barato el método. Con ReLU, se reemplaza por si y en otro caso.
Por qué es barata
Para una pérdida escalar y pesos, el modo inverso de la diferenciación automática (las técnicas para derivar programas de forma exacta; la retropropagación es su caso particular para redes) entrega las derivadas en un solo recorrido hacia atrás. El modo directo, o tantear con diferencias finitas, necesita un recorrido por peso. El gradiente completo cuesta una constante pequeña por el costo de evaluar la función: Baydin et al. (2018), citando a Griewank y Walther (2008), dan y típicamente entre 2 y 3, y Griewank (2012) lo llama el «principio del gradiente barato».
En un transformer grande, Kaplan et al. (2020) cuentan unos FLOPs por token hacia delante, con los parámetros sin contar los de embeddings, y observan que el pase hacia atrás cuesta aproximadamente el doble: de ahí su FLOPs por token de entrenamiento. A cambio, hay que guardar las activaciones del pase hacia delante hasta usarlas: el propio artículo de 1986 señala que las salidas de las capas intermedias del pase hacia delante hacen falta para el pase hacia atrás.
Un límite: la culpa puede atenuarse
Como , cada capa de sigmoides aporta un factor de a lo sumo a la culpa: tras capas. Los pesos también multiplican en cada capa y podrían compensarlo, pero con pesos moderados el producto se encoge de forma exponencial. Por eso en redes profundas se prefieren otras activaciones, conexiones residuales y variantes como la LSTM, temas de las lecciones 12 y 13.
De dónde viene, con cuidado
El nombre y la fama son de 1986, pero la idea es más vieja y tuvo varios descubridores:
- Linnainmaa. Su tesis de maestría (Universidad de Helsinki, 1970, en finés; resultados en inglés en BIT, 1976) estudia cómo se acumula el error de redondeo de un algoritmo y propone lo que hoy se llama modo inverso. Según Griewank (2012), él no lo presentó como un método para obtener gradientes de forma barata.
- Werbos. Su tesis doctoral en estadística (Harvard, agosto de 1974) desarrolla las «derivadas ordenadas» y la «retroalimentación dinámica» para modelos de predicción. Él mismo cuenta (Werbos, 2006) que de las redes neuronales solo escribió unas palabras en el capítulo 5; Goodfellow et al. (2016) fechan en 1981 su propuesta de aplicarlo a entrenar redes neuronales.
- Rumelhart, Hinton y Williams (Nature, 1986). Usan la misma matemática de esta lección: error , sigmoide, un pase hacia delante y uno hacia atrás que «propaga derivadas». Reconocen que David Parker y Yann LeCun descubrieron variantes de forma independiente. En el artículo, «back-propagation» nombra todo el procedimiento de aprendizaje (con la actualización y una variante con término de aceleración, lo que hoy se llama momento); la distinción de hoy, retropropagación para el gradiente y otro algoritmo para aprender con él, es la que explican Goodfellow et al. (2016). Los autores cierran diciendo que el procedimiento, «en su forma actual, no es un modelo plausible del aprendizaje en los cerebros».
En código
import math
def sigma(z):
return 1 / (1 + math.exp(-z))
X, T = (1.0, 0.5), 1.0
def forward(w):
a1 = sigma(w[0] * X[0] + w[1] * X[1])
a2 = sigma(w[2] * X[0] + w[3] * X[1])
y = sigma(w[4] * a1 + w[5] * a2)
return a1, a2, y, 0.5 * (y - T) ** 2
def backward(w):
a1, a2, y, loss = forward(w)
d_y = (y - T) * y * (1 - y) # culpa de la neurona de salida
d_1 = d_y * w[4] * a1 * (1 - a1) # culpa de la oculta 1
d_2 = d_y * w[5] * a2 * (1 - a2) # culpa de la oculta 2
grad = [d_1 * X[0], d_1 * X[1], d_2 * X[0], d_2 * X[1], d_y * a1, d_y * a2]
return loss, grad
w = [0.6, -0.3, 0.7, 0.5, 0.8, -0.9]
loss, grad = backward(w)
print(round(loss, 3), [round(g, 3) for g in grad])
# 0.146 [-0.026, -0.013, 0.024, 0.012, -0.082, -0.097]
# comprobación: tantear cada peso (un pase hacia delante extra por peso)
eps = 1e-6
check = []
for k in range(6):
w2 = w.copy()
w2[k] += eps
check.append((forward(w2)[3] - loss) / eps)
print([round(c, 3) for c in check])
# [-0.026, -0.013, 0.024, 0.012, -0.082, -0.097]
# un paso de descenso del gradiente: lo da el descenso, no la retropropagación
eta = 1.0
w = [wk - eta * g for wk, g in zip(w, grad)]
print(round(forward(w)[3], 3))
# 0.129
Lo que viene
Con datos reales el gradiente se calcula sobre un lote de ejemplos y no sobre uno solo, y optimizadores como el momento o Adam transforman ese gradiente antes de mover los pesos. Todos reciben el gradiente de la retropropagación. Es el tema de la lección 9.
Lente de decisión
Qué significa esta idea si tu trabajo es decidir, no programar.
- Un paso de entrenamiento cuesta del orden de tres pases hacia delante: uno hacia delante y uno hacia atrás que cuesta el doble. Pide el costo por token de entrenamiento, no solo el de uso.
- Entrenar exige guardar los valores intermedios del pase hacia delante: la memoria de la GPU, no solo el cómputo, limita qué modelo cabe. Pregunta cuánta memoria pide entrenar frente a usar.
- Por retropropagación solo se entrena lo que es derivable. Una regla dura, una búsqueda en una base de datos o una decisión discreta en medio del sistema cortan el flujo de la culpa: ahí hacen falta otros métodos.
- Casi nadie programa la retropropagación a mano: PyTorch y TensorFlow la derivan automáticamente. Las preguntas útiles son qué partes se entrenan y cuáles se congelan, porque congelar capas ahorra cómputo y memoria de gradientes.
Términos de la lecció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.
- Descenso del gradiente Método que ajusta los pesos paso a paso, siempre en contra de la pendiente del error (el gradiente), hasta llegar a un fondo.
- Derivada El nombre matemático de la pendiente de una curva en un punto: cuánto cambia una cantidad por cada pequeño cambio de otra.
- Tasa de aprendizaje Número (η) que multiplica la pendiente y fija el tamaño de cada paso. Muy pequeño es lento; muy grande rebota o diverge.
- 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.
- Función de pérdida Un único número que resume qué tan equivocado está un modelo con sus datos. Entrenar es buscar los parámetros que lo hacen lo más pequeño posible.
- 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 oculta Capa de neuronas entre la entrada y la salida. Crea señales intermedias que la salida combina; su valor no se observa directamente.
- 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.
- Neurona artificial Unidad de cálculo que multiplica cada entrada por un peso, suma los resultados, añade un sesgo y aplica una función de activación: y = f(w·x + b).
- 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.
- ReLU Unidad lineal rectificada: función de activación que devuelve cero si la suma es negativa y la propia suma si es positiva, máx(0, z). Una bisagra con una sola esquina.
- 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.
- Asignación de crédito (reparto de la culpa) El problema de decidir cuánto contribuyó al resultado final cada decisión, peso o neurona escondido en medio de un sistema (Minsky lo planteó así en 1961, para el aprendizaje por refuerzo). En una red derivable, la retropropagación lo resuelve de forma eficiente.
Transcripción completa
Fuentes
- Rumelhart, D. E., Hinton, G. E., Williams, R. J. · Nature 323, 533–536 (1986). Learning representations by back-propagating errors
- Griewank, A. (2012). Who invented the reverse mode of differentiation? · Documenta Mathematica, Extra Volume ISMP, 389–400
- Linnainmaa, S. (1976). Taylor expansion of the accumulated rounding error · BIT 16(2), 146–160 (versión en inglés de resultados de su tesis de maestría de 1970, Universidad de Helsinki)
- Werbos, P. J. (1974). Beyond Regression: New Tools for Prediction and Analysis in the Behavioral Sciences (tesis doctoral, Universidad de Harvard; copia escaneada)
- Werbos, P. J. (2006). Backwards differentiation in AD and neural nets: past links and new opportunities · en Automatic Differentiation: Applications, Theory, and Implementations, LNCSE 50, 15–34
- Goodfellow, I., Bengio, Y., Courville, A. (2016). Deep Learning, secciones 6.5 (Back-Propagation and Other Differentiation Algorithms) y 6.6 (Historical Notes)
- Baydin, A. G., Pearlmutter, B. A., Radul, A. A., Siskind, J. M. (2018). Automatic differentiation in machine learning: a survey · JMLR 18(153), 1–43
- Kaplan, J., McCandlish, S., Henighan, T., et al. (2020). Scaling Laws for Neural Language Models (cómputo de entrenamiento ≈ 6N por token; pase hacia atrás ≈ el doble que el de ida)
- Brown, T. B., Mann, B., Ryder, N., et al. (2020). Language Models are Few-Shot Learners (GPT-3: 175 mil millones de parámetros)
- Minsky, M. (1961). Steps toward Artificial Intelligence · Proceedings of the IRE 49(1), 8–30 (§ «The basic credit-assignment problem for complex reinforcement learning systems»)
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