Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/pt-br/guide/effective_tf2.ipynb
25115 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

TensorFlow 2 efetivo

Visão geral

Este guia apresenta uma lista de práticas recomendadas ao escrever código usando o TensorFlow 2 (TF2) e é destinado a usuários que tenham mudado recentemente do TensorFlow 1 (TF1) para o TF2. Confira mais informações sobre como migrar código do TF1 para o TF2 na seção de migração do guia.

Configuração

Importe o TensorFlow e outras dependências para os exemplos deste guia.

import tensorflow as tf import tensorflow_datasets as tfds

Recomendações para o TensorFlow 2 idiomático

Refatore seu código em módulos menores

Uma boa prática é refatorar seu código em funções menores que são chamadas conforme necessário. Para ter o melhor desempenho, tente decorar os maiores blocos de computação que você puder em uma tf.function (as funções do Python aninhadas chamadas por uma tf.function não requerem suas próprias decorações separadas, a menos que você deseje usar configurações diferentes de jit_compile para a tf.function). Dependendo do seu caso de uso, podem ser diversos passos de treinamento ou até mesmo seu loop de treinamento inteiro. Para inferência, talvez seja um único passo para frente do modelo.

Ajuste a taxa de aprendizado padrão para alguns tf.keras.optimizers

Alguns otimizadores do Keras têm taxas de aprendizados diferentes no TF2. Se você notar uma alteração no comportamento de convergências dos seus modelos, verifique as taxas de aprendizado padrão.

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

As seguintes taxas de aprendizado padrão mudaram:

  • optimizers.Adagrad: de 0.01 para 0.001

  • optimizers.Adadelta: de 1.0 para 0.001

  • optimizers.Adamax: de 0.002 para 0.001

  • optimizers.Nadam: de 0.002 para 0.001

Use tf.Modules e camadas do Keras para gerenciar variáveis

tf.Modules e tf.keras.layers.Layers do Keras oferecem as convenientes propriedades variables e trainable_variables, que reúnem recursivamente todas as variáveis dependentes. Assim, fica mais fácil gerenciar variáveis localmente, no lugar onde estão sendo usadas.

Os modelos/camadas do Keras herdam de tf.train.Checkpointable e estão integrados a @tf.function, o que permite fazer o checkpoint ou exportar SavedModels diretamente a partir de objetos do Keras. Você não precisa necessariamente usar a API Model.fit do Keras para aproveitar essas integrações.

Confira a seção sobre aprendizado por transferência e ajustes finos no guia do Keras para aprender a coletar um subconjunto de variáveis relevantes usando o Keras.

Combine tf.data.Datasets e tf.function

O pacote TensorFlow Datasets (tfds) contém utilitários para carregar datasets pré-definidos como objetos tf.data.Dataset. Neste exemplo, você pode carregar o dataset MNIST usando tfds:

datasets, info = tfds.load(name='mnist', with_info=True, as_supervised=True) mnist_train, mnist_test = datasets['train'], datasets['test']

Em seguida, prepare os dados para o treinamento:

  • Redimensione cada imagem.

  • Misture a ordem dos exemplos.

  • Colete lotes de imagens e rótulos.

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, corte o dataset para retornar somente 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 a iteração comum do Python ao iterar dados de treinamento que cabem na memória, Caso contrário, tf.data.Dataset é a melhor maneira de transmitir dados de treinamento a partir do disco. Os datasets são iteráveis (e não iteradores) e funcionam como qualquer outro iterável do Python na execução adiantada (eager). Você pode utilizar totalmente os recursos assíncronos de pré-busca/streaming dos datasets ao encapsular seu código em tf.function, que substitui uma iteração do Python pelas operações equivalentes de grafo usando o AutoGraph.

@tf.function def train(model, dataset, optimizer): for x, y in dataset: with tf.GradientTape() as tape: # training=True is only needed if there are layers with different # behavior during training versus inference (e.g. Dropout). prediction = model(x, training=True) loss = loss_fn(prediction, y) gradients = tape.gradient(loss, model.trainable_variables) optimizer.apply_gradients(zip(gradients, model.trainable_variables))

Se você usar a API Model.fit do Keras, não precisará se preocupar com a iteração de datasets.

model.compile(optimizer=optimizer, loss=loss_fn) model.fit(dataset)

Use os loops de treinamento do Keras

Se você não precisar de um controle de baixo nível do processo de treinamento, é recomendável usar os métodos integrados do Keras fit, evaluate e predict, que oferecem uma interface uniforme para treinar o modelo, independentemente da implementação (sequencial, funcional ou de subclasse).

