Diferenciación automática - Automatic differentiation

En matemáticas y álgebra computacional , diferenciación automática ( AD ), también llamado diferenciación algorítmica , diferenciación computacional , auto-diferenciación , o simplemente autodiff , es un conjunto de técnicas para evaluar el derivado de una función especificada por un programa de ordenador. AD aprovecha el hecho de que todo programa informático, por complicado que sea, ejecuta una secuencia de operaciones aritméticas elementales (suma, resta, multiplicación, división, etc.) y funciones elementales (exp, log, sin, cos, etc.). Al aplicar la regla de la cadena repetidamente a estas operaciones, las derivadas de orden arbitrario se pueden calcular automáticamente, con precisión de trabajo y utilizando como máximo un pequeño factor constante más operaciones aritméticas que el programa original.

Figura 1: Cómo se relaciona la diferenciación automática con la diferenciación simbólica

La diferenciación automática es distinta de la diferenciación simbólica y la diferenciación numérica (el método de las diferencias finitas). La diferenciación simbólica puede conducir a un código ineficiente y enfrenta la dificultad de convertir un programa de computadora en una sola expresión, mientras que la diferenciación numérica puede introducir errores de redondeo en el proceso de discretización y cancelación. Ambos métodos clásicos tienen problemas para calcular derivadas más altas, donde la complejidad y los errores aumentan. Finalmente, ambos métodos clásicos son lentos para calcular derivadas parciales de una función con respecto a muchas entradas, como es necesario para los algoritmos de optimización basados ​​en gradientes . La diferenciación automática resuelve todos estos problemas.

La regla de la cadena, acumulación hacia adelante y hacia atrás.

Fundamental para AD es la descomposición de diferenciales proporcionada por la regla de la cadena . Por la composición simple

la regla de la cadena da

Por lo general, se presentan dos modos distintos de AD, acumulación hacia adelante (o modo hacia adelante ) y acumulación hacia atrás (o modo hacia atrás ). La acumulación hacia adelante especifica que uno atraviesa la regla de la cadena de adentro hacia afuera (es decir, primero calcula y luego y al final ), mientras que la acumulación inversa tiene el recorrido de afuera hacia adentro (primero calcula y luego y al final ). Más sucintamente,

  1. La acumulación hacia adelante calcula la relación recursiva: con , y,
  2. la acumulación inversa calcula la relación recursiva: con .

Acumulación hacia adelante

Figura 2: Ejemplo de acumulación directa con gráfico computacional

En adelante acumulación AD, primero se fija la variable independiente con respecto al cual la diferenciación se realiza y calcula la derivada de cada sub- expresión de forma recursiva. En un cálculo con lápiz y papel, esto implica sustituir repetidamente la derivada de las funciones internas en la regla de la cadena:

Esto se puede generalizar a múltiples variables como un producto matricial de los jacobianos .

En comparación con la acumulación inversa, la acumulación directa es natural y fácil de implementar, ya que el flujo de información derivada coincide con el orden de evaluación. Cada variable w se aumenta con su derivada (almacenada como un valor numérico, no como una expresión simbólica),

como se indica con el punto. A continuación, las derivadas se calculan en sincronía con los pasos de evaluación y se combinan con otras derivadas mediante la regla de la cadena.

Como ejemplo, considere la función:

Para mayor claridad, las sub-expresiones individuales se han etiquetado con las variables w i .

La elección de la variable independiente a la que se realiza la diferenciación afecta a los valores semilla 1 y 2 . Dado el interés en la derivada de esta función con respecto ax 1 , los valores semilla deben establecerse en:

Con los valores de semilla establecidos, los valores se propagan usando la regla de la cadena como se muestra. La Figura 2 muestra una descripción pictórica de este proceso como un gráfico computacional.

Operaciones para calcular el valor Operaciones para calcular la derivada
(semilla)
(semilla)

Para calcular el gradiente de esta función de ejemplo, que requiere las derivadas de f con respecto no solo a x 1 sino también a x 2 , se realiza un barrido adicional sobre el gráfico computacional utilizando los valores semilla .

La complejidad computacional de un barrido de acumulación hacia adelante es proporcional a la complejidad del código original.

La acumulación hacia adelante es más eficiente que la acumulación inversa para las funciones f  : R nR m con mn ya que solo son necesarios n barridos, en comparación con m barridos para la acumulación inversa.

Acumulación inversa

