Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Migra tu código de TensorFlow 1 a TensorFlow 2

Ver en TensorFlow.org Ejecutar en Google Colab Ver fuente en GitHub Descargar cuaderno

Este documento para usuarios de API de TensorFlow de bajo nivel. Si está utilizando las API de alto nivel ( tf.keras ), es posible que deba realizar poca o ninguna acción para que su código sea totalmente compatible con TensorFlow 2.0:

Todavía es posible ejecutar código 1.X, sin modificar ( excepto para contrib ), en TensorFlow 2.0:

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

Sin embargo, esto no le permite aprovechar muchas de las mejoras realizadas en TensorFlow 2.0. Esta guía lo ayudará a actualizar su código, haciéndolo más simple, más eficiente y más fácil de mantener.

Script de conversión automática

El primer paso, antes de intentar implementar los cambios descritos en este documento, es intentar ejecutar el script de actualización .

Esto hará un pase inicial para actualizar su código a TensorFlow 2.0. Pero no puede convertir su código en idiomático a 2.0. Su código aún puede hacer uso de los tf.compat.v1 finales tf.compat.v1 para acceder a marcadores de posición, sesiones, colecciones y otras funciones de estilo 1.x.

Cambios de comportamiento de alto nivel

Si su código funciona en TensorFlow 2.0 usando tf.compat.v1.disable_v2_behavior() , todavía hay cambios de comportamiento globales que es posible que deba abordar. Los principales cambios son:

  • Ejecución v1.enable_eager_execution() , v1.enable_eager_execution() : cualquier código que utilice implícitamente un tf.Graph fallará. Asegúrese de envolver este código en un with tf.Graph().as_default() .

  • Variables de recursos, v1.enable_resource_variables() : Algunos códigos pueden depender de comportamientos no deterministas habilitados por las variables de referencia de TF. Las variables de recursos se bloquean mientras se escriben, por lo que proporcionan garantías de coherencia más intuitivas.

    • Esto puede cambiar el comportamiento en casos extremos.
    • Esto puede crear copias adicionales y puede tener un mayor uso de memoria.
    • Esto se puede desactivar pasando use_resource=False al constructor tf.Variable .
  • Formas de tensor, v1.enable_v2_tensorshape() : TF 2.0 simplifica el comportamiento de las formas de tensor. En lugar de t.shape[0].value , puede decir t.shape[0] . Estos cambios deben ser pequeños y tiene sentido corregirlos de inmediato. Consulte TensorShape para ver ejemplos.

  • Flujo de control, v1.enable_control_flow_v2() : La implementación del flujo de control TF 2.0 se ha simplificado y, por lo tanto, produce diferentes representaciones gráficas. Por favor, presente errores para cualquier problema.

Hacer el código 2.0 nativo

Esta guía mostrará varios ejemplos de conversión de código de TensorFlow 1.x a TensorFlow 2.0. Estos cambios permitirán que su código aproveche las optimizaciones de rendimiento y las llamadas API simplificadas.

En cada caso, el patrón es:

1. Reemplazar v1.Session.run llamadas v1.Session.run

Cada llamada a v1.Session.run debe ser reemplazada por una función de Python.

  • feed_dict y v1.placeholder s se convierten en argumentos de función.
  • Las fetches convierten en el valor de retorno de la función.
  • Durante la conversión, la ejecución ávida permite una fácil depuración con herramientas estándar de Python como pdb .

Después de eso, agregue un decorador tf.function para que se ejecute de manera eficiente en el gráfico. Consulte la Guía de autógrafos para obtener más información sobre cómo funciona.

Tenga en cuenta que:

  • A diferencia de v1.Session.run tf.function tiene una firma de retorno fija y siempre devuelve todas las salidas. Si esto causa problemas de rendimiento, cree dos funciones independientes.

  • No hay necesidad de tf.control_dependencies u operaciones similares: una tf.function comporta como si se ejecutara en el orden escrito. tf.Variable asignaciones tf.Variable y tf.assert s, por ejemplo, se ejecutan automáticamente.

La sección de conversión de modelos contiene un ejemplo práctico de este proceso de conversión.

2. Use objetos de Python para rastrear variables y pérdidas

En TF 2.0 se desaconseja enérgicamente todo seguimiento de variables basado en nombres. Utilice objetos de Python para realizar un seguimiento de las variables.

Utilice tf.Variable lugar de v1.get_variable .

Cada v1.variable_scope debe convertirse en un objeto Python. Normalmente, este será uno de los siguientes:

Si necesita agregar listas de variables (como tf.Graph.get_collection(tf.GraphKeys.VARIABLES) ), use los .variables y .trainable_variables de los objetos Layer y Model .

Estas clases de Layer y Model implementan otras propiedades que eliminan la necesidad de colecciones globales. Su propiedad .losses puede reemplazar el uso de la colección tf.GraphKeys.LOSSES .

Consulte las guías de keras para obtener más detalles.

3. Actualiza tus circuitos de entrenamiento

Utilice la API de nivel más alto que funcione para su caso de uso. Prefiere tf.keras.Model.fit a construir tus propios circuitos de entrenamiento.

Estas funciones de alto nivel gestionan muchos de los detalles de bajo nivel que podrían pasar por alto fácilmente si escribe su propio ciclo de entrenamiento. Por ejemplo, recopilan automáticamente las pérdidas de regularización y establecen el argumento training=True al llamar al modelo.

4. Actualice sus canalizaciones de entrada de datos

Utilice conjuntos de datos tf.data para la entrada de datos. Estos objetos son eficientes, expresivos y se integran bien con tensorflow.

Se pueden pasar directamente al método tf.keras.Model.fit .

model.fit(dataset, epochs=5)

Se pueden iterar sobre Python directamente estándar:

for example_batch, label_batch in dataset:
    break

5. compat.v1 símbolos de compat.v1

El módulo tf.compat.v1 contiene la API de TensorFlow 1.x completa, con su semántica original.

El script de actualización TF2 convertirá los símbolos a sus equivalentes 2.0 si dicha conversión es segura, es decir, si puede determinar que el comportamiento de la versión 2.0 es exactamente equivalente (por ejemplo, cambiará el nombre de v1.arg_max a tf.argmax , ya que esos son la misma función).

Después de que el script de actualización se realiza con un fragmento de código, es probable que haya muchas menciones de compat.v1 . Vale la pena revisar el código y convertirlos manualmente al equivalente 2.0 (debe mencionarse en el registro si lo hay).

Conversión de modelos

Variables de bajo nivel y ejecución del operador

Ejemplos de uso de API de bajo nivel incluyen:

Antes de convertir

Así es como pueden verse estos patrones en el código con TensorFlow 1.x.

import tensorflow as tf
import tensorflow.compat.v1 as v1

import tensorflow_datasets as tfds
g = v1.Graph()

with g.as_default():
  in_a = v1.placeholder(dtype=v1.float32, shape=(2))
  in_b = v1.placeholder(dtype=v1.float32, shape=(2))

  def forward(x):
    with v1.variable_scope("matmul", reuse=v1.AUTO_REUSE):
      W = v1.get_variable("W", initializer=v1.ones(shape=(2,2)),
                          regularizer=lambda x:tf.reduce_mean(x**2))
      b = v1.get_variable("b", initializer=v1.zeros(shape=(2)))
      return W * x + b

  out_a = forward(in_a)
  out_b = forward(in_b)
  reg_loss=v1.losses.get_regularization_loss(scope="matmul")

with v1.Session(graph=g) as sess:
  sess.run(v1.global_variables_initializer())
  outs = sess.run([out_a, out_b, reg_loss],
                feed_dict={in_a: [1, 0], in_b: [0, 1]})

