Path: blob/master/site/es-419/guide/migrate/model_mapping.ipynb
25118 views
Copyright 2021 The TensorFlow Authors.
Usar modelos TF1.x en flujos de trabajo TF2
Esta guía proporciona una visión general y ejemplos de un shim de código de modelado que puede emplear para usar sus modelos TF1.x existentes en flujos de trabajo TF2 como ejecución eager, tf.function
y estrategias de distribución con cambios mínimos en su código de modelado.
Ámbito de uso
La shim descrita en esta guía está diseñada para los modelos TF1.x que se basan en:
tf.compat.v1.get_variable
ytf.compat.v1.variable_scope
para controlar la creación y reutilización de variables, yAPIs basadas en la recopilación de grafos como
tf.compat.v1.global_variables()
,tf.compat.v1.trainable_variables
,tf.compat.v1.losses.get_regularization_losses()
, ytf.compat.v1.get_collection()
para conservar un registro de las ponderaciones y las pérdidas de regularización.
Esto incluye la mayoría de los modelos construidos usando como base las APIs tf.compat.v1.layer
, tf.contrib.layers
, y TensorFlow-Slim.
La shim NO es necesaria para los siguientes modelos TF1.x:
Modelos Keras autónomos que ya hacen un seguimiento de todas sus ponderaciones entrenables y pérdidas de regularización a través de
model.trainable_weights
ymodel.losses
respectivamente.tf.Module
s que ya hacen un seguimiento de todas sus ponderaciones entrenables a través demodule.trainable_variables
, y sólo crean ponderaciones si aún no se han creado.
Es probable que estos modelos funcionen en TF2 con ejecución eager y tf.function
s de forma inmediata.
Preparación
Importe TensorFlow y otras dependencias.
El decorador track_tf1_style_variables
La shim clave descrita en esta guía es tf.compat.v1.keras.utils.track_tf1_style_variables
, un decorador que puede usar dentro de métodos pertenecientes a tf.keras.layers.Layer
y tf.Module
para hacer un seguimiento de las ponderaciones de estilo TF1.x y capturar las pérdidas de regularización.
Decorar los métodos de llamada de un tf.keras.layers.Layer
o tf.Module
con tf.compat.v1.keras.utils.track_tf1_style_variables
permite que la creación y reutilización de variables a través de tf.compat.v1.get_variable
(y por extensión tf.compat.v1.layers
) trabajen correctamente dentro del método decorado en lugar de hacerlo dentro del método decorado. También hará que la capa o módulo haga un seguimiento implícito de cualquier ponderación creada o a la que se acceda mediante get_variable
dentro del método decorado.
Además de hacer un seguimiento de las propias ponderaciones bajo las propiedades estándares layer.variable
/module.variable
/etc., si el método pertenece a una tf.keras.layers. Layer
, entonces cualquier pérdida de regularización especificada mediante los argumentos de regularizador get_variable
o tf.compat.v1.layers
será seguida por la capa bajo la propiedad estándar layer.losses
.
Este mecanismo de seguimiento permite usar grandes clases de código TF1.x-style model-forward-pass dentro de capas Keras o tf.Module
s en TF2 incluso con los comportamientos TF2 habilitados.
Ejemplos de uso
Los ejemplos de uso que aparecen a continuación muestran las shims de modelado utilizadas para decorar los métodos tf.keras.layers.Layer
, pero excepto en los casos en los que interactúan específicamente con características de Keras, también son aplicables al decorar los métodos tf.Module
.
Capa construida con tf.compat.v1.get_variable
Imagine que tiene una capa implementada directamente sobre tf.compat.v1.get_variable
de la siguiente manera:
Use la shim para convertirla en una capa y llámela sobre las entradas.
Acceda a las variables de seguimiento y a las pérdidas de regularización capturadas como una capa Keras estándar.
Para comprobar que las ponderaciones se reutilizan cada vez que llama a la capa, ponga todas las ponderaciones a cero y vuelva a llamar a la capa.
También puede usar la capa convertida directamente en la construcción de modelos funcionales Keras.
Modelo construido con tf.compat.v1.layers
Imagine que tiene una capa o modelo implementado directamente sobre tf.compat.v1.layers
como sigue:
Use la shim para convertirla en una capa y llámela sobre las entradas.
Advertencia: Por motivos de seguridad, asegúrese de poner todas las tf.compat.v1.layers
dentro de una variable_scope
de cadena no vacía. Esto se debe a que tf.compat.v1.layers
con nombres autogenerados siempre autoincrementarán el nombre fuera de cualquier ámbito de variable. Esto significa que los nombres de las variables solicitadas no coincidirán cada vez que llame a la capa/módulo. Así, en lugar de reutilizar las ponderaciones ya hechas, creará un nuevo conjunto de variables en cada llamada.
Acceda a las variables de seguimiento y a las pérdidas de regularización capturadas como una capa Keras estándar.
Para comprobar que las ponderaciones se reutilizan cada vez que llama a la capa, ponga todas las ponderaciones a cero y vuelva a llamar a la capa.
También puede usar la capa convertida directamente en la construcción de modelos funcionales Keras.
Capturar las actualizaciones de normalización por lotes y los args de training
del modelo
En TF1.x, la normalización por lotes se realiza así:
Tenga en cuenta que:
Las actualizaciones promedio móviles de normalización por lotes son rastreadas por
get_collection
que se llamó por separado de la capatf.compat.v1.layers.batch_normalization
requiere un argumentotraining
(generalmente llamadois_training
cuando se usan capas de normalización por lotes TF-Slim).
En TF2, debido a ejecución eager y a las dependencias de control automáticas, las actualizaciones promedio móviles de normalización por lotes se ejecutarán de inmediato. No es necesario recopilarlas por separado de la recolección de actualizaciones y añadirlas como dependencias de control explícitas.
Además, si le da un argumento training
al método de pasada hacia adelante de su tf.keras.layers.Layer
, Keras podrá pasarle la fase de entrenamiento actual y cualquier capa anidada al igual que lo hace para cualquier otra capa. Consulte la documentación de la API de tf.keras.Model
para saber cómo maneja Keras el argumento training
.
Si está decorando métodos tf.Module
, deberá asegurarse de pasar manualmente todos los argumentos training
que sean necesarios. Sin embargo, las actualizaciones promedio móviles de normalización por lotes se seguirán aplicando automáticamente sin necesidad de dependencias de control explícitas.
Los siguientes fragmentos de código demuestran cómo incrustar capas de normalización por lotes en el shim y cómo funciona su uso en un modelo Keras (aplicable a tf.keras.layers.Layer
).
Reutilización de variables basada en el ámbito variable
Las creaciones de variables en la pasada hacia adelante basadas en get_variable
mantendrán la misma semántica de nomenclatura y reutilización de variables que tienen los ámbitos de variables en TF1.x. Esto es cierto siempre que tenga al menos un ámbito externo no vacío para cualquier tf.compat.v1.layers
con nombres autogenerados, como se mencionó anteriormente.
Nota: La asignación de nombres y la reutilización tendrán un alcance dentro de una única instancia de capa/módulo. Las llamadas a get_variable
dentro de una capa o módulo decorado con shim no podrán consultar variables creadas dentro de capas o módulos. Puede evitar esto usando referencias Python a otras variables directamente si es necesario, en lugar de acceder a las variables a través de get_variable
.
Ejecución eager y tf.function
Como se ha visto anteriormente, los métodos decorados para tf.keras.layers.Layer
y tf.Module
se ejecutan dentro de ejecución eager y también son compatibles con tf.function
. Esto significa que puede usar pdb y otras herramientas interactivas para recorrer su pasada hacia adelante mientras se ejecuta.
Advertencia: Aunque es perfectamente seguro llamar a sus métodos de capa/módulo decorados con shim desde dentro de un tf.function
, no es seguro poner tf.function
s dentro de sus métodos decorados con shim si esos tf.functions
contienen llamadas get_variable
. Introducir una tf.function
restablece variable_scope
s, lo que significa que la reutilización de variables basada en el alcance de variables al estilo TF1.x que imita el shim no funcionará con esta configuración.
Estrategias de distribución
Las llamadas a get_variable
dentro de métodos de capas o módulos decorados con @track_tf1_style_variables
usan creaciones de variables estándares tf.Variable
de forma oculta. Esto significa que puede usarlas con las distintas estrategias de distribución disponibles con tf.distribute
, como MirroredStrategy
y TPUStrategy
.
Anidar tf.Variable
s, tf.Module
s, tf.keras.layers
y tf.keras.models
en llamadas decoradas
Decorar su llamada de capa en tf.compat.v1.keras.utils.track_tf1_style_variables
sólo añadirá un seguimiento implícito automático de las variables creadas (y reutilizadas) mediante tf.compat.v1.get_variable
. No capturará ponderaciones creadas directamente por llamadas a tf.Variable
, como las que usan las capas Keras típicas y la mayoría de tf.Module
. Esta sección describe cómo manejar estos casos anidados.
(Usos preexistentes) tf.keras.layers
y tf.keras.models
Para usos preexistentes de capas y modelos Keras anidados, use tf.compat.v1.keras.utils.get_or_create_layer
. Esto sólo se recomienda para facilitar la migración de los usos anidados de Keras existentes en TF1.x; el código nuevo debe usar la configuración explícita de atributos como se describe a continuación para tf.Variables y tf.Modules.
Para usar tf.compat.v1.keras.utils.get_or_create_layer
, envuelva el código que construye su modelo anidado en un método y páselo al método. Ejemplo:
Este método garantiza que estas capas anidadas sean reutilizadas y seguidas correctamente por tensorflow. Tenga en cuenta que el decorador @track_tf1_style_variables
sigue siendo necesario en el método apropiado. El método constructor de modelos pasado a get_or_create_layer
(en este caso, self.build_model
), no debe tomar argumentos.
Se hace seguimiento de las ponderaciones:
Y también la pérdida de regularización:
Migración incremental: tf.Variables
y tf. Modules
Si necesita incrustar llamadas tf.Variable
o tf. Module
en sus métodos decorados (por ejemplo, si está siguiendo la migración incremental a las API de TF2 no heredadas que se describe más adelante en esta guía), aún deberá realizar un seguimiento explícito de las mismas, con los siguientes requisitos:
Asegúrese explícitamente de que la variable/módulo/capa sólo se crea una vez
Adjúntelos explícitamente como atributos de instancia del mismo modo que lo haría al definir un módulo o capa típicos
Reutilice explícitamente el objeto ya creado en las llamadas que sigan
Esto garantiza que las ponderaciones no se creen nuevas en cada llamada y se reutilicen correctamente. Además, esto también garantiza el seguimiento de las ponderaciones existentes y de las pérdidas de regularización.
Aquí tiene un ejemplo de cómo puede quedar:
Tenga en cuenta que el seguimiento explícito del módulo anidado es necesario aunque esté decorado con el decorador track_tf1_style_variables
. Esto se debe a que cada módulo/capa con métodos decorados tiene asociado su propio almacén de variables.
Se hace un seguimiento correcto de las ponderaciones:
Así como de la pérdida de regularización:
Tenga en cuenta que si la NestedLayer
fuera un tf.Module
no Keras en su lugar, las variables seguirían siendo objeto de seguimiento, pero las pérdidas de regularización no serían objeto de seguimiento automático, por lo que tendría que hacer un seguimiento explícito por separado.
Orientación sobre los nombres de variables
Las llamadas explícitas tf.Variable
y las capas Keras usan un mecanismo de autogeneración de nombre de capa/nombre de variable diferente al que puede estar acostumbrado por la combinación de get_variable
y variable_scopes
. Aunque la shim hará que sus nombres de variables coincidan para las variables creadas por get_variable
incluso al pasar de grafos TF1.x a ejecución eager y tf.function
de TF2, no puede garantizar lo mismo para los nombres de variables generados para las llamadas tf.Variable
y las capas Keras que incruste dentro de sus decoradores de métodos. Incluso es posible que varias variables compartan el mismo nombre en la eager execution y tf.function
de TF2.
Debe tener especial cuidado con esto cuando siga las secciones sobre validación de la corrección y mapeado de los puntos de verificación TF1.x más adelante en esta guía.
Usar tf.compat.v1.make_template
en el método decorado
Es muy recomendable usar directamente tf.compat.v1.keras.utils.track_tf1_style_variables
en lugar de usar tf.compat.v1.make_template
, ya que es una capa más delgada encima de TF2.
Siga la orientación de esta sección para el código TF1.x anterior que ya dependía de tf.compat.v1.make_template
.
Dado que tf.compat.v1.make_template
envuelve el código que utiliza get_variable
, el decorador track_tf1_style_variables
le permite usar estas plantillas en las llamadas a capas y realizar con éxito el seguimiento de las ponderaciones y las pérdidas de regularización.
Sin embargo, asegúrese de llamar a make_template
sólo una vez y luego reutilizar la misma plantilla en cada llamada a la capa. De lo contrario, se creará una nueva plantilla cada vez que llame a la capa junto con un nuevo conjunto de variables.
Por ejemplo,
Advertencia: Evite compartir la misma plantilla make_template
creada a través de múltiples instancias de capa ya que puede romper los mecanismos de seguimiento de pérdidas de variables y regularización del decorador shim. Además, si planea usar el mismo nombre de make_template
dentro de múltiples instancias de capa, entonces debería anidar el uso de la plantilla creada dentro de un variable_scope
. De lo contrario, el nombre generado para el variable_scope
de la plantilla se incrementará con cada nueva instancia de la capa. Esto puede alterar los nombres de las ponderaciones de forma inesperada.
Migración incremental al TF2 nativo
Como ya se ha mencionado, track_tf1_style_variables
permite mezclar el estilo TF2 orientado a objetos tf.Variable
/tf.keras.layers.Layer
/tf. Module
con el uso heredado tf.compat.v1.get_variable
/tf.compat.v1.layers
dentro del mismo módulo/capa decorado.
Esto significa que después de haber hecho su modelo TF1.x totalmente compatible con TF2, puede escribir todos los nuevos componentes del modelo con las API nativas de TF2 (que no sean tf.compat.v1
) y hacer que interoperen con su código más antiguo.
Sin embargo, si sigue modificando sus componentes modelo más antiguos, también puede seleccionar cambiar gradualmente su uso de estilo heredado tf.compat.v1
a las API orientadas a objetos puramente nativas que se recomiendan para el código TF2 recién escrito.
El uso de tf.compat.v1.get_variable
puede ser reemplazado por llamadas a self.add_weight
si está decorando una capa/modelo Keras, o por llamadas a tf.Variable
si está decorando objetos Keras o tf.Module
s.
Tanto la capa de estilo funcional como la orientada a objetos tf.compat.v1.layers
pueden ser generalmente reemplazadas por la capa equivalente tf.keras.layers
sin que se requieran cambios en los argumentos.
También puede considerar fraccionar partes de su modelo o patrones comunes en capas/módulos individuales durante su paso incremental a APIs puramente nativas, que pueden usar por sí mismas track_tf1_style_variables
.
Una nota sobre Slim y contrib.layers
Una gran cantidad de código anterior de TF 1.x usa la librería Slim, que se empaquetó con TF 1.x como tf.contrib.layers
. Convertir el código que usa Slim a TF 2 nativo es más complicado que convertir v1.layers
. De hecho, quizá tenga sentido convertir primero su código Slim a v1.layers
y después convertirlo a Keras. A continuación encontrará una guía general para convertir el código Slim.
Asegúrese de que todos los argumentos son explícitos. Elimine
arg_scopes
si es posible. Si aún necesita usarlos, dividanormalizer_fn
yactivation_fn
en sus propias capas.Las capas conv separables mapean una o varias capas Keras diferentes (capas Keras a profundidad, enfocadas a puntos y separables).
Slim y
v1.layers
tienen diferentes nombres de argumentos y valores por defecto.Tenga en cuenta que algunos argumentos tienen escalas diferentes.
Migración a TF2 nativo ignorando la compatibilidad de puntos de verificación
El siguiente ejemplo de código demuestra un paso incremental de un modelo a APIs puramente nativas sin tener en cuenta la compatibilidad de los puntos de verificación.
A continuación, sustituya las APIs compat.v1
con sus equivalentes nativos orientados a objetos por partes. Empiece por cambiar la capa de convolución por un objeto Keras creado en el constructor de capas.
Use la clase v1.keras.utils.DeterministicRandomTestTool
para verificar que este cambio incremental deja el modelo con el mismo comportamiento que antes.
Ahora ha sustituido todas las compat.v1.layers
individuales por capas Keras nativas.
Por último, elimine tanto cualquier uso restante (que ya no sea necesario) de variable_scope
como el propio decorador track_tf1_style_variables
.
Ahora solo le queda una versión del modelo que usa APIs totalmente nativas.
Mantener la compatibilidad de los puntos de verificación durante la migración al TF2 nativo
El proceso de migración anterior a las APIs nativas de TF2 cambió tanto los nombres de las variables (ya que las APIs de Keras producen nombres de ponderación muy diferentes), como las rutas orientadas a objetos que apuntan a diferentes ponderaciones en el modelo. Estos cambios dejarán inservibles tanto los puntos de verificación basados en nombres al estilo TF1 como los puntos de verificación orientados a objetos al estilo TF2.
Sin embargo, en algunos casos, es posible que pueda tomar su punto de verificación original basado en nombres y encontrar un mapeado de las variables a sus nuevos nombres con enfoques como el que se detalla en la guía Reutilización de puntos de verificación TF1.x.
Algunos consejos para que esto sea factible son los siguientes:
Las variables siguen teniendo todas un argumento
name
que puede configurar.Los modelos Keras también toman un argumento
name
que configuran como prefijo para sus variables.La función
v1.name_scope
puede usarse para configurar los prefijos de los nombres de las variables. Esto es muy diferente detf.variable_scope
. Sólo afecta a los nombres, y no hace un seguimiento de las variables y su reutilización.
Con las indicaciones anteriores en mente, los ejemplos de código siguientes demuestran un flujo de trabajo que puede adaptar a su código para actualizar de forma incremental parte de un modelo mientras se actualizan simultáneamente los puntos de verificación.
Nota: Debido a la complejidad de la denominación de variables con las capas Keras, no se garantiza que esto funcione para todos los casos de uso.
Empiece por cambiar las capas
tf.compat.v1.layers
de estilo funcional por sus versiones orientadas a objetos.
A continuación, asigne los objetos compat.v1.layer y cualquier variable creada por
compat.v1.get_variable
como propiedades del objetotf.keras.layers.Layer
/tf.Module
cuyo método está decorado contrack_tf1_style_variables
(tenga en cuenta que cualquier punto de verificación del estilo TF2 orientado a objetos guardará ahora tanto una ruta por nombre de variable como la nueva ruta orientada a objetos).
Vuelva a guardar un punto de verificación cargado en este punto para guardar las rutas tanto por el nombre de la variable (para compat.v1.layers), como por el grafo de objetos orientado a objetos.
Ahora puede cambiar las
compat.v1.layers
orientadas a objetos por capas Keras nativas sin dejar de poder cargar el punto de verificación guardado recientemente. Asegúrese de conservar los nombres de las variables para lascompat.v1.layers
restantes registrando aún losvariable_scopes
autogenerados de las capas sustituidas. Estas capas/variables sustituidas ahora sólo usarán la ruta del atributo del objeto a las variables en el punto de verificación en lugar de la ruta del nombre de la variable.
En general, puede reemplazar el uso de compat.v1.get_variable
en variables adjuntas a propiedades por:
Cambiarlas para usar
tf.Variable
, OActualizarlas usando
tf.keras.layers.Layer.add_weight
. Tenga en cuenta que si no está cambiando todas las capas de una sola vez, esto puede cambiar la nomenclatura autogenerada de capas/variables para lascompat.v1.layers
restantes a las que les falta un argumentoname
. Si ese es el caso, debe conservar los nombres de las variables para lascompat.v1.layers
restantes igual abriendo y cerrando manualmente unámbito_variable
correspondiente al nombre de ámbito generado de lacompat.v1.layer
eliminada. De lo contrario, las rutas de los puntos de verificación existentes pueden entrar en conflicto y la carga de puntos de verificación se comportará de forma incorrecta.
Guardar un punto de verificación en este paso después de construir las variables hará que contenga sólo las rutas de objetos disponibles en ese momento.
Asegúrese de registrar los ámbitos de las compat.v1.layers
eliminadas para conservar los nombres de ponderación autogenerados para las compat.v1.layers
restantes.
Repita los pasos anteriores hasta que haya sustituido todas las
compat.v1.layers
ycompat.v1.get_variable
de su modelo por equivalentes totalmente nativos.
Recuerde realizar pruebas para asegurarse de que el punto de verificación recién actualizado sigue comportándose como espera. Aplique las técnicas descritas en la guía de validación de la corrección numérica en cada paso incremental de este proceso para asegurarse de que su código migrado se ejecuta correctamente.
Manejar los cambios de comportamiento de TF1.x a TF2 no cubiertos por los shim de modelado
Los shim de modelado descritos en esta guía pueden garantizar que las variables, las capas y las pérdidas de regularización creadas con las semánticas get_variable
, tf.compat.v1.layers
y variable_scope
sigan funcionando como antes al usar ejecución eager y tf.function
, sin tener que depender de las recopilaciones.
Esto no cubre toda la semántica específica de TF1.x en la que pueden estar basándose sus modelos de pase hacia adelante. En algunos casos, los shim pueden ser insuficientes para que su pase hacia delante modelo entre en TF2 por sí solo. Lea la Guía de comportamientos de TF1.x frente a TF2 para saber más sobre las diferencias de comportamiento entre TF1.x y TF2.