Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

No11 - Programación Diferencial Pt1

Programación Diferenciable: Métodos Forward

Fecha: 27/05/2026

Programación diferenciable

Se tiene una función de costo

L(θ),θRp,p1\mathcal{L}(\theta), \quad \theta \in \mathbb{R}^p, \quad p \gg 1

donde pp representa los parámetros de un modelo de muchas dimensiones.

Optimización de Parámetros

Para resolver el problema de minimización de la función de costo:

minθRpL(θ)\min_{\theta \in \mathbb{R}^p} \mathcal{L}(\theta)

se requiere, por ejemplo, realizar actualizaciones iterativas del parámetro θ\theta mediante el algoritmo de descenso de gradiente. La regla de actualización en el paso mm se define como:

θm+1=θmαmLθ(θm)\theta^{m+1} = \theta^m - \alpha^m \frac{\partial \mathcal{L}}{\partial \theta}(\theta^m)

donde αm\alpha^m representa la tasa de aprendizaje (learning rate) en la iteración mm. Este esquema de optimización basado en gradientes es fundamental en el entrenamiento de modelos como Redes Neuronales Informadas por la Física (PINNs) y Ecuaciones Diferenciales Universales (UDEs).

En este marco, desde una perspectiva frecuentista, el proceso busca obtener un estimador puntual óptimo θ\theta^*. Sin embargo, la optimización y el cálculo de estos gradientes son herramientas necesarias en ambos paradigmas: Frecuentista: Para converger directamente al óptimo global o local θ\theta^*. Bayesiano: Aunque el objetivo principal es obtener la distribución de probabilidad a posteriori, la optimización basada en gradientes sigue siendo indispensable. Hay varios métodos que permiten calcular L(θ)\mathcal{L}(\theta), a nosotros nos interesan los métodos de programación diferenciable para ecuaciones diferenciales.

Métodos de PD para ecs. diferenciables

Para UDEs y para NODEs se puede definir la función de costo asociada utilizando la norma L2L_2 al cuadrado:

L(θ)=1Ni=1Nyix(ti;θ)22\mathcal{L}(\theta) = \frac{1}{N} \sum_{i=1}^{N} \| y_i - x(t_i; \theta) \|_2^2

donde x(ti;θ)x(t_i; \theta) representa la solución de una ecuación diferencial evaluada en el instante tit_i.

Dado que esta función de costo tiene dentro una ecuación diferencial, su evaluación no es analítica y requiere el uso de un solver numérico. A nivel de implementación, no importa estrictamente cómo se evalúa L(θ)\mathcal{L}(\theta) en su totalidad, ya que la computadora resuelve el problema descomponiéndolo en una secuencia de operaciones atómicas e iterativas.

Para calcular los gradientes y optimizar este sistema, los enfoques se pueden dividir según dos ejes principales, generando cuatro categorías conceptuales:

1. Eje del momento de discretización: Continuo vs. Discreto

2. Eje de propagación de derivadas: Forward vs. Reverse

Diferencias finitas

Diferenciacion compleja

Proponemos una función de costo simplificada de un solo parámetro:

L(θ),θRp,p=1\mathcal{L}(\theta), \quad \theta \in \mathbb{R}^p, \quad p = 1

Si la función es localmente analítica (una condición que no siempre se puede garantizar teóricamente, pero que en la práctica general se cumple para la mayoría de los modelos), es posible realizar una extensión analítica de L\mathcal{L} hacia el plano complejo. De esta forma, el dominio de la función pasa a aceptar parámetros complejos:

L(θ),θCp\mathcal{L}(\theta), \quad \theta \in \mathbb{C}^p

A nivel operativo, si partimos de una variable real xRx \in \mathbb{R} y la extendemos a una variable compleja z=x+iyz = x + iy (con zCz \in \mathbb{C}), las transformaciones de las funciones elementales se comportan de la siguiente manera:

