Esta página foi traduzida pela API Cloud Translation.
Switch to English

Migre seu código do TensorFlow 1 para o TensorFlow 2

Ver no TensorFlow.org Executar no Google Colab Ver fonte no GitHub Baixar caderno

Este documento para usuários de APIs TensorFlow de baixo nível. Se você estiver usando APIs de alto nível ( tf.keras ), pode haver pouca ou nenhuma ação a ser realizada para tornar seu código totalmente compatível com o TensorFlow 2.0:

Ainda é possível executar o código 1.X, sem modificações ( exceto para contrib ), no TensorFlow 2.0:

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

No entanto, isso não permite que você aproveite muitas das melhorias feitas no TensorFlow 2.0. Este guia o ajudará a atualizar seu código, tornando-o mais simples, com mais desempenho e mais fácil de manter.

Script de conversão automática

A primeira etapa, antes de tentar implementar as mudanças descritas neste documento, é tentar executar o script de atualização .

Isso fará uma passagem inicial para atualizar seu código para o TensorFlow 2.0. Mas não pode tornar seu código idiomático para 2.0. Seu código ainda pode usar pontos de extremidade tf.compat.v1 para acessar espaços reservados, sessões, coleções e outras funcionalidades do estilo 1.x.

Mudanças comportamentais de nível superior

Se seu código funciona no TensorFlow 2.0 usando tf.compat.v1.disable_v2_behavior() , ainda há mudanças comportamentais globais que você pode precisar resolver. As principais mudanças são:

  • Execução v1.enable_eager_execution() , v1.enable_eager_execution() : Qualquer código que usar implicitamente um tf.Graph falhará. Certifique-se de envolver este código em um with tf.Graph().as_default() .

  • Variáveis ​​de recursos, v1.enable_resource_variables() : Alguns códigos podem depender de comportamentos não determinísticos habilitados por variáveis ​​de referência TF. As variáveis ​​de recursos são bloqueadas durante a gravação e, portanto, fornecem garantias de consistência mais intuitivas.

    • Isso pode alterar o comportamento em casos extremos.
    • Isso pode criar cópias extras e pode ter maior uso de memória.
    • Isso pode ser desabilitado passando use_resource=False para o construtor tf.Variable .
  • Formas do tensor, v1.enable_v2_tensorshape() : TF 2.0 simplifica o comportamento das formas do tensor. Em vez de t.shape[0].value você pode dizer t.shape[0] . Essas alterações devem ser pequenas e faz sentido corrigi-las imediatamente. Consulte TensorShape para exemplos.

  • Fluxo de controle, v1.enable_control_flow_v2() : A implementação do fluxo de controle TF 2.0 foi simplificada e, portanto, produz diferentes representações gráficas. Por favor, registre bugs para quaisquer problemas.

Torne o código 2.0 nativo

Este guia apresentará vários exemplos de conversão de código do TensorFlow 1.x para TensorFlow 2.0. Essas alterações permitirão que seu código aproveite as otimizações de desempenho e chamadas de API simplificadas.

Em cada caso, o padrão é:

1. Substitua chamadas v1.Session.run

Cada chamada v1.Session.run deve ser substituída por uma função Python.

  • O feed_dict e v1.placeholder s tornam-se argumentos de função.
  • As fetches tornam-se o valor de retorno da função.
  • Durante a conversão, a execução rápida permite a depuração fácil com ferramentas Python padrão como pdb .

Depois disso, adicione um decorador tf.function para que ele seja executado de forma eficiente no gráfico. Veja o Guia do Autógrafo para mais informações sobre como isso funciona.

Observe que:

  • Ao contrário de v1.Session.run um tf.function tem uma assinatura de retorno fixa e sempre retorna todas as saídas. Se isso causar problemas de desempenho, crie duas funções separadas.

  • Não há necessidade de um tf.control_dependencies ou operações semelhantes: Um tf.function se comporta como se fosse executado na ordem em que foi escrito. tf.Variable atribuições de tf.Variable e tf.assert s, por exemplo, são executadas automaticamente.

A seção de conversão de modelos contém um exemplo prático desse processo de conversão.

2. Use objetos Python para rastrear variáveis ​​e perdas