print(outs[0])
print()
print(outs[1])
print()
print(outs[2])
[[1. 0.]
 [1. 0.]]

[[0. 1.]
 [0. 1.]]

1.0

Después de convertir

En el código convertido:

  • Las variables son objetos Python locales.
  • La función de forward todavía define el cálculo.
  • La llamada Session.run se reemplaza con una llamada para forward
  • El decorador opcional tf.function se puede agregar para el rendimiento.
  • Las regularizaciones se calculan manualmente, sin hacer referencia a ninguna colección global.
  • Sin sesiones ni marcadores de posición.
W = tf.Variable(tf.ones(shape=(2,2)), name="W")
b = tf.Variable(tf.zeros(shape=(2)), name="b")

@tf.function
def forward(x):
  return W * x + b

out_a = forward([1,0])
print(out_a)
tf.Tensor(
[[1. 0.]
 [1. 0.]], shape=(2, 2), dtype=float32)

out_b = forward([0,1])

regularizer = tf.keras.regularizers.l2(0.04)
reg_loss=regularizer(W)

Modelos basados ​​en tf.layers

El módulo v1.layers se utiliza para contener funciones de capa que se basaron en v1.variable_scope para definir y reutilizar variables.

Antes de convertir

def model(x, training, scope='model'):
  with v1.variable_scope(scope, reuse=v1.AUTO_REUSE):
    x = v1.layers.conv2d(x, 32, 3, activation=v1.nn.relu,
          kernel_regularizer=lambda x:0.004*tf.reduce_mean(x**2))
    x = v1.layers.max_pooling2d(x, (2, 2), 1)
    x = v1.layers.flatten(x)
    x = v1.layers.dropout(x, 0.1, training=training)
    x = v1.layers.dense(x, 64, activation=v1.nn.relu)
    x = v1.layers.batch_normalization(x, training=training)
    x = v1.layers.dense(x, 10)
    return x
train_data = tf.ones(shape=(1, 28, 28, 1))
test_data = tf.ones(shape=(1, 28, 28, 1))

train_out = model(train_data, training=True)
test_out = model(test_data, training=False)

print(train_out)
print()
print(test_out)
WARNING:tensorflow:From <ipython-input-1-1c8189d0d453>:4: conv2d (from tensorflow.python.keras.legacy_tf_layers.convolutional) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.keras.layers.Conv2D` instead.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/keras/legacy_tf_layers/convolutional.py:424: Layer.apply (from tensorflow.python.keras.engine.base_layer) is deprecated and will be removed in a future version.
Instructions for updating:
Please use `layer.__call__` method instead.
WARNING:tensorflow:From <ipython-input-1-1c8189d0d453>:5: max_pooling2d (from tensorflow.python.keras.legacy_tf_layers.pooling) is deprecated and will be removed in a future version.
Instructions for updating:
Use keras.layers.MaxPooling2D instead.
WARNING:tensorflow:From <ipython-input-1-1c8189d0d453>:6: flatten (from tensorflow.python.keras.legacy_tf_layers.core) is deprecated and will be removed in a future version.
Instructions for updating:
Use keras.layers.Flatten instead.
WARNING:tensorflow:From <ipython-input-1-1c8189d0d453>:7: dropout (from tensorflow.python.keras.legacy_tf_layers.core) is deprecated and will be removed in a future version.
Instructions for updating:
Use keras.layers.dropout instead.
WARNING:tensorflow:From <ipython-input-1-1c8189d0d453>:8: dense (from tensorflow.python.keras.legacy_tf_layers.core) is deprecated and will be removed in a future version.
Instructions for updating:
Use keras.layers.Dense instead.
WARNING:tensorflow:From <ipython-input-1-1c8189d0d453>:9: batch_normalization (from tensorflow.python.keras.legacy_tf_layers.normalization) is deprecated and will be removed in a future version.
Instructions for updating:
Use keras.layers.BatchNormalization instead.  In particular, `tf.control_dependencies(tf.GraphKeys.UPDATE_OPS)` should not be used (consult the `tf.keras.layers.BatchNormalization` documentation).
tf.Tensor([[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]], shape=(1, 10), dtype=float32)

tf.Tensor(
[[ 0.07562444 -0.27538717  0.21692204  0.2411264  -0.01209673 -0.0923705
   0.19058049 -0.00468709 -0.17215249 -0.07528099]], shape=(1, 10), dtype=float32)

Después de convertir

La mayoría de los argumentos se mantuvieron igual. Pero note las diferencias:

  • El modelo pasa el argumento de training a cada capa cuando se ejecuta.
  • El primer argumento de la función del model original (la entrada x ) se ha ido. Esto se debe a que las capas de objetos separan la construcción del modelo de la llamada al modelo.

También tenga en cuenta que:

  • Si estaba usando regularizadores de inicializadores de tf.contrib , estos tienen más cambios de argumentos que otros.
  • El código ya no escribe en colecciones, por lo que funciones como v1.losses.get_regularization_loss ya no devolverán estos valores, lo que podría romper los ciclos de entrenamiento.
model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(32, 3, activation='relu',
                           kernel_regularizer=tf.keras.regularizers.l2(0.04),
                           input_shape=(28, 28, 1)),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dropout(0.1),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.Dense(10)
])

train_data = tf.ones(shape=(1, 28, 28, 1))
test_data = tf.ones(shape=(1, 28, 28, 1))
train_out = model(train_data, training=True)
print(train_out)
tf.Tensor([[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]], shape=(1, 10), dtype=float32)

test_out = model(test_data, training=False)
print(test_out)
tf.Tensor(
[[-0.32132083  0.22252844 -0.11330387 -0.4613616  -0.08817139 -0.52697927
  -0.1538124   0.23069203 -0.15860984 -0.453844  ]], shape=(1, 10), dtype=float32)

# Here are all the trainable variables.
len(model.trainable_variables)
8
# Here is the regularization loss.
model.losses
[<tf.Tensor: shape=(), dtype=float32, numpy=0.08671833>]

Variables mixtas y v1.layers

El código existente a menudo mezcla variables y operaciones TF 1.x de nivel inferior con v1.layers nivel v1.layers .

Antes de convertir

def model(x, training, scope='model'):
  with v1.variable_scope(scope, reuse=v1.AUTO_REUSE):
    W = v1.get_variable(
      "W", dtype=v1.float32,
      initializer=v1.ones(shape=x.shape),
      regularizer=lambda x:0.004*tf.reduce_mean(x**2),
      trainable=True)
    if training:
      x = x + W
    else:
      x = x + W * 0.5
    x = v1.layers.conv2d(x, 32, 3, activation=tf.nn.relu)
    x = v1.layers.max_pooling2d(x, (2, 2), 1)
    x = v1.layers.flatten(x)
    return x

train_out = model(train_data, training=True)
test_out = model(test_data, training=False)

Después de convertir

Para convertir este código, siga el patrón de mapeo de capas a capas como en el ejemplo anterior.

El patrón general es:

  • Recopile los parámetros de la capa en __init__ .
  • Construye las variables en build .
  • Ejecute los cálculos en la call y devuelva el resultado.

v1.variable_scope es esencialmente una capa propia. Así que tf.keras.layers.Layer como tf.keras.layers.Layer . Consulte la guía para obtener más detalles.

# Create a custom layer for part of the model
class CustomLayer(tf.keras.layers.Layer):
  def __init__(self, *args, **kwargs):
    super(CustomLayer, self).__init__(*args, **kwargs)

  def build(self, input_shape):
    self.w = self.add_weight(
        shape=input_shape[1:],
        dtype=tf.float32,
        initializer=tf.keras.initializers.ones(),
        regularizer=tf.keras.regularizers.l2(0.02),
        trainable=True)

  # Call method will sometimes get used in graph mode,
  # training will get turned into a tensor
  @tf.function
  def call(self, inputs, training=None):
    if training:
      return inputs + self.w
    else:
      return inputs + self.w * 0.5
custom_layer = CustomLayer()
print(custom_layer([1]).numpy())
print(custom_layer([1], training=True).numpy())
[1.5]
[2.]

train_data = tf.ones(shape=(1, 28, 28, 1))
test_data = tf.ones(shape=(1, 28, 28, 1))

# Build the model including the custom layer
model = tf.keras.Sequential([
    CustomLayer(input_shape=(28, 28, 1)),
    tf.keras.layers.Conv2D(32, 3, activation='relu'),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Flatten(),
])

train_out = model(train_data, training=True)
test_out = model(test_data, training=False)

Algunas cosas a tener en cuenta:

  • Los modelos y capas de Keras subclasificados deben ejecutarse tanto en gráficos v1 (sin dependencias de control automático) como en modo ansioso

    • Envuelva la call() en un tf.function() para obtener autógrafos y dependencias de control automático
  • No olvide aceptar un argumento de training para call .

    • A veces es un tf.Tensor
    • A veces es un booleano de Python.
  • Cree variables de modelo en constructor o Model.build usando self.add_weight() .

    • En Model.build tiene acceso a la forma de entrada, por lo que puede crear pesos con la forma correspondiente.
    • El uso de tf.keras.layers.Layer.add_weight permite a Keras rastrear las variables y las pérdidas de regularización.
  • No deje tf.Tensors en sus objetos.

    • Pueden crearse en una función de tf.function o en el contexto ansioso, y estos tensores se comportan de manera diferente.
    • Use tf.Variable s para el estado, siempre se pueden usar en ambos contextos
    • tf.Tensors son solo para valores intermedios.

Una nota sobre Slim & contrib.layers

Una gran cantidad de código antiguo de TensorFlow 1.x usa la biblioteca Slim , que se empaquetó con TensorFlow 1.x como tf.contrib.layers . Como módulo contrib , ya no está disponible en TensorFlow 2.0, incluso en tf.compat.v1 . Convertir código usando Slim a TF 2.0 es más complicado que convertir repositorios que usan v1.layers . De hecho, puede tener sentido convertir su código Slim a v1.layers y luego convertirlo a Keras.

  • Elimina arg_scopes , todos los arg_scopes deben ser explícitos
  • Si los usa, divida normalizer_fn y activation_fn en sus propias capas
  • Las capas de conv separables se asignan a una o más capas de Keras diferentes (capas de Keras en profundidad, puntuales y separables)
  • Slim y v1.layers tienen diferentes nombres de arg y valores predeterminados
  • Algunos argumentos tienen diferentes escalas
  • Si usa modelos Slim pre-entrenados, pruebe los modelos pre-entrenados de Keras de tf.keras.applications o TF2 SavedModels de TF Hub exportados desde el código Slim original.

tf.contrib posible que algunas capas tf.contrib no se hayan movido al núcleo de TensorFlow, sino que se hayan movido al paquete de complementos TF .

Formación

Hay muchas formas de alimentar datos a un modelo tf.keras . Aceptarán generadores de Python y matrices Numpy como entrada.

La forma recomendada de alimentar datos a un modelo es utilizar el paquete tf.data , que contiene una colección de clases de alto rendimiento para manipular datos.

Si todavía usa tf.queue , ahora solo se admiten como estructuras de datos, no como canalizaciones de entrada.

Usar conjuntos de datos

El paquete de conjuntos de datos de TensorFlow ( tfds ) contiene utilidades para cargar conjuntos de datos predefinidos como objetos tf.data.Dataset .

Para este ejemplo, cargue el MNISTdataset, usando tfds :

datasets, info = tfds.load(name='mnist', with_info=True, as_supervised=True)
mnist_train, mnist_test = datasets['train'], datasets['test']
Downloading and preparing dataset mnist/3.0.1 (download: 11.06 MiB, generated: 21.00 MiB, total: 32.06 MiB) to /home/kbuilder/tensorflow_datasets/mnist/3.0.1...

Warning:absl:Dataset mnist is hosted on GCS. It will automatically be downloaded to your
local data directory. If you'd instead prefer to read directly from our public
GCS bucket (recommended if you're running on GCP), you can instead pass
`try_gcs=True` to `tfds.load` or set `data_dir=gs://tfds-data/datasets`.


