Programación Diferenciable: Métodos Reverse Pt1¶
Fecha: 03/06/2026
Programación diferenciable utilizando métodos reverse¶
Repaso de la clase anteirior: Diferenciación automática en modo forward¶
En la clase 12, se estudió el método de Automatic Differentiation (AD) en el caso Forward, implementado mediante los números duales. Repasaremos a continuación los conceptos de este caso que reaparecerán en esta clase.
Para calcular derivadas mediante AD, representamos el cálculo de una función como un grafo computacional. En este grafo, los nodos de entrada corresponden a los parámetros del problema, mientras que el nodo final representa la cantidad que deseamos diferenciar. Esta situación se muestra en
grafo-computacional.

Figure 1:Grafo computacional. Una cantidad de salida , generalmente la función de pérdida, se escribe en términos de los parámetros del problema () a partir de una serie de cantidades intermedias a . Las aristas dirigidas en el grafo muestran como las cantidades iniciales se utilizan para calcular las siguientes, y así sucesivamente.
A partir de esta representación, la derivada de la salida respecto a algún parámetro puede interpretarse en términos de los caminos del grafo. En particular, según la fórmula de Bauer, dicha derivada se obtiene como la suma de los productos de derivadas correspondientes a los diferentes caminos del gráfo que los unen (ver clase 11).
donde denota un camino dirigido en el grafo computacional desde hasta .
Costo computacional en la fórmula de Bauer, métodos de evaluación.¶
La eficiencia en la evaluación de la fórmula de Bauer depende del método utilizado.
Un método naïf consiste en listar todos los caminos del grafo computacional, calcular el producto de derivadas asociado a cada camino y luego sumar los resultados. Este procedimiento es altamente ineficiente, ya que muchos caminos comparten subcaminos, lo que implica recalcular múltiples veces las mismas derivadas sin reutilizar resultados.
Por ejemplo, en Figure 2 se muestran todas las aristas relevantes para calcular . No es difícil notar que existe más de un camino que conecta los nodos relevantes y que una parte importante de ellos utiliza la arista que une con , por lo que la derivada parcial se recalcula repetidamente a lo largo de distintos caminos.

Figure 2:Mismo grafo computacional de ejemplo que Figure 1. Se muestran resaltadas las aristas que componen los distintos caminos que unen los nodos correspondientes a y , y por lo tanto, que son relevantes para el cálculo de la derivada .
El método Forward¶
Otro método, empleado en la clase pasada, consiste en recorrer el grafo en un orden topológico, de manera que cada nodo se evalúa únicamente después de haber evaluado todos sus predecesores en el grafo. Esto permite reutilizar cálculos intermedios y evitar la enumeración explícita de todos los caminos, reduciendo significativamente el costo computacional.
Al propagar de manera ordenada los términos de la fórmula de Bauer, se van obteniendo derivadas parciales de nodos cada vez más “alejados” de las entradas. En este contexto, la estrategia forward para calcular la derivada consiste en expresar dicha cantidad en función de los predecesores inmediatos de :
Al ser inmediatamente próximo a , la derivada será sencilla de calcular, restando la dificultad en calcular , lo que se hará de forma recursiva reaplicando la fórmula.
En nuestro ejemplo (y como se muestra en Figure 3), comenzaremos calculando , luego y , luego , y , luego y y por último el resultado buscado .
Dado que las derivadas se calculan propagando información desde las entradas hacia la salida siguiendo el orden topológico del grafo, este procedimiento se denomina método Forward.

Figure 3:Mismo caso que Figure 2. Se muestra ahora también un orden posible en que un método forward logrará calcular las distintas derivadas parciales , con .
El método Reverse¶
Análogamente al método forward, que consistía en explorar los nodos del grafo de forma ordenada partiendo de los parámetros y llegando al valor de salida, el método reverse consistirá en explorar los nodos del grafo en un orden similar pero partiendo del valor de salida y dirigiéndose hacia los parámetros, calculando en el proceso derivadas de la salida respectoa valores de indices menores. Así, el método reverse para calcular una derivada con también hará uso de cantidades intermedias que sucedan al nodo y se valdrá de la relación dinámica:
De las dos derivadas a la derecha, esta vez será la que es fácil de calcular mientras que para se tendrá que aplicar la relación recursivamente. A este método también se le da el nombre back-propagation.
Reusando el ejemplo anterior (como se muestra en Figure 4), se calcularán primero y , luego , y , luego y y por último .

Figure 4:Mismo caso que Figure 2. Se muestra ahora también un orden posible en que un método reverse logrará calcular las distintas derivadas parciales , con .
Uso de memoria y checkpointing¶
Una desventaja del modo reverse respecto al modo forwards, es que requiere precomputar los valores asignados a cada nodo para poder evaluar las derivadas.
Por ejemplo, para calcular un valor para , uno necesita del valor de o en que evaluar la derivada.
En el modo forward, estos valores se generan y utilizan de manera secuencial a medida que avanza el cálculo. En cambio, en el modo reverse, los valores intermedios obtenidos durante el pase forward deben permanecer disponibles durante el recorrido inverso del grafo, como se esquematiza en Figure 5. Esto implica un costo adicional en memoria para guardar todas las variables intermedias del programa y un costo en tiempo por el acceso de la memoria.

