Backpropagation
La retropropagación aplica la regla de la cadena hacia atrás a través de una red neuronal para obtener el gradiente de cada peso en una sola pasada. Incluye las matemáticas, el coste y el código.
La retropropagación, abreviatura de «propagación hacia atrás de errores», es el algoritmo que calcula cuánto ha contribuido cada peso de una red neuronal al error de una predicción. Partiendo de la función de pérdida, aplica la regla de la cadena capa a capa hacia la entrada y reutiliza cada resultado intermedio, de modo que un único recorrido hacia atrás obtiene el gradiente de cada peso, tanto si el modelo tiene miles de parámetros como miles de millones. Después, un optimizador utiliza esos gradientes para actualizar los pesos, por lo que la retropropagación es el paso de aprendizaje que sustenta prácticamente todos los modelos de aprendizaje profundo. Rumelhart, Hinton y Williams popularizaron este método para las redes neuronales en el artículo de Nature de 1986 Learning representations by back-propagating errors.
Cómo funciona la retropropagación#
El entrenamiento con un lote consta de dos pasadas. En la pasada hacia delante, las entradas atraviesan cada capa, se guardan las activaciones intermedias y se calcula la pérdida al final. La pasada hacia atrás comienza en la pérdida y recorre las capas en orden inverso. Cada capa recibe el gradiente de la pérdida con respecto a su salida, denominado gradiente ascendente, y lo multiplica por sus derivadas locales para obtener dos resultados: el gradiente de los pesos de la capa, que se guarda para el optimizador, y el gradiente con respecto a la entrada de la capa, que se convierte en el gradiente ascendente de la capa inferior.
Como cada capa solo necesita su gradiente ascendente y las activaciones guardadas, nunca se calcula dos veces una derivada. En términos de diferenciación automática, la retropropagación es la diferenciación en modo inverso del grafo computacional de la red; PyTorch construye ese grafo durante la pasada hacia delante y lo recorre hacia atrás cuando se llama a loss.backward(). En una red con dos pesos, el resultado de autograd de PyTorch se puede comprobar con la regla de la cadena desarrollada a mano:
import torch
# A two-weight network: prediction = w2 * tanh(w1 * x)
x, target = torch.tensor(1.5), torch.tensor(0.5)
w1 = torch.tensor(0.8, requires_grad=True)
w2 = torch.tensor(-1.2, requires_grad=True)
# Forward pass, keeping the hidden activation h for the backward pass
h = torch.tanh(w1 * x)
loss = (w2 * h - target) ** 2
# Backward pass: autograd applies the chain rule from the loss back to each weight
loss.backward()
# The same chain rule by hand, reusing the upstream gradient dL/dy for both weights
dL_dy = 2 * (w2 * h - target)
dL_dw2 = dL_dy * h
dL_dw1 = dL_dy * w2 * (1 - h**2) * x
print(f"autograd: dL/dw1 = {w1.grad:.4f}, dL/dw2 = {w2.grad:.4f}")
print(f"by hand: dL/dw1 = {dL_dw1:.4f}, dL/dw2 = {dL_dw2:.4f}")Ambas líneas imprimen dL/dw1 = 1.6475, dL/dw2 = -2.5016. La versión escrita a mano calcula dL_dy una vez y lo reutiliza para ambos pesos; esa misma reutilización permite que autograd gestione redes con miles de millones de pesos. La retropropagación a través del tiempo (BPTT) es el mismo algoritmo aplicado a una red neuronal recurrente desplegada a lo largo de sus pasos temporales.
Retropropagación frente al optimizador#
La retropropagación solo calcula gradientes y no cambia ningún peso. Un algoritmo de optimización, como el descenso de gradiente estocástico (SGD) o Adam, convierte esos gradientes en actualizaciones de pesos, escaladas por la tasa de aprendizaje. PyTorch suma el resultado de cada pasada hacia atrás a los gradientes ya almacenados en los pesos, por lo que un paso del optimizador puede combinar varios lotes:
El entrenamiento de Ultralytics YOLO utiliza esta acumulación de gradientes para alcanzar un lote nominal de 64 imágenes (nbs=64): tras el calentamiento, una ejecución de batch=16 calcula la retropropagación en cada lote, pero ejecuta el paso del optimizador cada cuatro lotes, después de limitar la norma del gradiente combinado a 10.
Gradientes que desaparecen y que explotan#
La propagación hacia atrás multiplica las derivadas locales capa tras capa, por lo que el tamaño del gradiente puede reducirse o aumentar geométricamente con la profundidad. Cuando la mayoría de los factores son menores que 1, como ocurre con las unidades sigmoid saturadas, las primeras capas apenas reciben señal: este es el problema del gradiente que desaparece. Cuando la mayoría de los factores son mayores que 1, el problema del gradiente que explota genera actualizaciones enormes y pérdidas NaN. Las activaciones de la familia ReLU, la inicialización de pesos escalada, la normalización por lotes y las conexiones de salto de las redes residuales mantienen estables las magnitudes de los gradientes a lo largo de cientos de capas.
Coste computacional y de memoria#
Todas las activaciones que necesita una derivada local deben permanecer en memoria desde la propagación hacia delante hasta que la propagación hacia atrás llegue a ellas. Por eso, la memoria de entrenamiento aumenta con el tamaño del lote, la resolución de entrada y la profundidad, y el entrenamiento necesita mucha más memoria que la inferencia. La verificación de gradientes almacena solo algunas activaciones y vuelve a calcular las demás durante la propagación hacia atrás; así, intercambia más cómputo por menos memoria. La precisión mixta mantiene la mayoría de las activaciones en formatos de 16 bits, que ocupan la mitad que los números de coma flotante de 32 bits. En cuanto al cómputo, la propagación hacia atrás cuesta aproximadamente el doble que la propagación hacia delante, porque cada capa calcula los gradientes tanto de sus pesos como de sus entradas. Por eso, las estimaciones basadas en leyes de escalado cuentan unas 6 operaciones de coma flotante por parámetro y token de entrenamiento: 2 en la propagación hacia delante y 4 en la propagación hacia atrás.