Dataset mnist downloaded and prepared to /home/kbuilder/tensorflow_datasets/mnist/3.0.1. Subsequent calls will reuse this data.

Luego, prepare los datos para el entrenamiento:

  • Vuelve a escalar cada imagen.
  • Mezcla el orden de los ejemplos.
  • Recopile lotes de imágenes y etiquetas.
BUFFER_SIZE = 10 # Use a much larger value for real code.
BATCH_SIZE = 64
NUM_EPOCHS = 5


def scale(image, label):
  image = tf.cast(image, tf.float32)
  image /= 255

  return image, label

Para que el ejemplo sea breve, recorta el conjunto de datos para que solo devuelva 5 lotes:

train_data = mnist_train.map(scale).shuffle(BUFFER_SIZE).batch(BATCH_SIZE)
test_data = mnist_test.map(scale).batch(BATCH_SIZE)

STEPS_PER_EPOCH = 5

train_data = train_data.take(STEPS_PER_EPOCH)
test_data = test_data.take(STEPS_PER_EPOCH)
image_batch, label_batch = next(iter(train_data))

Usa bucles de entrenamiento Keras

Si no necesita un control de bajo nivel de su proceso de entrenamiento, se recomienda utilizar los métodos de fit , evaluate y predict integrados de Keras. Estos métodos proporcionan una interfaz uniforme para entrenar el modelo independientemente de la implementación (secuencial, funcional o subclasificada).

Las ventajas de estos métodos incluyen:

A continuación, se muestra un ejemplo de entrenamiento de un modelo con un Dataset . (Para obtener detalles sobre cómo funciona, consulte los tutoriales ).

model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(32, 3, activation='relu',
                           kernel_regularizer=tf.keras.regularizers.l2(0.02),
                           input_shape=(28, 28, 1)),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dropout(0.1),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.Dense(10)
])

# Model is the full model w/o custom layers
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

model.fit(train_data, epochs=NUM_EPOCHS)
loss, acc = model.evaluate(test_data)

print("Loss {}, Accuracy {}".format(loss, acc))
Epoch 1/5
5/5 [==============================] - 0s 6ms/step - loss: 1.5665 - accuracy: 0.4969
Epoch 2/5
5/5 [==============================] - 0s 6ms/step - loss: 0.5249 - accuracy: 0.8656
Epoch 3/5
5/5 [==============================] - 0s 5ms/step - loss: 0.3246 - accuracy: 0.9438
Epoch 4/5
5/5 [==============================] - 0s 6ms/step - loss: 0.2407 - accuracy: 0.9719
Epoch 5/5
5/5 [==============================] - 0s 5ms/step - loss: 0.1841 - accuracy: 0.9906
5/5 [==============================] - 0s 4ms/step - loss: 1.5957 - accuracy: 0.5375
Loss 1.5956770181655884, Accuracy 0.5375000238418579

Escribe tu propio bucle

Si el paso de entrenamiento del modelo de Keras funciona para usted, pero necesita más control fuera de ese paso, considere usar el método tf.keras.Model.train_on_batch , en su propio ciclo de iteración de datos.

Recuerde: muchas cosas se pueden implementar como tf.keras.callbacks.Callback .

Este método tiene muchas de las ventajas de los métodos mencionados en la sección anterior, pero le da al usuario el control del ciclo externo.