Todo rastreamento de variável baseado em nome é fortemente desencorajado no TF 2.0. Use objetos Python para rastrear variáveis.

Use tf.Variable vez de v1.get_variable .

Cada v1.variable_scope deve ser convertido em um objeto Python. Normalmente, será um dos seguintes:

Se você precisa de listas agregados de variáveis (como tf.Graph.get_collection(tf.GraphKeys.VARIABLES) ), use os .variables e .trainable_variables atributos da Layer e Model objetos.

Essas classes Layer e Model implementam várias outras propriedades que eliminam a necessidade de coleções globais. Sua propriedade .losses pode substituir o uso da coleção tf.GraphKeys.LOSSES .

Consulte os guias do keras para obter detalhes.

3. Atualize seus loops de treinamento

Use a API de nível mais alto que funciona para seu caso de uso. Prefira tf.keras.Model.fit vez de criar seus próprios loops de treinamento.

Essas funções de alto nível gerenciam muitos dos detalhes de baixo nível que podem ser facilmente perdidos se você escrever seu próprio loop de treinamento. Por exemplo, eles coletam automaticamente as perdas de regularização e definem o argumento training=True ao chamar o modelo.

4. Atualize seus pipelines de entrada de dados

Use conjuntos de dados tf.data para entrada de dados. Esses objetos são eficientes, expressivos e se integram bem ao tensorflow.

Eles podem ser passados ​​diretamente para o método tf.keras.Model.fit .

model.fit(dataset, epochs=5)

Eles podem ser iterados diretamente no Python padrão:

for example_batch, label_batch in dataset:
    break

5. Migrar símbolos compat.v1

O módulo tf.compat.v1 contém a API TensorFlow 1.x completa, com sua semântica original.

O script de atualização do TF2 converterá os símbolos em seus equivalentes 2.0 se tal conversão for segura, ou seja, se puder determinar que o comportamento da versão 2.0 é exatamente equivalente (por exemplo, ele renomeará v1.arg_max para tf.argmax , uma vez que essas são a mesma função).

Depois que o script de atualização é feito com um trecho de código, é provável que haja muitas menções de compat.v1 . Vale a pena revisar o código e convertê-los manualmente para o equivalente 2.0 (deve ser mencionado no log, se houver).

Modelos de conversão

Variáveis ​​de baixo nível e execução do operador

Exemplos de uso de API de baixo nível incluem:

Antes de converter

Veja como esses padrões podem parecer no código usando o 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

Depois de converter

No código convertido:

  • As variáveis ​​são objetos locais do Python.
  • A função forward ainda define o cálculo.
  • A chamada Session.run é substituída por uma chamada para forward
  • O decorador tf.function opcional pode ser adicionado para desempenho.
  • As regularizações são calculadas manualmente, sem fazer referência a nenhuma coleção global.
  • Sem sessões ou espaços reservados.
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 baseados em tf.layers

O módulo v1.layers é usado para conter funções de camada que dependiam de v1.variable_scope para definir e reutilizar variáveis.

Antes de converter

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)

Depois de converter

A maioria dos argumentos permaneceu igual. Mas observe as diferenças:

  • O argumento de training é passado para cada camada pelo modelo quando ele é executado.
  • O primeiro argumento para a função do model original (a entrada x ) se foi. Isso ocorre porque as camadas do objeto separam a construção do modelo da chamada do modelo.

Observe também que:

  • Se você estava usando regularizadores de inicializadores de tf.contrib , eles têm mais mudanças de argumento do que outros.
  • O código não grava mais em coleções, portanto, funções como v1.losses.get_regularization_loss não retornarão mais esses valores, potencialmente interrompendo seus loops de treinamento.
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>]

Variáveis ​​mistas e v1.layers

O código existente geralmente combina variáveis ​​e operações do TF 1.x de nível inferior com v1.layers nível v1.layers .

Antes de converter

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)

Depois de converter

Para converter esse código, siga o padrão de mapeamento de camadas em camadas, como no exemplo anterior.

O padrão geral é:

  • Colete parâmetros de camada em __init__ .
  • Construa as variáveis ​​na build .
  • Execute os cálculos em call e retorne o resultado.