Veja algumas vantagens desses métodos:

  • Aceitam matrizes Numpy, geradores Python e tf.data.Datasets.

  • Aplicam regularização e perdas de ativação atuomaticamente.

  • Têm suporte a tf.distribute, em que o código de treinamento permanece o mesmo independentemente da configuração de hardware.

  • Têm suporte a callables arbitrários, como perdas e métricas.

  • Têm suporte a callbacks, como tf.keras.callbacks.TensorBoard, e a callbacks personalizados.

  • Têm bom desempenho usando automaticamente os grafos do TensorFlow.

Veja um exemplo de treinamento de um modelo usando um Dataset. Confira mais detalhes de como isso funciona nos 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))

Personalize o treinamento e escreva seu próprio loop

Se os modelos do Keras funcionarem para você, mas você precisar de mais flexibilidade e controle do passo de treinamento ou dos loops de treinamento externos, você pode implementar seus próprios passos de treinamento ou até mesmo loops de treinamento inteiros. Saiba mais no guia do Keras sobre como personalizar fit.

Você também pode implementar diversas coisas como um tf.keras.callbacks.Callback.

Este método tem muitas das vantagens mencionadas anteriormente, mas te dá controle do passo de treinamento e até mesmo do loop externo.

Existem três passos em um loop de treinamento padrão:

  1. Fazer a interação de um gerador do Python ou de tf.data.Dataset para obter lotes de exemplos.

  2. Usar tf.GradientTape para coletar gradientes.

  3. Usar um dos otimizadores tf.keras.optimizers para aplicar atualizações de peso às variáveis do modelo.

Lembre-se:

  • Sempre inclua um argumento training no método call de modelos e camadas que são uma subclasse.

  • Você deve chamar o modelo com o argumento training definido corretamente.

  • Dependendo do uso, as variáveis do modelo podem não existir até que ele seja executado em um lote de dados.

  • Você precisa tratar alguns aspectos manualmente, como perdas de regularização do modelo.

Não há necessidade de executar inicializadores de variáveis ou de adicionar dependências de controle manual. tf.function trata as dependências de controle automático e a inicialização de variáveis durante a criação para você.

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)

Use tf.function com fluxo de controle do Python

tf.function fornece uma maneira de converter fluxos de controle dependentes de dados em equivalentes no modo grafo, como tf.cond e tf.while_loop.

Um caso comum de uso de fluxos de controle dependentes de dados são os modelos sequenciais. tf.keras.layers.RNN encapsula uma célula de RNN, permitindo que você desdobre a recorrência de maneira estática ou dinâmica. Por exemplo, você poderia implementar novamente o desdobramento dinâmico da seguinte maneira:

class DynamicRNN(tf.keras.Model): def __init__(self, rnn_cell): super(DynamicRNN, self).__init__(self) self.cell = rnn_cell @tf.function(input_signature=[tf.TensorSpec(dtype=tf.float32, shape=[None, None, 3])]) def call(self, input_data): # [batch, time, features] -> [time, batch, features] input_data = tf.transpose(input_data, [1, 0, 2]) timesteps = tf.shape(input_data)[0] batch_size = tf.shape(input_data)[1] outputs = tf.TensorArray(tf.float32, timesteps) state = self.cell.get_initial_state(batch_size = batch_size, dtype=tf.float32) for i in tf.range(timesteps): output, state = self.cell(input_data[i], state) outputs = outputs.write(i, output) return tf.transpose(outputs.stack(), [1, 0, 2]), state
lstm_cell = tf.keras.layers.LSTMCell(units = 13) my_rnn = DynamicRNN(lstm_cell) outputs, state = my_rnn(tf.random.normal(shape=[10,20,3])) print(outputs.shape)

Confira mais informações no guia de tf.function.

Métricas e perdas com estilo novo

As métricas e perdas são objetos que funcionam em modo adiantado (eager) e em tf.functions.

Um objeto de perda é chamável e espera (y_true, y_pred) como argumentos:

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

Use métricas para coletar e exibir dados

Você pode usar tf.metrics para agregar dados e tf.summary para criar um log de resumos e redirecioná-lo para um writer usando um gerenciador de contexto. Os resumos são enviados diretamente para o writer, ou seja, você precisa fornecer o valor step no local da chamada.

summary_writer = tf.summary.create_file_writer('/tmp/summaries') with summary_writer.as_default(): tf.summary.scalar('loss', 0.1, step=42)