También puede utilizar tf.keras.Model.test_on_batch o tf.keras.Model.evaluate para comprobar el rendimiento durante el entrenamiento.

Para seguir entrenando el modelo anterior:

# Model is the full model w/o custom layers
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

for epoch in range(NUM_EPOCHS):
  #Reset the metric accumulators
  model.reset_metrics()

  for image_batch, label_batch in train_data:
    result = model.train_on_batch(image_batch, label_batch)
    metrics_names = model.metrics_names
    print("train: ",
          "{}: {:.3f}".format(metrics_names[0], result[0]),
          "{}: {:.3f}".format(metrics_names[1], result[1]))
  for image_batch, label_batch in test_data:
    result = model.test_on_batch(image_batch, label_batch,
                                 # return accumulated metrics
                                 reset_metrics=False)
  metrics_names = model.metrics_names
  print("\neval: ",
        "{}: {:.3f}".format(metrics_names[0], result[0]),
        "{}: {:.3f}".format(metrics_names[1], result[1]))
train:  loss: 0.145 accuracy: 1.000
train:  loss: 0.183 accuracy: 0.984
train:  loss: 0.216 accuracy: 0.953
train:  loss: 0.229 accuracy: 0.938
train:  loss: 0.201 accuracy: 0.969

eval:  loss: 1.588 accuracy: 0.628
train:  loss: 0.097 accuracy: 1.000
train:  loss: 0.101 accuracy: 1.000
train:  loss: 0.086 accuracy: 1.000
train:  loss: 0.130 accuracy: 0.984
train:  loss: 0.127 accuracy: 1.000

eval:  loss: 1.580 accuracy: 0.766
train:  loss: 0.086 accuracy: 1.000
train:  loss: 0.081 accuracy: 1.000
train:  loss: 0.079 accuracy: 1.000
train:  loss: 0.076 accuracy: 1.000
train:  loss: 0.077 accuracy: 1.000

eval:  loss: 1.542 accuracy: 0.809
train:  loss: 0.067 accuracy: 1.000
train:  loss: 0.068 accuracy: 1.000
train:  loss: 0.063 accuracy: 1.000
train:  loss: 0.063 accuracy: 1.000
train:  loss: 0.056 accuracy: 1.000

eval:  loss: 1.503 accuracy: 0.816
train:  loss: 0.055 accuracy: 1.000
train:  loss: 0.056 accuracy: 1.000
train:  loss: 0.048 accuracy: 1.000
train:  loss: 0.051 accuracy: 1.000
train:  loss: 0.048 accuracy: 1.000

eval:  loss: 1.482 accuracy: 0.828

Personaliza el paso de entrenamiento

Si necesita más flexibilidad y control, puede tenerlo implementando su propio ciclo de entrenamiento. Hay tres pasos:

  1. Itere sobre un generador de Python o tf.data.Dataset para obtener lotes de ejemplos.
  2. Utilice tf.GradientTape para recopilar gradientes.
  3. Utilice uno de los tf.keras.optimizers para aplicar actualizaciones de peso a las variables del modelo.

Recuerda:

  • Incluya siempre un argumento de training en el método de call de capas y modelos de subclases.
  • Asegúrese de llamar al modelo con el argumento de training configurado correctamente.
  • Según el uso, es posible que las variables del modelo no existan hasta que el modelo se ejecute en un lote de datos.
  • Necesita manejar manualmente cosas como pérdidas de regularización para el modelo.

Tenga en cuenta las simplificaciones relativas a v1:

  • No es necesario ejecutar inicializadores de variables. Las variables se inicializan al crearse.
  • No es necesario agregar dependencias de control manual. Incluso en tf.function operaciones actúan como en modo ansioso.
model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(32, 3, activation='relu',
                           kernel_regularizer=tf.keras.regularizers.l2(0.02),
                           input_shape=(28, 28, 1)),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dropout(0.1),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.Dense(10)
])

optimizer = tf.keras.optimizers.Adam(0.001)
loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)

@tf.function
def train_step(inputs, labels):
  with tf.GradientTape() as tape:
    predictions = model(inputs, training=True)
    regularization_loss=tf.math.add_n(model.losses)
    pred_loss=loss_fn(labels, predictions)
    total_loss=pred_loss + regularization_loss

  gradients = tape.gradient(total_loss, model.trainable_variables)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))

for epoch in range(NUM_EPOCHS):
  for inputs, labels in train_data:
    train_step(inputs, labels)
  print("Finished epoch", epoch)

Finished epoch 0
Finished epoch 1
Finished epoch 2
Finished epoch 3
Finished epoch 4

Métricas y pérdidas de nuevo estilo

En TensorFlow 2.0, las métricas y las pérdidas son objetos. Estos funcionan con entusiasmo y en tf.function s.

Un objeto de pérdida es invocable y espera el (y_true, y_pred) como argumentos:

cce = tf.keras.losses.CategoricalCrossentropy(from_logits=True)
cce([[1, 0]], [[-1.0,3.0]]).numpy()
4.01815

Un objeto de métrica tiene los siguientes métodos:

El objeto en sí es invocable. La llamada actualiza el estado con nuevas observaciones, como con update_state , y devuelve el nuevo resultado de la métrica.

No es necesario que inicialice manualmente las variables de una métrica y, dado que TensorFlow 2.0 tiene dependencias de control automático, tampoco debe preocuparse por ellas.

El siguiente código utiliza una métrica para realizar un seguimiento de la pérdida media observada dentro de un ciclo de entrenamiento personalizado.

# Create the metrics
loss_metric = tf.keras.metrics.Mean(name='train_loss')
accuracy_metric = tf.keras.metrics.SparseCategoricalAccuracy(name='train_accuracy')

@tf.function
def train_step(inputs, labels):
  with tf.GradientTape() as tape:
    predictions = model(inputs, training=True)
    regularization_loss=tf.math.add_n(model.losses)
    pred_loss=loss_fn(labels, predictions)
    total_loss=pred_loss + regularization_loss

  gradients = tape.gradient(total_loss, model.trainable_variables)
  optimizer.apply_gradients(zip(gradients, model.trainable_variables))
  # Update the metrics
  loss_metric.update_state(total_loss)
  accuracy_metric.update_state(labels, predictions)


for epoch in range(NUM_EPOCHS):
  # Reset the metrics
  loss_metric.reset_states()
  accuracy_metric.reset_states()

  for inputs, labels in train_data:
    train_step(inputs, labels)
  # Get the metric results
  mean_loss=loss_metric.result()
  mean_accuracy = accuracy_metric.result()

  print('Epoch: ', epoch)
  print('  loss:     {:.3f}'.format(mean_loss))
  print('  accuracy: {:.3f}'.format(mean_accuracy))

papá2804bc4

Nombres de métricas de Keras

En TensorFlow 2.0, los modelos keras son más consistentes en el manejo de nombres de métricas.

Ahora, cuando pasa una cadena en la lista de métricas, esa cadena exacta se usa como el name la métrica. Estos nombres son visibles en el objeto histórico devuelto por model.fit y en los registros pasados ​​a keras.callbacks . se establece en la cadena que pasó en la lista de métricas.

model.compile(
    optimizer = tf.keras.optimizers.Adam(0.001),
    loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics = ['acc', 'accuracy', tf.keras.metrics.SparseCategoricalAccuracy(name="my_accuracy")])
history = model.fit(train_data)
5/5 [==============================] - 0s 6ms/step - loss: 0.1233 - acc: 0.9937 - accuracy: 0.9937 - my_accuracy: 0.9937

history.history.keys()
dict_keys(['loss', 'acc', 'accuracy', 'my_accuracy'])