O v1.variable_scope é essencialmente uma camada própria. Portanto, reescreva-o como tf.keras.layers.Layer . Consulte o guia para obter detalhes.

# 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)

Algumas coisas a serem observadas:

  • Modelos e camadas de Keras com subclasse precisam ser executados em ambos os gráficos v1 (sem dependências de controle automático) e no modo ansioso

    • Envolva a call() em um tf.function() para obter autógrafo e dependências de controle automático
  • Não se esqueça de aceitar um argumento de training para call .

    • Às vezes é um tf.Tensor
    • Às vezes, é um booleano Python.
  • Crie variáveis ​​de modelo no construtor ou Model.build usando self.add_weight() .

    • Em Model.build você tem acesso ao formato de entrada, então pode criar pesos com formato correspondente.
    • Usar tf.keras.layers.Layer.add_weight permite que Keras rastreie variáveis ​​e perdas de regularização.
  • Não mantenha tf.Tensors em seus objetos.

    • Eles podem ser criados em uma função tf.function ou no contexto ansioso, e esses tensores se comportam de maneira diferente.
    • Use tf.Variable s para o estado, elas sempre podem ser usadas em ambos os contextos
    • tf.Tensors são apenas para valores intermediários.

Uma observação sobre Slim e contrib.layers

Uma grande quantidade de códigos mais antigos do TensorFlow 1.x usa a biblioteca Slim , que foi empacotada com o TensorFlow 1.x como tf.contrib.layers . Como um módulo contrib , ele não está mais disponível no TensorFlow 2.0, mesmo em tf.compat.v1 . Converter o código usando Slim para TF 2.0 envolve mais do que converter repositórios que usam v1.layers . Na verdade, pode fazer sentido converter primeiro seu código Slim para v1.layers , em seguida, converter para Keras.

  • Remova arg_scopes , todos os args precisam ser explícitos
  • Se você usá-los, divida normalizer_fn e activation_fn em suas próprias camadas
  • Camadas conv separáveis ​​são mapeadas para uma ou mais camadas Keras diferentes (camadas Keras profundas, pontuais e separáveis)
  • Slim e v1.layers têm nomes de argumentos e valores padrão diferentes
  • Alguns args têm escalas diferentes
  • Se você usa modelos pré-treinados Slim, experimente os modelos pré-treinados de Keras em tf.keras.applications ou TF2 SavedModels do TF Hub exportados do código Slim original.

Algumas camadas tf.contrib podem não ter sido movidas para o TensorFlow central, mas sim para o pacote de complementos do TF .

Treinamento

Existem muitas maneiras de alimentar dados para um modelo tf.keras . Eles aceitarão geradores Python e matrizes Numpy como entrada.

A maneira recomendada de alimentar um modelo com dados é usar o pacote tf.data , que contém uma coleção de classes de alto desempenho para manipulação de dados.

Se você ainda estiver usando tf.queue , agora eles são suportados apenas como estruturas de dados, não como pipelines de entrada.

Usando conjuntos de dados

O pacote TensorFlow Datasets ( tfds ) contém utilitários para carregar conjuntos de dados predefinidos como objetos tf.data.Dataset .

Para este exemplo, carregue o 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.

Em seguida, prepare os dados para o treinamento:

  • Redimensione cada imagem.
  • Misture a ordem dos exemplos.
  • Colete lotes de imagens e 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 manter o exemplo curto, apare o conjunto de dados para retornar apenas 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))

Use loops de treinamento Keras

Se você não precisa de controle de baixo nível de seu processo de treinamento, é recomendado usar os métodos integrados de fit , evaluate e predict Keras. Esses métodos fornecem uma interface uniforme para treinar o modelo, independentemente da implementação (sequencial, funcional ou subclassificada).

As vantagens desses métodos incluem:

  • Eles aceitam matrizes Numpy, geradores Python e tf.data.Datasets
  • Eles aplicam a regularização e as perdas de ativação automaticamente.
  • Eles suportam tf.distribute para tf.distribute em vários dispositivos .
  • Eles suportam cobráveis ​​arbitrários como perdas e métricas.
  • Eles oferecem suporte a retornos de chamada como tf.keras.callbacks.TensorBoard e retornos de chamada personalizados.
  • Eles têm desempenho, usando gráficos do TensorFlow automaticamente.

