Un grafo computacional es el mapa de operaciones que una red neuronal ejecuta para transformar sus entradas en una pérdida, y la diferenciación automática es la técnica que recorre ese mapa para calcular las derivadas exactas. Juntas resuelven el problema central del entrenamiento: saber cómo cambiar cada peso para reducir el error. Este artículo explica qué es el grafo, en qué se diferencian el modo directo y el modo inverso, y por qué la retropropagación no es más que un caso concreto de esta maquinaria. La misma explicación está disponible en inglés.

Fórmula clave $\dfrac{\partial L}{\partial w} = \sum_{k} \dfrac{\partial L}{\partial v_k}\,\dfrac{\partial v_k}{\partial w}$

Puntos clave

  • Un grafo computacional descompone una función en operaciones elementales (sumas, productos, activaciones) conectadas como nodos y aristas.
  • La diferenciación automática aplica la regla de la cadena sobre ese grafo para obtener derivadas exactas, sin las aproximaciones del método numérico.
  • Hay dos modos: el directo propaga derivadas hacia delante; el inverso las propaga hacia atrás y es el que usan las redes neuronales.
  • El modo inverso calcula el gradiente de todos los pesos en una sola pasada hacia atrás, con un coste de apenas unas 5 veces el de evaluar la función.
  • La retropropagación es diferenciación automática en modo inverso: PyTorch y TensorFlow la construyen y ejecutan por ti.

¿Qué es un grafo computacional?

Cuando escribes $L = (f(\mathbf{W}x+b)-y)^2$, esa expresión esconde una secuencia de operaciones simples. Un grafo computacional las hace explícitas: cada nodo es una operación elemental (un producto de matrices, una suma del sesgo, una activación, una resta) y cada arista lleva un valor de un nodo al siguiente. Siguiendo la notación compartida de esta serie, la suma ponderada $z = \mathbf{W}x+b$ y la activación $a = f(z)$ son dos nodos encadenados.

La ventaja de esta representación es doble. Primero, calcular la salida es recorrer el grafo de las entradas a la pérdida: eso es la propagación hacia delante. Segundo, y más importante, la estructura del grafo guarda toda la información necesaria para derivar. Cada nodo sabe cuál es su derivada local respecto a sus entradas, así que basta con multiplicar y sumar esas derivadas locales a lo largo de los caminos del grafo. Como recoge el capítulo 6 de Deep Learning[1], este grafo es la abstracción que convierte el cálculo de gradientes en un procedimiento mecánico.

Modo hacia delante y modo inverso

La diferenciación automática puede recorrer el grafo en dos sentidos. El modo directo (o hacia delante) propaga las derivadas en el mismo orden que el cálculo: parte de una entrada y arrastra su derivada nodo a nodo hasta la salida. Su coste es proporcional al número de entradas, así que resulta eficiente cuando hay pocas entradas y muchas salidas.

El modo inverso hace lo contrario. Primero completa la pasada hacia delante guardando los valores intermedios; después recorre el grafo desde la salida hacia las entradas, acumulando la derivada de la pérdida respecto a cada nodo. Su coste es proporcional al número de salidas. En una red neuronal la salida es un único escalar (la pérdida $L$) y las entradas son millones de pesos, de modo que el modo inverso obtiene el gradiente completo $\nabla L$ en una sola pasada hacia atrás. Un resultado clásico, el teorema de Baur-Strassen, garantiza que ese gradiente cuesta como máximo un factor constante (del orden de 5) respecto a evaluar la función original. Por eso entrenar un modelo con 175.000 millones de parámetros sigue siendo viable: el gradiente no cuesta 175.000 millones de veces más que una predicción, sino solo unas pocas veces más.

El precio del modo inverso es la memoria: para derivar necesita conservar todos los valores intermedios del paso directo hasta que termina la pasada hacia atrás. Ese es el motivo de que entrenar consuma mucha más memoria que solo predecir.

Cómo la diferenciación automática implementa la retropropagación