Esto difiere de las versiones anteriores en las que pasar metrics=["accuracy"] daría como resultado dict_keys(['loss', 'acc'])

Optimizadores de Keras

Los optimizadores en v1.train , como v1.train.AdamOptimizer y v1.train.GradientDescentOptimizer , tienen equivalentes en tf.keras.optimizers .

Convierta v1.train en keras.optimizers

A continuación, se indican algunos aspectos que debe tener en cuenta al convertir sus optimizadores:

Nuevos valores predeterminados para algunos tf.keras.optimizers

No hay cambios para optimizers.SGD , optimizers.Adam u optimizers.RMSprop .

Las siguientes tasas de aprendizaje predeterminadas han cambiado:

TensorBoard

TensorFlow 2 incluye cambios significativos en la API tf.summary usa para escribir datos de resumen para su visualización en TensorBoard. Para una introducción general al nuevo tf.summary , hay varios tutoriales disponibles que usan la API TF 2. Esto incluye una guía de migración de TensorBoard TF 2

Guardar y cargar

Compatibilidad con puntos de control

TensorFlow 2.0 usa puntos de control basados ​​en objetos .

Los puntos de control basados ​​en nombres de estilo antiguo aún se pueden cargar, si tiene cuidado. El proceso de conversión de código puede resultar en cambios de nombre de variable, pero existen soluciones.

El enfoque más simple es alinear los nombres del nuevo modelo con los nombres en el punto de control:

  • Las variables todavía tienen un argumento de name que puede establecer.
  • Los modelos de Keras también toman un argumento de name que establecen como prefijo para sus variables.
  • La función v1.name_scope se puede utilizar para establecer prefijos de nombre de variable. Esto es muy diferente de tf.variable_scope . Solo afecta a los nombres y no rastrea las variables ni la reutilización.

Si eso no funciona para su caso de uso, pruebe la función v1.train.init_from_checkpoint . Toma un argumento assignment_map , que especifica la asignación de nombres antiguos a nombres nuevos.

El repositorio de estimadores de TensorFlow incluye una herramienta de conversión para actualizar los puntos de control de los estimadores prefabricados de TensorFlow 1.X a 2.0. Puede servir como ejemplo de cómo crear una herramienta para un caso de uso similar.

Compatibilidad de modelos guardados

No hay problemas de compatibilidad importantes para los modelos guardados.

  • Los modelos guardados de TensorFlow 1.x funcionan en TensorFlow 2.x.
  • Los modelos guardados de TensorFlow 2.x funcionan en TensorFlow 1.x, si todas las operaciones son compatibles.

Un Graph.pb o Graph.pbtxt

No existe una forma sencilla de actualizar un archivo Graph.pb sin Graph.pb a TensorFlow 2.0. Su mejor opción es actualizar el código que generó el archivo.

Pero, si usted tiene un "gráfico congelado" (un tf.Graph donde las variables se han convertido en constantes), entonces es posible convertir a un concrete_function usando v1.wrap_function :

def wrap_frozen_graph(graph_def, inputs, outputs):
  def _imports_graph_def():
    tf.compat.v1.import_graph_def(graph_def, name="")
  wrapped_import = tf.compat.v1.wrap_function(_imports_graph_def, [])
  import_graph = wrapped_import.graph
  return wrapped_import.prune(
      tf.nest.map_structure(import_graph.as_graph_element, inputs),
      tf.nest.map_structure(import_graph.as_graph_element, outputs))

Por ejemplo, aquí hay un gráfico congelado para Inception v1, de 2016:

path = tf.keras.utils.get_file(
    'inception_v1_2016_08_28_frozen.pb',
    'http://storage.googleapis.com/download.tensorflow.org/models/inception_v1_2016_08_28_frozen.pb.tar.gz',
    untar=True)
Downloading data from http://storage.googleapis.com/download.tensorflow.org/models/inception_v1_2016_08_28_frozen.pb.tar.gz
24698880/24695710 [==============================] - 1s 0us/step

Cargue el tf.GraphDef :

graph_def = tf.compat.v1.GraphDef()
loaded = graph_def.ParseFromString(open(path,'rb').read())

Envuélvalo en una concrete_function :

inception_func = wrap_frozen_graph(
    graph_def, inputs='input:0',
    outputs='InceptionV1/InceptionV1/Mixed_3b/Branch_1/Conv2d_0a_1x1/Relu:0')

Pásale un tensor como entrada:

input_img = tf.ones([1,224,224,3], dtype=tf.float32)
inception_func(input_img).shape
TensorShape([1, 28, 28, 96])

Estimadores

Entrenamiento con estimadores

Los estimadores son compatibles con TensorFlow 2.0.

Cuando usa estimadores, puede usar input_fn() , tf.estimator.TrainSpec y tf.estimator.EvalSpec de TensorFlow 1.x.

Aquí hay un ejemplo que usa input_fn con entrenar y evaluar especificaciones.

Creación de las especificaciones input_fn y train / eval

# Define the estimator's input_fn
def input_fn():
  datasets, info = tfds.load(name='mnist', with_info=True, as_supervised=True)
  mnist_train, mnist_test = datasets['train'], datasets['test']

  BUFFER_SIZE = 10000
  BATCH_SIZE = 64

  def scale(image, label):
    image = tf.cast(image, tf.float32)
    image /= 255

    return image, label[..., tf.newaxis]

  train_data = mnist_train.map(scale).shuffle(BUFFER_SIZE).batch(BATCH_SIZE)
  return train_data.repeat()

# Define train & eval specs
train_spec = tf.estimator.TrainSpec(input_fn=input_fn,
                                    max_steps=STEPS_PER_EPOCH * NUM_EPOCHS)
eval_spec = tf.estimator.EvalSpec(input_fn=input_fn,
                                  steps=STEPS_PER_EPOCH)

Usando una definición de modelo de Keras

Hay algunas diferencias en cómo construir sus estimadores en TensorFlow 2.0.

Le recomendamos que defina su modelo usando Keras, luego use la utilidad tf.keras.estimator.model_to_estimator para convertir su modelo en un estimador. El siguiente código muestra cómo utilizar esta utilidad al crear y entrenar un estimador.

def make_model():
  return tf.keras.Sequential([
    tf.keras.layers.Conv2D(32, 3, activation='relu',
                           kernel_regularizer=tf.keras.regularizers.l2(0.02),
                           input_shape=(28, 28, 1)),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dropout(0.1),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.BatchNormalization(),
    tf.keras.layers.Dense(10)
  ])
model = make_model()

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

estimator = tf.keras.estimator.model_to_estimator(
  keras_model = model
)

tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)
INFO:tensorflow:Using default config.

INFO:tensorflow:Using default config.

Warning:tensorflow:Using temporary folder as model directory: /tmp/tmp333woaev

Warning:tensorflow:Using temporary folder as model directory: /tmp/tmp333woaev

INFO:tensorflow:Using the Keras model provided.

INFO:tensorflow:Using the Keras model provided.

Warning:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow_estimator/python/estimator/keras.py:220: set_learning_phase (from tensorflow.python.keras.backend) is deprecated and will be removed after 2020-10-11.
Instructions for updating:
Simply pass a True/False value to the `training` argument of the `__call__` method of your layer or model.

Warning:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow_estimator/python/estimator/keras.py:220: set_learning_phase (from tensorflow.python.keras.backend) is deprecated and will be removed after 2020-10-11.
Instructions for updating:
Simply pass a True/False value to the `training` argument of the `__call__` method of your layer or model.

INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmp333woaev', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmp333woaev', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

INFO:tensorflow:Not using Distribute Coordinator.

INFO:tensorflow:Not using Distribute Coordinator.