Aqui está um exemplo de treinamento de um modelo usando um Dataset . (Para obter detalhes sobre como isso funciona, consulte os tutoriais .)

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

Escreva seu próprio loop

Se a etapa de treinamento do modelo Keras funcionar para você, mas você precisar de mais controle fora dessa etapa, considere usar o método tf.keras.Model.train_on_batch , em seu próprio loop de iteração de dados.

Lembre-se: muitas coisas podem ser implementadas como tf.keras.callbacks.Callback .

Esse método tem muitas das vantagens dos métodos mencionados na seção anterior, mas fornece ao usuário o controle do loop externo.

Você também pode usar tf.keras.Model.test_on_batch ou tf.keras.Model.evaluate para verificar o desempenho durante o treinamento.

Para continuar treinando o modelo acima:

# 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

Personalize a etapa de treinamento

Se você precisa de mais flexibilidade e controle, pode fazê-lo implementando seu próprio ciclo de treinamento. Existem três etapas:

  1. Itere sobre um gerador Python ou tf.data.Dataset para obter lotes de exemplos.
  2. Use tf.GradientTape para coletar gradientes.
  3. Use um dos tf.keras.optimizers para aplicar atualizações de peso às variáveis ​​do modelo.

Lembrar:

  • Sempre inclua um argumento de training no método de call de camadas e modelos de subclasse.
  • Certifique-se de chamar o modelo com o argumento de training definido corretamente.
  • Dependendo do uso, as variáveis ​​do modelo podem não existir até que o modelo seja executado em um lote de dados.
  • Você precisa lidar manualmente com coisas como perdas de regularização para o modelo.

Observe as simplificações em relação a v1:

  • Não há necessidade de executar inicializadores de variáveis. As variáveis ​​são inicializadas na criação.
  • Não há necessidade de adicionar dependências de controle manual. Mesmo em tf.function operações funcionam como no modo tf.function .
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 e perdas de novo estilo

No TensorFlow 2.0, métricas e perdas são objetos. Eles funcionam avidamente e em tf.function s.

Um objeto de perda pode ser chamado e espera o (y_true, y_pred) como argumentos:

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

Um objeto métrico tem os seguintes métodos:

O próprio objeto pode ser chamado. Chamar atualiza o estado com novas observações, como com update_state , e retorna o novo resultado da métrica.

Você não precisa inicializar manualmente as variáveis ​​de uma métrica e, como o TensorFlow 2.0 tem dependências de controle automático, você também não precisa se preocupar com elas.

O código abaixo usa uma métrica para rastrear a perda média observada em um loop de treinamento 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))

Epoch:  0
  loss:     0.207
  accuracy: 0.991
Epoch:  1
  loss:     0.167
  accuracy: 0.994
Epoch:  2
  loss:     0.147
  accuracy: 0.997
Epoch:  3
  loss:     0.123
  accuracy: 0.997
Epoch:  4
  loss:     0.109
  accuracy: 0.997

Nomes de métricas Keras

No TensorFlow 2.0, os modelos keras são mais consistentes sobre como lidar com nomes de métricas.

Agora, quando você passa uma string na lista de métricas, essa string exata é usada como o name da métrica. Esses nomes são visíveis no objeto de histórico retornado por model.fit e nos logs passados ​​para keras.callbacks . é definido como a string que você passou na 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'])

Isso difere das versões anteriores, onde passar metrics=["accuracy"] resultaria em dict_keys(['loss', 'acc'])

Otimizadores Keras

Os otimizadores em v1.train , como v1.train.AdamOptimizer e v1.train.GradientDescentOptimizer , têm equivalentes em tf.keras.optimizers .

Converter v1.train em keras.optimizers

Aqui estão alguns pontos a serem considerados ao converter seus otimizadores:

Novos padrões para alguns tf.keras.optimizers

Não há mudanças para optimizers.SGD , optimizers.Adam ou optimizers.RMSprop .

As seguintes taxas de aprendizagem padrão foram alteradas:

TensorBoard