Use tf.metrics para agregar os dados antes de criar os logs resumos. As métricas são stateful: elas acumulam valores e retornam um resultado cumulativo quando você chama o método result (como Mean.result). Use Model.reset_states para limpar os valores acumulados.

def train(model, optimizer, dataset, log_freq=10): avg_loss = tf.keras.metrics.Mean(name='loss', dtype=tf.float32) for images, labels in dataset: loss = train_step(model, optimizer, images, labels) avg_loss.update_state(loss) if tf.equal(optimizer.iterations % log_freq, 0): tf.summary.scalar('loss', avg_loss.result(), step=optimizer.iterations) avg_loss.reset_states() def test(model, test_x, test_y, step_num): # training=False is only needed if there are layers with different # behavior during training versus inference (e.g. Dropout). loss = loss_fn(model(test_x, training=False), test_y) tf.summary.scalar('loss', loss, step=step_num) train_summary_writer = tf.summary.create_file_writer('/tmp/summaries/train') test_summary_writer = tf.summary.create_file_writer('/tmp/summaries/test') with train_summary_writer.as_default(): train(model, optimizer, dataset) with test_summary_writer.as_default(): test(model, test_x, test_y, optimizer.iterations)

Visualize os resumos gerados apontando o TensorBoard para o diretório de logs de resumos:

tensorboard --logdir /tmp/summaries

Use a API tf.summary para gravar dados de resumo para visualização no TensorBoard. Confira mais informações no guia de tf.summary.

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

Nomes de métricas do Keras

Os modelos do Keras são consistentes no tratamento de nomes de métricas. Quando você passa uma string na lista de métricas, essa string exata é usada como o name (nome) da métrica. Esses nomes ficam visíveis no objeto de histórico retornado por model.fit e nos logs passados para keras.callbacks, que é 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)
history.history.keys()

Depuração

Use a execução adiantada (eager) para executar o código passo a passo a fim de inspecionar formatos, tipos de dados e valores. Determinadas APIs, como tf.function, tf.keras, etc., foram concebidas para usar a execução de grafo por questões de desempenho e portabilidade. Ao depurar, use tf.config.run_functions_eagerly(True) para utilizar a execução adiantada dentro desse código.

Por exemplo:

@tf.function def f(x): if x > 0: import pdb pdb.set_trace() x = x + 1 return x tf.config.run_functions_eagerly(True) f(tf.constant(1))
>>> f() -> x = x + 1 (Pdb) l 6 @tf.function 7 def f(x): 8 if x > 0: 9 import pdb 10 pdb.set_trace() 11 -> x = x + 1 12 return x 13 14 tf.config.run_functions_eagerly(True) 15 f(tf.constant(1)) [EOF]

Isso também funciona dentro dos modelos do Keras e de outras APIs que têm suporte à execução adiantada (eager):

class CustomModel(tf.keras.models.Model): @tf.function def call(self, input_data): if tf.reduce_mean(input_data) > 0: return input_data else: import pdb pdb.set_trace() return input_data // 2 tf.config.run_functions_eagerly(True) model = CustomModel() model(tf.constant([-2, -4]))
>>> call() -> return input_data // 2 (Pdb) l 10 if tf.reduce_mean(input_data) > 0: 11 return input_data 12 else: 13 import pdb 14 pdb.set_trace() 15 -> return input_data // 2 16 17 18 tf.config.run_functions_eagerly(True) 19 model = CustomModel() 20 model(tf.constant([-2, -4]))

Observações:

  • Os métodos de tf.keras.Model, como fit, evaluate e predict, são executados como grafos com tf.function por baixo dos panos.

  • Ao usar tf.keras.Model.compile, defina run_eagerly = True para desativar a lógica de Model de encapsulamento em uma tf.function.

  • Use tf.data.experimental.enable_debug_mode para ativar o modo de depuração para tf.data. Confira mais detalhes na documentação da API.

Não mantenha tf.Tensors em seus objetos

Esses objetos tensores podem ser criados em uma tf.function ou no contexto eager e se comportam de maneira diferente. Sempre use tf.Tensors somente para valores intermediários.

Para monitorar o estado, use tf.Variables, pois elas sempre podem ser usadas em ambos os contextos. Confira mais informações no guia de tf.Variable.

Recursos e leitura adicional

  • Saiba mais sobre como usar o TF2 nos guias e tutoriais.

  • Se você estava usando o TF1.x anteriormente, é altamente recomendável migrar seu código para o TF2. Saiba mais nos guias de migração.