INFO:tensorflow:Running training and evaluation locally (non-distributed).

INFO:tensorflow:Running training and evaluation locally (non-distributed).

INFO:tensorflow:Start train and evaluate loop. The evaluate will happen after every checkpoint. Checkpoint frequency is determined based on RunConfig arguments: save_checkpoints_steps None or save_checkpoints_secs 600.

INFO:tensorflow:Start train and evaluate loop. The evaluate will happen after every checkpoint. Checkpoint frequency is determined based on RunConfig arguments: save_checkpoints_steps None or save_checkpoints_secs 600.

Warning:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/training_util.py:236: Variable.initialized_value (from tensorflow.python.ops.variables) is deprecated and will be removed in a future version.
Instructions for updating:
Use Variable.read_value. Variables in 2.X are initialized automatically both in eager and graph (inside tf.defun) contexts.

Warning:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/training_util.py:236: Variable.initialized_value (from tensorflow.python.ops.variables) is deprecated and will be removed in a future version.
Instructions for updating:
Use Variable.read_value. Variables in 2.X are initialized automatically both in eager and graph (inside tf.defun) contexts.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Warm-starting with WarmStartSettings: WarmStartSettings(ckpt_to_initialize_from='/tmp/tmp333woaev/keras/keras_model.ckpt', vars_to_warm_start='.*', var_name_to_vocab_info={}, var_name_to_prev_var_name={})

INFO:tensorflow:Warm-starting with WarmStartSettings: WarmStartSettings(ckpt_to_initialize_from='/tmp/tmp333woaev/keras/keras_model.ckpt', vars_to_warm_start='.*', var_name_to_vocab_info={}, var_name_to_prev_var_name={})

INFO:tensorflow:Warm-starting from: /tmp/tmp333woaev/keras/keras_model.ckpt

INFO:tensorflow:Warm-starting from: /tmp/tmp333woaev/keras/keras_model.ckpt

INFO:tensorflow:Warm-starting variables only in TRAINABLE_VARIABLES.

INFO:tensorflow:Warm-starting variables only in TRAINABLE_VARIABLES.

INFO:tensorflow:Warm-started 8 variables.

INFO:tensorflow:Warm-started 8 variables.

INFO:tensorflow:Create CheckpointSaverHook.

INFO:tensorflow:Create CheckpointSaverHook.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 0...

INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 0...

INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmp333woaev/model.ckpt.

INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmp333woaev/model.ckpt.

INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 0...

INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 0...

INFO:tensorflow:loss = 2.946777, step = 0

INFO:tensorflow:loss = 2.946777, step = 0

INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 25...

INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 25...

INFO:tensorflow:Saving checkpoints for 25 into /tmp/tmp333woaev/model.ckpt.

INFO:tensorflow:Saving checkpoints for 25 into /tmp/tmp333woaev/model.ckpt.

INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 25...

INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 25...

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Calling model_fn.

Warning:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_v1.py:2048: Model.state_updates (from tensorflow.python.keras.engine.training) is deprecated and will be removed in a future version.
Instructions for updating:
This property should not be used in TensorFlow 2.0, as updates are applied automatically.

Warning:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_v1.py:2048: Model.state_updates (from tensorflow.python.keras.engine.training) is deprecated and will be removed in a future version.
Instructions for updating:
This property should not be used in TensorFlow 2.0, as updates are applied automatically.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Starting evaluation at 2020-10-15T01:27:37Z

INFO:tensorflow:Starting evaluation at 2020-10-15T01:27:37Z

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Restoring parameters from /tmp/tmp333woaev/model.ckpt-25

INFO:tensorflow:Restoring parameters from /tmp/tmp333woaev/model.ckpt-25

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Evaluation [1/5]

INFO:tensorflow:Evaluation [1/5]

INFO:tensorflow:Evaluation [2/5]

INFO:tensorflow:Evaluation [2/5]

INFO:tensorflow:Evaluation [3/5]

INFO:tensorflow:Evaluation [3/5]

INFO:tensorflow:Evaluation [4/5]

INFO:tensorflow:Evaluation [4/5]

INFO:tensorflow:Evaluation [5/5]

INFO:tensorflow:Evaluation [5/5]

INFO:tensorflow:Inference Time : 0.84716s

INFO:tensorflow:Inference Time : 0.84716s

INFO:tensorflow:Finished evaluation at 2020-10-15-01:27:38

INFO:tensorflow:Finished evaluation at 2020-10-15-01:27:38

INFO:tensorflow:Saving dict for global step 25: accuracy = 0.715625, global_step = 25, loss = 1.5356585

INFO:tensorflow:Saving dict for global step 25: accuracy = 0.715625, global_step = 25, loss = 1.5356585

INFO:tensorflow:Saving 'checkpoint_path' summary for global step 25: /tmp/tmp333woaev/model.ckpt-25

INFO:tensorflow:Saving 'checkpoint_path' summary for global step 25: /tmp/tmp333woaev/model.ckpt-25

INFO:tensorflow:Loss for final step: 0.52498615.

INFO:tensorflow:Loss for final step: 0.52498615.

({'accuracy': 0.715625, 'loss': 1.5356585, 'global_step': 25}, [])

Usando un model_fn personalizado

Si tiene un estimador personalizado model_fn existente que necesita mantener, puede convertir su model_fn para usar un modelo de Keras.

Sin embargo, por razones de compatibilidad, un model_fn personalizado aún se ejecutará en el modo de gráfico de estilo 1.x. Esto significa que no hay una ejecución ávida ni dependencias de control automático.

Model_fn personalizado con cambios mínimos

Para que su model_fn personalizado funcione en TF 2.0, si prefiere cambios mínimos en el código existente, se pueden tf.compat.v1 símbolos tf.compat.v1 como optimizers y metrics .

Usar un modelo de Keras en un model_fn personalizado es similar a usarlo en un ciclo de entrenamiento personalizado:

  • Establezca la fase de training adecuada, según el argumento de mode .
  • Pase explícitamente las trainable_variables del modelo al optimizador.

Pero existen diferencias importantes en relación con un bucle personalizado :

  • En lugar de utilizar Model.losses , extraiga las pérdidas utilizando Model.get_losses_for .
  • Extraiga las actualizaciones del modelo usando Model.get_updates_for .

El siguiente código crea un estimador a partir de un model_fn personalizado, que ilustra todas estas preocupaciones.

def my_model_fn(features, labels, mode):
  model = make_model()

  optimizer = tf.compat.v1.train.AdamOptimizer()
  loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)

  training = (mode == tf.estimator.ModeKeys.TRAIN)
  predictions = model(features, training=training)

  if mode == tf.estimator.ModeKeys.PREDICT:
    return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)

  reg_losses = model.get_losses_for(None) + model.get_losses_for(features)
  total_loss=loss_fn(labels, predictions) + tf.math.add_n(reg_losses)

  accuracy = tf.compat.v1.metrics.accuracy(labels=labels,
                                           predictions=tf.math.argmax(predictions, axis=1),
                                           name='acc_op')

  update_ops = model.get_updates_for(None) + model.get_updates_for(features)
  minimize_op = optimizer.minimize(
      total_loss,
      var_list=model.trainable_variables,
      global_step=tf.compat.v1.train.get_or_create_global_step())
  train_op = tf.group(minimize_op, update_ops)

  return tf.estimator.EstimatorSpec(
    mode=mode,
    predictions=predictions,
    loss=total_loss,
    train_op=train_op, eval_metric_ops={'accuracy': accuracy})

# Create the Estimator & Train
estimator = tf.estimator.Estimator(model_fn=my_model_fn)
tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)
INFO:tensorflow:Using default config.

INFO:tensorflow:Using default config.