O TensorFlow 2 inclui mudanças significativas na API tf.summary usada para escrever dados resumidos para visualização no TensorBoard. Para uma introdução geral ao novo tf.summary , existem vários tutoriais disponíveis que usam a API TF 2. Isso inclui um Guia de migração do TensorBoard TF 2

Salvando e carregando

Compatibilidade do ponto de verificação

O TensorFlow 2.0 usa pontos de verificação baseados em objetos .

Os pontos de verificação baseados em nomes no estilo antigo ainda podem ser carregados, se você for cuidadoso. O processo de conversão do código pode resultar em mudanças no nome da variável, mas existem soluções alternativas.

A abordagem mais simples é alinhar os nomes do novo modelo com os nomes no ponto de verificação:

  • Todas as variáveis ​​ainda têm um argumento de name que você pode definir.
  • Os modelos Keras também usam um argumento de name como o prefixo de suas variáveis.
  • A função v1.name_scope pode ser usada para definir prefixos de nomes de variáveis. Isso é muito diferente de tf.variable_scope . Afeta apenas nomes e não rastreia variáveis ​​e nem reutiliza.

Se isso não funcionar para o seu caso de uso, experimente a função v1.train.init_from_checkpoint . Recebe um argumento assignment_map , que especifica o mapeamento de nomes antigos para novos nomes.

O repositório TensorFlow Estimator inclui uma ferramenta de conversão para atualizar os pontos de verificação para estimadores predefinidos do TensorFlow 1.X para 2.0. Pode servir como um exemplo de como construir uma ferramenta para um caso de uso semelhante.

Compatibilidade de modelos salvos

Não há problemas de compatibilidade significativos para modelos salvos.

  • Os modelos salvos do TensorFlow 1.x funcionam no TensorFlow 2.x.
  • Os modelos salvos do TensorFlow 2.x funcionam no TensorFlow 1.x, se todas as operações forem compatíveis.

A Graph.pb ou Graph.pbtxt

Não há uma maneira direta de atualizar um arquivo Graph.pb bruto para o TensorFlow 2.0. Sua melhor aposta é atualizar o código que gerou o arquivo.

Mas, se você tiver um "gráfico congelado" (um tf.Graph onde as variáveis ​​foram transformadas em constantes), é possível convertê-lo em uma função 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 exemplo, aqui está um gráfico congelado para o início 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

Carregue o tf.GraphDef :

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

Envolva-o em uma função concrete_function :

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

Passe um 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

Treinamento com estimadores

Estimadores são compatíveis com TensorFlow 2.0.

Ao usar estimadores, você pode usar input_fn() , tf.estimator.TrainSpec e tf.estimator.EvalSpec do TensorFlow 1.x.

Aqui está um exemplo usando input_fn com especificações de treinamento e avaliação.

Criação das especificações input_fn e 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 uma definição de modelo Keras

Existem algumas diferenças em como construir seus estimadores no TensorFlow 2.0.

Recomendamos que você defina seu modelo usando Keras e, em seguida, use o utilitário tf.keras.estimator.model_to_estimator para transformar seu modelo em um estimador. O código a seguir mostra como usar esse utilitário ao criar e treinar um 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 um model_fn personalizado

Se você tiver um estimador customizado model_fn que precisa manter, pode converter seu model_fn para usar um modelo Keras.

No entanto, por motivos de compatibilidade, um model_fn personalizado ainda será executado no modo gráfico no estilo 1.x. Isso significa que não há execução rápida e nem dependências de controle automático.

Model_fn personalizado com alterações mínimas

Para fazer seu model_fn customizado funcionar no TF 2.0, se você preferir mudanças mínimas no código existente, símbolos tf.compat.v1 , como optimizers e metrics podem ser usados.

Usar um modelo Keras em um model_fn personalizado é semelhante a usá-lo em um loop de treinamento personalizado:

  • Defina a fase de training apropriadamente, com base no argumento de mode .
  • Passe explicitamente as trainable_variables do modelo para o otimizador.

Mas existem diferenças importantes, em relação a um loop personalizado :

  • Em vez de usar Model.losses , extraia as perdas usando Model.get_losses_for .
  • Extraia as atualizações do modelo usando Model.get_updates_for .