Figura 3: Ejemplo de acumulación inversa con gráfico computacional

En la acumulación de AD inversa, la variable dependiente a ser diferenciada es fijo y el derivado se calcula con respecto a cada sub- expresión de forma recursiva. En un cálculo con lápiz y papel, la derivada de las funciones externas se sustituye repetidamente en la regla de la cadena:

En la acumulación inversa, la cantidad de interés es el adjunto , denotado con una barra ( ); es una derivada de una variable dependiente elegida con respecto a una subexpresión w :

La acumulación inversa atraviesa la regla de la cadena de afuera hacia adentro, o en el caso del gráfico computacional de la Figura 3, de arriba hacia abajo. La función de ejemplo tiene valores escalares y, por lo tanto, solo hay una semilla para el cálculo derivado y solo se necesita un barrido del gráfico computacional para calcular el gradiente (de dos componentes). Esto es solo la mitad del trabajo en comparación con la acumulación directa, pero la acumulación inversa requiere el almacenamiento de las variables intermedias w i así como las instrucciones que las produjeron en una estructura de datos conocida como lista de Wengert (o "cinta"), que puede consumen una cantidad significativa de memoria si el gráfico computacional es grande. Esto se puede mitigar hasta cierto punto almacenando solo un subconjunto de las variables intermedias y luego reconstruyendo las variables de trabajo necesarias repitiendo las evaluaciones, una técnica conocida como rematerialización . Los puntos de control también se utilizan para salvar estados intermedios.

Las operaciones para calcular la derivada usando acumulación inversa se muestran en la siguiente tabla (observe el orden inverso):

Operaciones para calcular la derivada

El gráfico de flujo de datos de un cálculo se puede manipular para calcular el gradiente de su cálculo original. Esto se hace agregando un nodo adjunto para cada nodo primario, conectado por bordes adjuntos que son paralelos a los bordes primarios pero fluyen en la dirección opuesta. Los nodos en el gráfico adjunto representan la multiplicación por las derivadas de las funciones calculadas por los nodos en el primario. Por ejemplo, la adición en el primario provoca un abanico en el adjunto; fanout en el primario causa adición en el adjunto; una función unaria y = f  ( x ) en el primario causa = ȳ f  ′ ( x ) en el adjunto; etc.

La acumulación inversa es más eficiente que la acumulación directa para las funciones f  : R nR m con mn, ya que solo son necesarios m barridos, en comparación con n barridos para la acumulación directa.

El modo inverso AD fue publicado por primera vez en 1976 por Seppo Linnainmaa .

La propagación hacia atrás de errores en perceptrones multicapa, una técnica utilizada en el aprendizaje automático , es un caso especial de AD en modo inverso.

Más allá de la acumulación hacia adelante y hacia atrás

La acumulación hacia adelante y hacia atrás son solo dos formas (extremas) de atravesar la regla de la cadena. El problema de calcular un jacobiano completo de f  : R nR m con un número mínimo de operaciones aritméticas se conoce como el problema de acumulación jacobiana óptima (OJA), que es NP-completo . Para esta prueba es fundamental la idea de que pueden existir dependencias algebraicas entre los parciales locales que etiquetan los bordes del gráfico. En particular, dos o más etiquetas de borde pueden reconocerse como iguales. La complejidad del problema sigue abierta si se asume que todas las etiquetas de los bordes son únicas y algebraicamente independientes.

Diferenciación automática mediante números duales

La diferenciación automática en modo directo se logra aumentando el álgebra de números reales y obteniendo una nueva aritmética . Se agrega un componente adicional a cada número para representar la derivada de una función en el número, y todos los operadores aritméticos se extienden para el álgebra aumentada. El álgebra aumentada es el álgebra de números duales .

Reemplace cada número con el número , donde es un número real, pero es un número abstracto con la propiedad (un infinitesimal ; consulte Análisis suave infinitesimal ). Usando solo esto, la aritmética regular da

e igualmente para la resta y la división.

Ahora, los polinomios se pueden calcular en esta aritmética aumentada. Si entonces

donde denota la derivada de con respecto a su primer argumento y , llamada semilla , se puede elegir arbitrariamente.

La nueva aritmética consta de pares ordenados , elementos escritos , con aritmética ordinaria en el primer componente y aritmética de diferenciación de primer orden en el segundo componente, como se describió anteriormente. Al extender los resultados anteriores sobre polinomios a