Warning:tensorflow:Using temporary folder as model directory: /tmp/tmpnhx_c2r_

Warning:tensorflow:Using temporary folder as model directory: /tmp/tmpnhx_c2r_

INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmpnhx_c2r_', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmpnhx_c2r_', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

INFO:tensorflow:Not using Distribute Coordinator.

INFO:tensorflow:Not using Distribute Coordinator.

INFO:tensorflow:Running training and evaluation locally (non-distributed).

INFO:tensorflow:Running training and evaluation locally (non-distributed).

INFO:tensorflow:Start train and evaluate loop. The evaluate will happen after every checkpoint. Checkpoint frequency is determined based on RunConfig arguments: save_checkpoints_steps None or save_checkpoints_secs 600.

INFO:tensorflow:Start train and evaluate loop. The evaluate will happen after every checkpoint. Checkpoint frequency is determined based on RunConfig arguments: save_checkpoints_steps None or save_checkpoints_secs 600.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Create CheckpointSaverHook.

INFO:tensorflow:Create CheckpointSaverHook.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 0...

INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 0...

INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmpnhx_c2r_/model.ckpt.

INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmpnhx_c2r_/model.ckpt.

INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 0...

INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 0...

INFO:tensorflow:loss = 2.7539256, step = 0

INFO:tensorflow:loss = 2.7539256, step = 0

INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 25...

INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 25...

INFO:tensorflow:Saving checkpoints for 25 into /tmp/tmpnhx_c2r_/model.ckpt.

INFO:tensorflow:Saving checkpoints for 25 into /tmp/tmpnhx_c2r_/model.ckpt.

INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 25...

INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 25...

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Starting evaluation at 2020-10-15T01:27:41Z

INFO:tensorflow:Starting evaluation at 2020-10-15T01:27:41Z

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Restoring parameters from /tmp/tmpnhx_c2r_/model.ckpt-25

INFO:tensorflow:Restoring parameters from /tmp/tmpnhx_c2r_/model.ckpt-25

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Evaluation [1/5]

INFO:tensorflow:Evaluation [1/5]

INFO:tensorflow:Evaluation [2/5]

INFO:tensorflow:Evaluation [2/5]

INFO:tensorflow:Evaluation [3/5]

INFO:tensorflow:Evaluation [3/5]

INFO:tensorflow:Evaluation [4/5]

INFO:tensorflow:Evaluation [4/5]

INFO:tensorflow:Evaluation [5/5]

INFO:tensorflow:Evaluation [5/5]

INFO:tensorflow:Inference Time : 0.94175s

INFO:tensorflow:Inference Time : 0.94175s

INFO:tensorflow:Finished evaluation at 2020-10-15-01:27:42

INFO:tensorflow:Finished evaluation at 2020-10-15-01:27:42

INFO:tensorflow:Saving dict for global step 25: accuracy = 0.678125, global_step = 25, loss = 1.5622549

INFO:tensorflow:Saving dict for global step 25: accuracy = 0.678125, global_step = 25, loss = 1.5622549

INFO:tensorflow:Saving 'checkpoint_path' summary for global step 25: /tmp/tmpnhx_c2r_/model.ckpt-25

INFO:tensorflow:Saving 'checkpoint_path' summary for global step 25: /tmp/tmpnhx_c2r_/model.ckpt-25

INFO:tensorflow:Loss for final step: 0.39462265.

INFO:tensorflow:Loss for final step: 0.39462265.

({'accuracy': 0.678125, 'loss': 1.5622549, 'global_step': 25}, [])

model_fn personalizado con símbolos TF 2.0

Si desea deshacerse de todos los símbolos TF model_fn actualizar su model_fn personalizado a TF 2.0 nativo, debe actualizar el optimizador y las métricas a tf.keras.optimizers y tf.keras.metrics .

En el model_fn personalizado_fn, además de los cambios anteriores, es necesario realizar más actualizaciones:

Para el ejemplo anterior de my_model_fn , el código migrado con símbolos 2.0 se muestra como:

def my_model_fn(features, labels, mode):
  model = make_model()

  training = (mode == tf.estimator.ModeKeys.TRAIN)
  loss_obj = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
  predictions = model(features, training=training)

  # Get both the unconditional losses (the None part)
  # and the input-conditional losses (the features part).
  reg_losses = model.get_losses_for(None) + model.get_losses_for(features)
  total_loss=loss_obj(labels, predictions) + tf.math.add_n(reg_losses)

  # Upgrade to tf.keras.metrics.
  accuracy_obj = tf.keras.metrics.Accuracy(name='acc_obj')
  accuracy = accuracy_obj.update_state(
      y_true=labels, y_pred=tf.math.argmax(predictions, axis=1))

  train_op = None
  if training:
    # Upgrade to tf.keras.optimizers.
    optimizer = tf.keras.optimizers.Adam()
    # Manually assign tf.compat.v1.global_step variable to optimizer.iterations
    # to make tf.compat.v1.train.global_step increased correctly.
    # This assignment is a must for any `tf.train.SessionRunHook` specified in
    # estimator, as SessionRunHooks rely on global step.
    optimizer.iterations = tf.compat.v1.train.get_or_create_global_step()
    # Get both the unconditional updates (the None part)
    # and the input-conditional updates (the features part).
    update_ops = model.get_updates_for(None) + model.get_updates_for(features)
    # Compute the minimize_op.
    minimize_op = optimizer.get_updates(
        total_loss,
        model.trainable_variables)[0]
    train_op = tf.group(minimize_op, *update_ops)

  return tf.estimator.EstimatorSpec(
    mode=mode,
    predictions=predictions,
    loss=total_loss,
    train_op=train_op,
    eval_metric_ops={'Accuracy': accuracy_obj})

# Create the Estimator & Train.
estimator = tf.estimator.Estimator(model_fn=my_model_fn)
tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)
INFO:tensorflow:Using default config.

INFO:tensorflow:Using default config.

Warning:tensorflow:Using temporary folder as model directory: /tmp/tmp3kddt__h

Warning:tensorflow:Using temporary folder as model directory: /tmp/tmp3kddt__h

INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmp3kddt__h', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmp3kddt__h', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true
graph_options {
  rewrite_options {
    meta_optimizer_iterations: ONE
  }
}
, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

INFO:tensorflow:Not using Distribute Coordinator.

INFO:tensorflow:Not using Distribute Coordinator.

INFO:tensorflow:Running training and evaluation locally (non-distributed).

INFO:tensorflow:Running training and evaluation locally (non-distributed).

INFO:tensorflow:Start train and evaluate loop. The evaluate will happen after every checkpoint. Checkpoint frequency is determined based on RunConfig arguments: save_checkpoints_steps None or save_checkpoints_secs 600.

INFO:tensorflow:Start train and evaluate loop. The evaluate will happen after every checkpoint. Checkpoint frequency is determined based on RunConfig arguments: save_checkpoints_steps None or save_checkpoints_secs 600.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Create CheckpointSaverHook.

INFO:tensorflow:Create CheckpointSaverHook.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 0...

INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 0...

INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmp3kddt__h/model.ckpt.

INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmp3kddt__h/model.ckpt.

INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 0...

INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 0...

INFO:tensorflow:loss = 2.4914804, step = 0

INFO:tensorflow:loss = 2.4914804, step = 0

INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 25...

INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 25...

INFO:tensorflow:Saving checkpoints for 25 into /tmp/tmp3kddt__h/model.ckpt.

INFO:tensorflow:Saving checkpoints for 25 into /tmp/tmp3kddt__h/model.ckpt.

INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 25...

INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 25...

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Done calling model_fn.