Nota computacional: Extender las funciones al plano complejo es la base conceptual del método de diferenciación numérica por Paso Complejo (Complex-Step Derivative). Esta técnica permite calcular gradientes perturbando el sistema en el eje imaginario, lo que evita por completo los errores por cancelación catastrófica (resta de números muy parecidos) que sufren los métodos discretos tradicionales como las diferencias finitas.

Definiendo a nuestro parámetro en el dominio complejo como z=x+iyz = x + iy (donde z=θz = \theta cuando y=0y=0), podemos expresar nuestra función descompuesta en su parte real e imaginaria:

L(z)=u(x,y)+iv(x,y)\mathcal{L}(z) = u(x,y) + i v(x,y)

Si L\mathcal{L} es localmente analítica (diferenciable en el sentido complejo) alrededor de zz, podemos aplicar:

Teorema de Cauchy-Riemann

Hipótesis: Sea una función de variable compleja L(z)=u(x,y)+iv(x,y)\mathcal{L}(z) = u(x,y) + i v(x,y) que es analítica en un entorno del punto zz.

Resultado: Las derivadas parciales de primer orden de uu y vv existen, son continuas y satisfacen las ecuaciones:

ux=vyyuy=vx\frac{\partial u}{\partial x} = \frac{\partial v}{\partial y} \quad \text{y} \quad \frac{\partial u}{\partial y} = -\frac{\partial v}{\partial x}

De este modo, sabemos que la derivada de la función respecto al parámetro real θ\theta equivale a la derivada parcial respecto a xx. Y por las ecuaciones de Cauchy-Riemann, esto es igual a la derivada de la parte imaginaria respecto a yy:

dLdθ=ux=vy\frac{d\mathcal{L}}{d\theta} = \frac{\partial u}{\partial x} = \frac{\partial v}{\partial y}

Por lo tanto

vyv(x,y+ϵ)v(x,y)ϵ\frac{\partial v}{\partial y} \approx \frac{v(x, y + \epsilon) - v(x, y)}{\epsilon}

Dado que partimos de un parámetro estrictamente real θ\theta, estamos evaluando en y=0y=0. Además, como L(θ)\mathcal{L}(\theta) devuelve una función de costo real, su parte imaginaria inicial es cero (v(x,0)=0v(x,0) = 0). Reemplazando esto en la expresión:

dLdθIm[L(θ+iϵ)]0ϵ\frac{d\mathcal{L}}{d\theta} \approx \frac{\text{Im}[\mathcal{L}(\theta + i \epsilon)] - 0}{\epsilon}

En conclusión, si L\mathcal{L} admite extensión compleja, podemos calcular su derivada de la siguiente manera:

dLdθIm[L(θ+iϵ)]ϵ,con ϵ1\frac{d\mathcal{L}}{d\theta} \approx \frac{\text{Im}[\mathcal{L}(\theta + i \epsilon)]}{\epsilon}, \quad \text{con } \epsilon \ll 1

Pros:

Contras:

Tanto el método de diferencias finitas como el de diferenciación compleja presentan un error de aproximación (de orden ϵ\epsilon). Por el contrario, Forward AD nos permite obtener la derivada numérica exacta, sin error de aproximación.

3. Diferenciación Automática Forward (Forward AD)

Concepto: Grafo Computacional

Para entender AD, primero debemos modelar nuestra función como un Grafo Dirigido Acíclico (DAG). En este esquema, definimos un conjunto de variables de entrada, variables intermedias y una variable de salida. Las variables de entrada se denotan como vp+1,vp+2,,v0v_{-p+1}, v_{-p+2}, \dots, v_0. Estas variables corresponden a los parámetros del modelo, por lo que forman el vector de entrada θRp\theta \in \mathbb{R}^p. Luego, tenemos las variables intermedias, que se denotan desde v1v_1 hasta vm1v_{m-1}. Finalmente, la variable vmv_m representa el output de nuestra función. En este grafo computacional, una variable vjv_j depende de viv_i siempre que i<ji < j. Las aristas del DAG representan las operaciones elementales que conectan a las variables de una capa con la siguiente.