funciones analíticas, se obtiene una lista de la aritmética básica y algunas funciones estándar para la nueva aritmética:
y en general para la función primitiva ,
donde y son las derivadas de con respecto a su primer y segundo argumento, respectivamente.

Cuando se aplica una operación aritmética básica binaria a argumentos mixtos (el par y el número real), el número real se eleva primero a . La derivada de una función en el punto ahora se encuentra calculando usando la aritmética anterior, que da como resultado.

Argumentos y funciones vectoriales

Las funciones multivariadas se pueden manejar con la misma eficiencia y los mismos mecanismos que las funciones univariadas mediante la adopción de un operador derivado direccional. Es decir, si es suficiente para calcular , la derivada direccional de at en la dirección , esto puede calcularse usando la misma aritmética que arriba. Si se desean todos los elementos de , entonces se requieren evaluaciones de funciones. Tenga en cuenta que en muchas aplicaciones de optimización, la derivada direccional es suficiente.

Alto orden y muchas variables

La aritmética anterior se puede generalizar para calcular las derivadas de segundo orden y superiores de funciones multivariadas. Sin embargo, las reglas aritméticas se complican rápidamente: la complejidad es cuadrática en el grado de derivada más alto. En su lugar, se puede utilizar el álgebra polinomial de Taylor truncada . La aritmética resultante, definida en números duales generalizados, permite un cálculo eficiente utilizando funciones como si fueran un tipo de datos. Una vez que se conoce el polinomio de Taylor de una función, las derivadas se extraen fácilmente.

Implementación

El modo directo AD se implementa mediante una interpretación no estándar del programa en la que los números reales se reemplazan por números duales, las constantes se elevan a números duales con un coeficiente épsilon cero y las primitivas numéricas se elevan para operar en números duales. Esta interpretación no estándar se implementa generalmente usando una de dos estrategias: transformación del código fuente o sobrecarga del operador .

Transformación de código fuente (SCT)

Figura 4: Ejemplo de cómo podría funcionar la transformación del código fuente

El código fuente de una función se reemplaza por un código fuente generado automáticamente que incluye declaraciones para calcular las derivadas intercaladas con las instrucciones originales.

La transformación del código fuente se puede implementar para todos los lenguajes de programación y también es más fácil para el compilador realizar optimizaciones de tiempo de compilación. Sin embargo, la implementación de la herramienta AD en sí es más difícil.

Sobrecarga del operador (OO)

Figura 5: Ejemplo de cómo podría funcionar la sobrecarga del operador

La sobrecarga del operador es una posibilidad para el código fuente escrito en un lenguaje que lo admita. Los objetos para números reales y operaciones matemáticas elementales deben sobrecargarse para adaptarse a la aritmética aumentada que se muestra arriba. Esto no requiere cambios en la forma o secuencia de operaciones en el código fuente original para que la función sea diferenciada, pero a menudo requiere cambios en los tipos de datos básicos para números y vectores para soportar la sobrecarga y, a menudo, también implica la inserción de operaciones especiales de marcado.

La sobrecarga del operador para la acumulación hacia adelante es fácil de implementar y también es posible para la acumulación hacia atrás. Sin embargo, los compiladores actuales se quedan atrás en la optimización del código en comparación con la acumulación directa.

La sobrecarga del operador, tanto para acumulación directa como inversa, puede ser adecuada para aplicaciones en las que los objetos son vectores de números reales en lugar de escalares. Esto se debe a que la cinta comprende operaciones vectoriales; esto puede facilitar implementaciones computacionalmente eficientes donde cada operación vectorial realiza muchas operaciones escalares. Se pueden usar técnicas de diferenciación algorítmica de vectores adjuntos (vector AAD), por ejemplo, para diferenciar valores calculados mediante simulación Monte-Carlo.

Ejemplos de implementaciones de diferenciación automática con sobrecarga de operadores en C ++ son las bibliotecas Adept y Stan .

Ver también

Notas

Referencias

Otras lecturas

enlaces externos

implementación de diferenciación automática basada en plantillas de C ++
  • Derivados depurables tangentes de origen a origen
  • [1] , Griegos exactos de primer y segundo orden por diferenciación algorítmica
  • [2] , Diferenciación algorítmica adjunta de una aplicación acelerada por GPU
  • [3] , Métodos adjuntos en soporte de herramientas de software de finanzas computacionales para diferenciación algorítmicaop