INFO:tensorflow:Starting evaluation at 2020-10-15T01:27:45Z

INFO:tensorflow:Starting evaluation at 2020-10-15T01:27:45Z

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Graph was finalized.

INFO:tensorflow:Restoring parameters from /tmp/tmp3kddt__h/model.ckpt-25

INFO:tensorflow:Restoring parameters from /tmp/tmp3kddt__h/model.ckpt-25

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Done running local_init_op.

INFO:tensorflow:Evaluation [1/5]

INFO:tensorflow:Evaluation [1/5]

INFO:tensorflow:Evaluation [2/5]

INFO:tensorflow:Evaluation [2/5]

INFO:tensorflow:Evaluation [3/5]

INFO:tensorflow:Evaluation [3/5]

INFO:tensorflow:Evaluation [4/5]

INFO:tensorflow:Evaluation [4/5]

INFO:tensorflow:Evaluation [5/5]

INFO:tensorflow:Evaluation [5/5]

INFO:tensorflow:Inference Time : 0.91708s

INFO:tensorflow:Inference Time : 0.91708s

INFO:tensorflow:Finished evaluation at 2020-10-15-01:27:46

INFO:tensorflow:Finished evaluation at 2020-10-15-01:27:46

INFO:tensorflow:Saving dict for global step 25: Accuracy = 0.690625, global_step = 25, loss = 1.554177

INFO:tensorflow:Saving dict for global step 25: Accuracy = 0.690625, global_step = 25, loss = 1.554177

INFO:tensorflow:Saving 'checkpoint_path' summary for global step 25: /tmp/tmp3kddt__h/model.ckpt-25

INFO:tensorflow:Saving 'checkpoint_path' summary for global step 25: /tmp/tmp3kddt__h/model.ckpt-25

INFO:tensorflow:Loss for final step: 0.3999393.

INFO:tensorflow:Loss for final step: 0.3999393.

({'Accuracy': 0.690625, 'loss': 1.554177, 'global_step': 25}, [])

Estimadores prediseñados

Los estimadores prediseñados de la familia de tf.estimator.DNN* , tf.estimator.Linear* y tf.estimator.DNNLinearCombined* aún son compatibles con la API de TensorFlow 2.0; sin embargo, algunos argumentos han cambiado:

  1. input_layer_partitioner : Eliminado en 2.0.
  2. loss_reduction : actualizado a tf.keras.losses.Reduction lugar de tf.compat.v1.losses.Reduction . Su valor predeterminado también se cambia a tf.keras.losses.Reduction.SUM_OVER_BATCH_SIZE de tf.compat.v1.losses.Reduction.SUM .
  3. optimizer , dnn_optimizer y linear_optimizer : este linear_optimizer se ha actualizado a tf.keras.optimizers lugar de tf.compat.v1.train.Optimizer .

Para migrar los cambios anteriores:

  1. No se necesita migración para input_layer_partitioner ya que Distribution Strategy lo manejará automáticamente en TF 2.0.
  2. Para loss_reduction , consulte tf.keras.losses.Reduction para conocer las opciones admitidas.
  3. Para los argumentos del optimizer , si no pasa un optimizer , dnn_optimizer o linear_optimizer arg, o si especifica el optimizer arg como una string en su código, no necesita cambiar nada. tf.keras.optimizers se utiliza de forma predeterminada. De lo contrario, debe actualizarlo desde tf.compat.v1.train.Optimizer a sus tf.keras.optimizers correspondientes

Convertidor de punto de control

La migración a keras.optimizers romperá los puntos de control guardados con TF 1.x, ya que tf.keras.optimizers genera un conjunto diferente de variables que se guardarán en los puntos de control. Para hacer que el antiguo punto de control sea reutilizable después de su migración a TF 2.0, pruebe la herramienta de conversión de puntos de control .

 curl -O https://raw.githubusercontent.com/tensorflow/estimator/master/tensorflow_estimator/python/estimator/tools/checkpoint_converter.py
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 15165  100 15165    0     0  32265      0 --:--:-- --:--:-- --:--:-- 32197

La herramienta tiene ayuda incorporada:

 python checkpoint_converter.py -h
2020-10-15 01:27:47.423752: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libcudart.so.10.1
usage: checkpoint_converter.py [-h]
                               {dnn,linear,combined} source_checkpoint
                               source_graph target_checkpoint

positional arguments:
  {dnn,linear,combined}
                        The type of estimator to be converted. So far, the
                        checkpoint converter only supports Canned Estimator.
                        So the allowed types include linear, dnn and combined.
  source_checkpoint     Path to source checkpoint file to be read in.
  source_graph          Path to source graph file to be read in.
  target_checkpoint     Path to checkpoint file to be written out.

optional arguments:
  -h, --help            show this help message and exit

TensorShape

Esta clase se simplificó para contener int s, en lugar de tf.compat.v1.Dimension objetos. Por lo tanto, no es necesario llamar a .value() para obtener un int .

Los objetos individuales tf.compat.v1.Dimension todavía son accesibles desde tf.TensorShape.dims .

A continuación, se muestran las diferencias entre TensorFlow 1.xy TensorFlow 2.0.

# Create a shape and choose an index
i = 0
shape = tf.TensorShape([16, None, 256])
shape
TensorShape([16, None, 256])

Si tenía esto en TF 1.x:

value = shape[i].value

Luego haz esto en TF 2.0:

value = shape[i]
value
16

Si tenía esto en TF 1.x:

for dim in shape:
    value = dim.value
    print(value)

Luego haz esto en TF 2.0:

for value in shape:
  print(value)
16
None
256

Si tenía esto en TF 1.x (O utilizó cualquier otro método de dimensión):

dim = shape[i]
dim.assert_is_compatible_with(other_dim)

Luego haz esto en TF 2.0:

other_dim = 16
Dimension = tf.compat.v1.Dimension

if shape.rank is None:
  dim = Dimension(None)
else:
  dim = shape.dims[i]
dim.is_compatible_with(other_dim) # or any other dimension method
True
shape = tf.TensorShape(None)

if shape:
  dim = shape.dims[i]
  dim.is_compatible_with(other_dim) # or any other dimension method

El valor booleano de un tf.TensorShape es True si se conoce el rango, False caso contrario.

print(bool(tf.TensorShape([])))      # Scalar
print(bool(tf.TensorShape([0])))     # 0-length vector
print(bool(tf.TensorShape([1])))     # 1-length vector
print(bool(tf.TensorShape([None])))  # Unknown-length vector
print(bool(tf.TensorShape([1, 10, 100])))       # 3D tensor
print(bool(tf.TensorShape([None, None, None]))) # 3D tensor with no known dimensions
print()
print(bool(tf.TensorShape(None)))  # A tensor with unknown rank.
True
True
True
True
True
True

False

Otros cambios

  • Elimina tf.colocate_with : los algoritmos de ubicación de dispositivos de TensorFlow han mejorado significativamente. Esto ya no debería ser necesario. Si eliminarlo provoca una degradación del rendimiento , presente un error .

  • Reemplace el uso de v1.ConfigProto con las funciones equivalentes de tf.config .

Conclusiones

El proceso general es:

  1. Ejecute el script de actualización.
  2. Elimina los símbolos contrib.
  3. Cambie sus modelos a un estilo orientado a objetos (Keras).
  4. Utilice los tf.keras formación y evaluación de tf.keras o tf.estimator donde pueda.
  5. De lo contrario, use bucles personalizados, pero asegúrese de evitar sesiones y colecciones.

Se necesita un poco de trabajo para convertir el código al idiomático TensorFlow 2.0, pero cada cambio da como resultado:

  • Menos líneas de código.
  • Mayor claridad y sencillez.
  • Depuración más sencilla.