Ejemplo: f(x)=sin(x2)f(x) = \sin(x^2)

Podemos representar esta función mediante un DAG de tres capas. En la primera capa, definimos la variable de entrada v0=xv_0 = x. La arista hacia la segunda capa aplica la operación tt2t \to t^2, generando la variable intermedia v1=v02v_1 = v_0^2. La arista hacia la tercera capa aplica la operación tsin(t)t \to \sin(t), generando el output v2=sin(v1)v_2 = \sin(v_1). De esta manera, obtenemos el resultado final v2=sin(x2)v_2 = \sin(x^2).

En el DAG general, nos interesa calcular la derivada del output con respecto a una de las entradas, es decir, vmvp+1\frac{\partial v_m}{\partial v_{-p+1}}. Para ello, utilizamos la Fórmula de Bauer. La Fórmula de Bauer establece que vivj\frac{\partial v_i}{\partial v_j} (con i>ji > j) es igual a la sumatoria, sobre todos los caminos posibles w0w1wkw_0 \to w_1 \to \dots \to w_k (donde w0=vjw_0 = v_j y wk=viw_k = v_i), del producto de las derivadas locales wk+1wk\frac{\partial w_{k+1}}{\partial w_k}.

vivj=caminosk=1K1wk+1wk\frac{\partial v_i}{\partial v_j} = \sum_{\text{caminos}} \prod_{k=1}^{K-1} \frac{\partial w_{k+1}}{\partial w_k}
Implementación de Forward AD: Números Duales

Una manera de implementar Forward AD es mediante el uso de Números Duales. Un número dual extiende los números reales introduciendo una componente abstracta ϵ\epsilon. Esta componente cumple con la propiedad de que ϵ2=0\epsilon^2 = 0, con ϵ0\epsilon \neq 0. Un número dual se escribe de la forma xϵ=x1+ϵx2x_\epsilon = x_1 + \epsilon x_2. En este x1x_1 es el valor real de la variable y x2x_2 representa la variable derivada. Ambos coeficientes, x1x_1 y x2x_2, pertenecen a los números reales.

Propiedades de los Números Duales:

Si tenemos dos números duales xϵ=x1+ϵx2x_\epsilon = x_1 + \epsilon x_2 e yϵ=y1+ϵy2y_\epsilon = y_1 + \epsilon y_2, se cumplen las siguientes propiedades:

En este contexto, x1x_1 almacena el valor de la variable original y x2x_2 almacena la derivada de esa variable con respecto a un parámetro. Por simplicidad, asumiendo p=1p=1, tenemos que x2=x1θx_2 = \frac{\partial x_1}{\partial \theta} e y2=y1θy_2 = \frac{\partial y_1}{\partial \theta}. Reemplazando en la regla del producto, obtenemos xϵyϵ=x1y1+ϵ(x1y1θ+y1x1θ)x_\epsilon \cdot y_\epsilon = x_1 y_1 + \epsilon \left( x_1 \frac{\partial y_1}{\partial \theta} + y_1 \frac{\partial x_1}{\partial \theta} \right). Esto equivale directamente a xϵyϵ=x1y1+ϵ(x1y1)θx_\epsilon \cdot y_\epsilon = x_1 y_1 + \epsilon \frac{\partial (x_1 y_1)}{\partial \theta}.

Implementación Computacional

Para implementar esto, extendemos el concepto de “número” en nuestro código al de “número dual”. De esta forma, cada operación matemática atómica sabe cómo multiplicar números duales y, en consecuencia, propaga la derivada automáticamente. En el Modo Forward (a diferencia del modo Reverse), la evaluación avanza desde las entradas hacia la salida. Para ello, inicializamos nuestras variables de entrada emparejando su valor con su derivada direccional. Por ejemplo, el número dual inicializado para la entrada vp+1v_{-p+1} sería: vp+1+ϵvp+1θ1v_{-p+1} + \epsilon \frac{\partial v_{-p+1}}{\partial \theta_1}.