La retropropagación que estudiamos en la regla de la cadena es exactamente el modo inverso aplicado al grafo de una red. Cada capa aporta su derivada local (la de la activación $f'(z)$, la del producto por $\mathbf{W}$, la del sesgo) y el modo inverso las encadena de la salida a la entrada. La regla de la cadena reparte así la responsabilidad del error $L$ capa por capa, sin que tengamos que escribir a mano ninguna derivada.

Esta equivalencia tiene historia. El modo inverso lo describió Seppo Linnainmaa en su tesis de máster de 1970; Paul Werbos lo conectó con las redes neuronales en su tesis doctoral de 1974; y Rumelhart, Hinton y Williams lo popularizaron en 1986. Como resumen Baydin y sus colegas en su repaso del campo, «la retropropagación es un caso particular del modo inverso de la diferenciación automática». Dicho de otro modo, la fórmula del héroe de este artículo se sostiene: autodiff en modo inverso es retropropagación.

Frameworks: PyTorch y TensorFlow

Ningún ingeniero deriva estas expresiones a mano. Los frameworks construyen el grafo por ti y ejecutan el modo inverso automáticamente. PyTorch[2], disponible desde 2017, usa un motor llamado autograd que construye el grafo sobre la marcha: cada operación con tensores que requieren gradiente añade un nodo, y al llamar a loss.backward() recorre ese grafo hacia atrás y rellena el atributo .grad de cada parámetro. Es lo que se conoce como grafo dinámico o define-by-run.

TensorFlow[3] sigue una idea parecida con tf.GradientTape: un contexto que graba las operaciones ejecutadas para poder reproducir el paso inverso después. En ambos casos, el patrón es el mismo que en el grafo teórico: registrar operaciones hacia delante, guardar los valores intermedios y recorrer el registro hacia atrás para obtener los gradientes.

Ejemplo de grafo

Este es el grafo de una neurona con pérdida cuadrática, con su paso directo y su paso inverso:

Paso directo (de las entradas a la perdida):
  x, W, b          valores de entrada
  z = W * x + b    operacion 1: suma ponderada
  a = f(z)         operacion 2: activacion
  L = (a - y)^2    operacion 3: perdida

Paso inverso (regla de la cadena, de L a los pesos):
  dL/da = 2 * (a - y)
  dL/dz = dL/da * f'(z)
  dL/dW = dL/dz * x
  dL/db = dL/dz

Cada línea del paso inverso reutiliza el resultado de la anterior: eso es la clave de la eficiencia del modo inverso. La derivada de la pérdida respecto a cada peso se obtiene sin recalcular nada del paso directo, porque los valores intermedios ($z$, $a$) quedaron guardados.

Ver la derivación

Partimos de $L=(a-y)^2$ con $a=f(z)$ y $z=\mathbf{W}x+b$. La regla de la cadena encadena las tres derivadas locales del grafo: $\dfrac{\partial L}{\partial \mathbf{W}} = \dfrac{\partial L}{\partial a}\cdot\dfrac{\partial a}{\partial z}\cdot\dfrac{\partial z}{\partial \mathbf{W}} = 2(a-y)\cdot f'(z)\cdot x$. Cada factor es exactamente uno de los nodos del paso inverso: $2(a-y)$ es $\partial L/\partial a$, $f'(z)$ traduce de $a$ a $z$ y $x$ traduce de $z$ a $\mathbf{W}$.

Preguntas frecuentes

¿En qué se diferencia la diferenciación automática de la simbólica y la numérica?

La numérica aproxima la derivada con pequeñas perturbaciones y arrastra errores de redondeo. La simbólica manipula fórmulas y puede crecer de forma explosiva. La automática evalúa derivadas exactas operación a operación, con un coste controlado: reúne la precisión de la simbólica y la eficiencia de la numérica.

¿Por qué las redes neuronales usan el modo inverso y no el directo?

Porque una red tiene una salida (la pérdida) y muchísimas entradas (los pesos). El coste del modo inverso depende del número de salidas, así que con una única salida calcula el gradiente de todos los pesos en una pasada. El modo directo necesitaría una pasada por cada peso.

¿Necesito entender el grafo si uso PyTorch o TensorFlow?

Para tareas sencillas, el framework lo gestiona por ti. Pero entender el grafo ayuda a depurar gradientes que no fluyen, a controlar la memoria (los valores intermedios ocupan espacio) y a saber cuándo desconectar partes del grafo con operaciones como detach().

Conclusión

El grafo computacional y la diferenciación automática son la infraestructura silenciosa del aprendizaje profundo: convierten una función arbitraria en una red de operaciones derivables y calculan su gradiente de forma exacta y barata. El modo inverso, con su única pasada hacia atrás, es lo que hace escalable el entrenamiento. El siguiente paso natural es repasar cómo se encadenan esas derivadas en la regla de la cadena y volver al mapa general de las matemáticas para situar cada pieza.

Fuentes

  1. Deep Learning
  2. PyTorch
  3. TensorFlow
  4. Automatic differentiation in machine learning: a survey (Baydin et al.)
  5. Automatic differentiation (Wikipedia)

Ruta: Entrenamiento: descenso de gradiente y retropropagación