O código a seguir cria um estimador a partir de um model_fn personalizado, ilustrando todas essas questões.

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 com símbolos TF 2.0

Se você deseja se livrar de todos os símbolos TF 1.x e atualizar seu model_fn personalizado para TF 2.0 nativo, você precisa atualizar o otimizador e as métricas para tf.keras.optimizers e tf.keras.metrics .

No model_fn personalizado, além das alterações acima, mais atualizações precisam ser feitas:

Para o exemplo acima de my_model_fn , o código migrado com símbolos 2.0 é mostrado 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 pré-fabricados

Estimadores tf.estimator.DNN* na família de tf.estimator.DNN* , tf.estimator.Linear* e tf.estimator.DNNLinearCombined* ainda são suportados na API TensorFlow 2.0, no entanto, alguns argumentos mudaram:

  1. input_layer_partitioner : Removido em 2.0.
  2. loss_reduction : atualizado para tf.keras.losses.Reduction vez de tf.compat.v1.losses.Reduction . Seu valor padrão também é alterado para tf.keras.losses.Reduction.SUM_OVER_BATCH_SIZE de tf.compat.v1.losses.Reduction.SUM .
  3. optimizer , dnn_optimizer e linear_optimizer : este argumento foi atualizado para tf.keras.optimizers vez de tf.compat.v1.train.Optimizer .

Para migrar as alterações acima:

  1. Nenhuma migração é necessária para input_layer_partitioner já que a Distribution Strategy irá lidar com isso automaticamente no TF 2.0.
  2. Para loss_reduction , verifique tf.keras.losses.Reduction para as opções suportadas.
  3. Para argumentos do optimizer , se você não passar um dnn_optimizer optimizer , dnn_optimizer ou linear_optimizer , ou se você especificar o arg do optimizer como uma string em seu código, você não precisa alterar nada. tf.keras.optimizers é usado por padrão. Caso contrário, você precisa atualizá-lo de tf.compat.v1.train.Optimizer para seu tf.keras.optimizers correspondente

Conversor de ponto de verificação

A migração para keras.optimizers interromperá os pontos de verificação salvos usando TF 1.x, pois tf.keras.optimizers gera um conjunto diferente de variáveis ​​para serem salvas nos pontos de verificação. Para tornar o ponto de verificação antigo reutilizável após sua migração para o TF 2.0, experimente a ferramenta de conversão de ponto de verificação .

 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

A ferramenta tem ajuda integrada:

 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

Essa classe foi simplificada para conter int s, em vez de objetos tf.compat.v1.Dimension . Portanto, não há necessidade de chamar .value() para obter um int .

Os objetos tf.compat.v1.Dimension individuais ainda podem ser acessados ​​em tf.TensorShape.dims .

A seguir, demonstramos as diferenças entre o TensorFlow 1.x e o TensorFlow 2.0.

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

Se você tivesse isso no TF 1.x:

value = shape[i].value

Então faça isso no TF 2.0:

value = shape[i]
value
16

Se você tivesse isso no TF 1.x:

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

Então faça isso no TF 2.0:

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

Se você tinha isso no TF 1.x (ou usou qualquer outro método de dimensão):

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

Então faça isso no 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

O valor booleano de um tf.TensorShape é True se a classificação for conhecida, False caso contrário.

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

Outras Mudanças

  • Remova tf.colocate_with : os algoritmos de posicionamento de dispositivos do TensorFlow melhoraram significativamente. Isso não deve mais ser necessário. Se removê-lo causar uma degradação do desempenho, informe um bug .

  • Substitua o uso de v1.ConfigProto pelas funções equivalentes de tf.config .

Conclusões

O processo geral é:

  1. Execute o script de atualização.
  2. Remova os símbolos contrib.
  3. Mude seus modelos para um estilo orientado a objetos (Keras).
  4. Use tf.keras ou tf.estimator loops de treinamento e avaliação onde puder.
  5. Caso contrário, use loops personalizados, mas certifique-se de evitar sessões e coleções.

É um pouco trabalhoso converter o código para o TensorFlow 2.0 idiomático, mas cada mudança resulta em:

  • Menos linhas de código.
  • Maior clareza e simplicidade.
  • Depuração mais fácil.