Figure 5:Ventaja en memoria de los métodos modo forward con respecto a los modo reverse. Se esquematiza como en el caso forward, a medida que el programa calcula las diferentes cantidades intermedias del sistema (por ejemplo, resolviendo una ODE), estas ya se pueden utilizar para calcular los gradientes. En cambio, en el caso backwards, uno debe esperar a calcular la variable final antes de ir sucesivamente utilizando variables intermedias anteriores para propagar el gradiente para atrás.
Para aliviar esta demanda de memoria, se suele usar la estrategia de Checkpointing ilustrada en Figure 6. Esta estrategia consiste en guardar en memoria el estado del sistema únicamente en ciertos puntos espaciados del programa. Si luego para el cálculo de derivadas mediante algún metodo backwards se requieren valores intermedios a los puntos disponibles, estos deberán poder obtenerse corriendo el programa de vuelta a partir del punto guardado más cercano. Con esta estrategia se balancea el úso de memoria y cómputo al decidir sobre que puntos guardar el estado del sistema.

Figure 6:Mismo caso que Figure 5. Se muestra la estrategia de checkpointing, en que el estado del sistema (en este caso valor de la ODE) se guarda únicamente en los puntos marcados por una cruz azul. Al calcular gradientes mediante backpropagation, el valor de la ODE en el punto a considerar debe calcularse a partir del valor en memoria más cercano.
Esta estrategia permite equilibrar el uso de memoria y el costo computacional, intercambiando almacenamiento por costo de calculo computacional: cuanto menor es la cantidad de estados guardados, mayor es el trabajo necesario para reconstruir los valores intermedios durante el barrido inverso.
Cuando conviene usar reverse? VJP vs JVP¶
Vale la pena pensar en que casos las ventajas de los métodos reverse los vuelven convenientes aún considerando las penalidades en memoria que estos implican. Para ver un ejemplo de estas ventajas, podemos considerar una versión vectorizada de un grafo computacional (ilustrado en Figure 7):

Figure 7:Grafo computacional en una versión vectorizada, en que cada cantidad representa un vector de cantidades intermedias que se calculan de las cantidades del nodo anterior mediante una función .
Aquí, los parámetros son la entrada del grafo computacional, mientras que la salida es la función de costo , un escalar real. En las capas intermedias, las variables intermedias se calculan como
donde es la función que relaciona las variables en cada nodo con el anterior. Así, la función de costo será
Empleando la regla de la cadena, el Jacobiano de la función de costo será el producto de los Jacobianos de cada :
con
Podemos observar que en este caso el cálculo del lado derecho de la ecuación mediante un método backward corresponde a la propagación de derivadas en sentido inverso sobre el grafo computacional, lo cual es equivalente a la evaluación de productos vector–Jacobian (VJP). Este enfoque resulta especialmente eficiente cuando la dimensión de la salida es pequeña, en particular cuando .
En cambio, el método forward corresponde a la evaluación de productos Jacobian–vector (JVP), en los cuales se propagan direcciones desde las entradas hacia la salida. Este enfoque es más eficiente cuando la dimensión de entrada es pequeña, es decir, cuando no es grande.
Para calcular con y se requieren productos internos, cada uno de términos, el costo de calcular será de orden . En general, en un caso en que tenemos una función de costo con pasos intermedios, el número de operaciones a realizar en modo forward va como , mientras que en el modo backward irá como .
Esto, junto al mayor costo en memoria de aplicar metodos backwards, sugieren que esto es únicamente conveniente si .
| Caso | Forward (JVP) | Reverse (VJP) |
|---|---|---|
| ✓ | X | |
| ✓ | X | |
| X | ✓ |
Para dar números más concretos. Dada una ODE de variables, con , para , convene utilizar métodos reverse, mientras que en el caso contrario conviene utilizar métodos forward.
Método del adjunto¶
Este es un metodo estándar de programación diferencial utilizando ecuaciones diferenciales. Supongamos que tenemos que resolver una ecuación diferencial
.
Podemos discretizar la solución en el tiempo para buscar únicamente un conjunto , tales que con
Podemos concatenar los valores a cada tiempo en un super-vector, , tal que la expresión para la ecuación diferencial discreta es .
Podemos pensar, por ejemplo, en el caso de una ecuación diferencial lineal
Una discretización posible, si utilizamos el método de euler explicito, es
Esta ecuación diferencial a su vez se puede reescribir como
En forma vectorial, esta resultará
Podemos considerar que además tendremos una función de costo para contrastar con datos observacionales, . Por ejemplo, podría ser de la forma
siendo el peso asignado a cada observación.
El objetivo del método del adjunto será calcular el gradiente de la función de costo respecto a los parámetros, . Utilizando la regla de la cadena podemos relacionar este gradiente con la sensibilidad:
Para obtener la sensibilidad, que es el término difícil de esta ecuación resultante, se puede, por ejemplo, derivar la ecuación diferencial discreta. Dado que
Nota: asumimos que es inversible bajo ciertas condiciones.
Esta expresión para la sensibilidad, al remplazarse en la expresión del gradiente de la función de costo otorga
El método del adjunto define una cantidad , llamada la variable adjunta, tal que
La clase siguiente continuaremos viendo el método del adjunto, continuando con el caso discreto y luego incluyendo también el caso continuo.