Un tutorial oficial sobre @tf.function
dice:
Para obtener el máximo rendimiento y hacer que su modelo sea desplegable en cualquier lugar, use tf.function para hacer gráficos de sus programas. Gracias a AutoGraph, una sorprendente cantidad de código de Python simplemente funciona con tf.function, pero todavía hay dudas de las que debemos tener cuidado.
Las principales conclusiones y recomendaciones son:
- No confíe en los efectos secundarios de Python como la mutación de objetos o los anexos de listas.
- La función tf funciona mejor con operaciones TensorFlow, en lugar de operaciones NumPy o primitivas Python.
- En caso de duda, utilice el idioma for x in y.
Solo menciona cómo implementar @tf.function
funciones anotadas, pero no cuándo usarlo.
¿Hay una heurística sobre cómo decidir si al menos debería intentar anotar una función tf.function
? Parece que no hay razones para no hacerlo, a menos que sea demasiado flojo para eliminar los efectos secundarios o cambiar algunas cosas como range()
-> tf.range()
. Pero si estoy dispuesto a hacer esto ...
¿Hay alguna razón para no usar @tf.function
para todas las funciones?
fuente
tensorflow0.1
,tensorflow0.2
,tensorflow0.3
,tensorflow0.4
,tensorflow0.5
y así sucesivamente, así como una etiqueta para cada uno de estostf
módulos y clases luego. Además, ¿por qué no agregar una etiqueta para cada uno de los módulos estándar de Python y sus funciones y clases?tf.function
guía dice "Decorar funciones a nivel de módulo y métodos de clases a nivel de módulo, y evitar decorar funciones o métodos locales". Me parece recordar una redacción más explícita, como "no decorar todas las funciones, usartf.function
en funciones de nivel superior, como un ciclo de entrenamiento", pero puedo recordar mal (o tal vez se ha eliminado). OTOH, esta discusión tiene una entrada interesante de los desarrolladores, al final parece estar bien usarla en cualquier función para tensores / variables.@tf.function
funciones anotadas de @jdehesa AFAIK también compilan las funciones que ellos mismos llaman gráficos. Por lo tanto, solo necesitaría anotar el punto de entrada al módulo que sea coherente con lo que describe. Pero tampoco estaría de más anotar manualmente las funciones más bajas en la pila de llamadas.tf.function
se llama a varias veces, no puede evitar la "duplicación de código" en el gráfico, por lo que parece recomendable su uso generalizado.Respuestas:
TLDR: depende de su función y de si está en producción o desarrollo. No lo use
tf.function
si desea poder depurar su función fácilmente, o si se encuentra bajo las limitaciones de AutoGraph o la compatibilidad del código tf.v1. Recomiendo ver Inside TensorFlow habla sobre AutoGraph y Funciones, no sobre Sesiones .A continuación, desglosaré los motivos, todos tomados de la información disponible en línea por Google.
En general, el
tf.function
decorador hace que una función se compile como invocable que ejecuta un gráfico TensorFlow. Esto implica:Hay información detallada disponible sobre las ideas de diseño detrás de esto.
Beneficios de decorar una función con
tf.function
Beneficios generales
Para funciones con código Python / Uso de AutoGraph vía
tf.function
decoraciónSi desea usar AutoGraph,
tf.function
se recomienda usarlo en lugar de llamar directamente a AutoGraph. Las razones para esto incluyen: dependencias de control automático, se requiere para algunas API, más almacenamiento en caché y ayudantes de excepción (Fuente) .Inconvenientes de decorar una función con
tf.function
Inconvenientes generales
Para funciones con código Python / Uso de AutoGraph mediante
tf.function
decoraciónLa información detallada sobre las limitaciones de AutoGraph está disponible.
Para funciones con código tf.v1
tf.function
, pero está sujeto a cambios a medida que el código tf.v1 se elimina (Fuente)Para funciones con código tf.v2
Ejemplos de limitaciones.
Crear variables más de una vez
No está permitido crear variables más de una vez, como
v
en el siguiente ejemplo:En el siguiente código, esto se mitiga asegurándose de que
self.v
solo se crea una vez:Efectos secundarios ocultos no capturados por AutoGraph
Los cambios como
self.a
en este ejemplo no se pueden ocultar, lo que conduce a un error ya que el análisis de funciones cruzadas aún no se realiza (Fuente) :Los cambios a simple vista no son un problema:
Ejemplo de limitación debido al flujo de control TF
Esta declaración if conduce a un error porque el valor de else debe definirse para el flujo de control TF:
fuente
@tf.function
para la producción sino solo para el desarrollo no es una solución factible. En primer lugar, en el aprendizaje automático (al menos en investigación), la capacitación durante la etapa de desarrollo también crea el producto final (el modelo capacitado). En segundo lugar, los decoradores son un cambio significativo. No puedo simplemente ponerlos "después del desarrollo" y asegurarme de que el código se comporte igual. Esto significa que tengo que desarrollar y probar con ellos ya allí.tf.function
si es apropiado.tf.function es útil en la creación y el uso de gráficos computacionales, deben usarse en el entrenamiento y en la implementación, sin embargo, no es necesario para la mayoría de sus funciones.
Digamos que estamos construyendo una capa especial que estará separada de un modelo más grande. No queremos tener el decorador tf.function encima de la función que construye esa capa porque es simplemente una definición de cómo se verá la capa.
Por otro lado, digamos que vamos a hacer una predicción o continuar nuestro entrenamiento usando alguna función. Nos gustaría tener el decorador tf.function porque en realidad estamos usando el gráfico computacional para obtener algún valor.
Un gran ejemplo sería construir un modelo codificador-decodificador. NO coloque el decorador alrededor de la función para crear el codificador o decodificador o cualquier capa, eso es solo una definición de lo que hará. SÍ coloque el decorador alrededor del método "entrenar" o "predecir" porque esos realmente van a usar el gráfico computacional para el cálculo.
fuente
tf.range()
. AFAIK estos no se pueden convertir automáticamente. Por lo tanto, necesitaría escribir mis capas personalizadas con el gráfico automático en mente desde el principio. Por lo tanto, no puedo simplemente decorar la función de llamada (predicción).