Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/pt-br/guide/estimator.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.

Estimadores

Aviso: os Estimadores são recomendados para novos códigos. Os Estimadores executam código v1.Session, que é mais difícil de escrever corretamente e pode se comportar se forma inesperada, ainda mais quando usado em conjunto com código do TF 2. Os Estimators são abarcados pelas garantias de compatibilidade, mas não recebem mais correções, exceto para vulnerabilidades de segurança. Confira mais detalhes no guia de migração.

Este documento apresenta o tf.estimator, uma API de alto nível do TensorFlow. Os Estimadores encapsulam as seguintes ações:

  • Treinamento

  • Avaliação

  • Previsão

  • Exportação para serviço

O TensorFlow implementa diversos Estimadores pré-criados. Ainda há suporte a Estimators personalizados, mas principalmente por questões de compatibilidade legada. Os Estimadores personalizados não devem ser usados para novos códigos. Todos os Estimadores, sejam pré-criados ou personalizados, são classes baseadas na classe tf.estimator.Estimator.

Veja um exemplo rápido nos tutoriais sobre Estimadores. Confira uma visão geral do design da API neste artigo técnico.

Configuração

!pip install -U tensorflow_datasets
import tempfile import os import tensorflow as tf import tensorflow_datasets as tfds

Vantagens

Similar a tf.keras.Model, um estimator é uma abstração de modelo. tf.estimator conta com recursos ainda em desenvolvimento para tf.keras, que são:

  • Treinamento baseado em servidor de parâmetros

  • Integração total com o TFX

Funcionalidades dos Estimadores

Os Estimadores proporcionam os seguintes benefícios:

  • É possível executar modelos baseados em Estimadores em um host local ou em um ambiente distribuído com vários servidores sem alterar seu modelo. Além disso, é possível executar modelos baseados em Estimadores em CPUs, GPUs ou TPUs sem alterar o código do seu modelo.

  • Os Estimadores oferecem um loop de treinamento distribuído seguro que controla como e quando:

    • Carregar dados

    • Tratar exceções

    • Criar arquivos de checkpoint e recuperar-se de falhas

    • Salvar resumos para o TensorBoard

Ao escrever uma aplicação com Estimadores, você precisa separar o pipeline de entrada de dados e o modelo. Essa separação simplifica os experimentos com datasets diferentes.

Uso de Estimadores pré-criados

Com os Estimadores pré-criados, você pode trabalhar em um nível conceitual muito maior do que ao trabalhar com as APIs base do TensorFlow. Você não precisa mais se preocupar com a criação do grafo computacional ou de sessões, pois os Estimadores tratam esses detalhes internos para você. Além disso, com os Estimadores pré-criados, você pode usar diferentes arquiteturas de modelo fazendo apenas mudanças mínimas no código. Por exemplo, tf.estimator.DNNClassifier é uma classe de Estimador pré-criada que treina modelos de classificação baseados em redes neurais densas com alimentação para frente.

Tipicamente, um programa do TensorFlow que use um Estimador pré-criado consiste das quatro etapas abaixo:

1. Escreva funções de entrada

Por exemplo, você poderia criar uma função para importar o conjunto de treinamento e outra para importar o conjunto de teste. Os Estimadores esperam que suas entradas sejam formatadas como um par de objetos:

  • Um dicionário, em que as chaves são os nomes das características, e os valores são os tensores (SparseTensors) que contêm os dados de características correspondentes

  • Um Tensor contendo um ou mais rótulos

input_fn deve retornar um tf.data.Dataset que gere pares nesse formato.

Por exemplo, o código abaixo cria um tf.data.Dataset a partir do arquivo train.csv do dataset Titanic:

def train_input_fn(): titanic_file = tf.keras.utils.get_file("train.csv", "https://storage.googleapis.com/tf-datasets/titanic/train.csv") titanic = tf.data.experimental.make_csv_dataset( titanic_file, batch_size=32, label_name="survived") titanic_batches = ( titanic.cache().repeat().shuffle(500) .prefetch(tf.data.AUTOTUNE)) return titanic_batches

input_fn é executado em um tf.Graph e também pode retornar tiretamente um par (features_dics, labels) contendo tensores do grafo, mas isso está propenso a erros, exceto em casos simples, como retornar constantes.

2. Defina as colunas de características

Cada tf.feature_column identifica um nome de característica, seu tipo e qualquer pré-processamento da entrada.

Por exemplo, o trecho de código abaixo cria três colunas de características:

  • A primeira usa a característica age (idade) diretamente como uma entrada de ponto flutuante.

  • A segunda usa a característica class (classe) como uma entrada de categoria.

  • A terceira usa a característica embark_town (cidade de embarque) como uma entrada de categoria, mas utiliza hashing trick para evitar a necessidade de enumerar as opções e para definir o número de opções.

Confira mais informações no tutorial sobre colunas de características.

age = tf.feature_column.numeric_column('age') cls = tf.feature_column.categorical_column_with_vocabulary_list('class', ['First', 'Second', 'Third']) embark = tf.feature_column.categorical_column_with_hash_bucket('embark_town', 32)

3. Instancie o Estimador pré-criado relevante

Por exemplo, veja a instanciação de uma amostra de um Estimador pré-criado chamado LinearClassifier:

model_dir = tempfile.mkdtemp() model = tf.estimator.LinearClassifier( model_dir=model_dir, feature_columns=[embark, cls, age], n_classes=2 )

Confira mais informações no tutorial sobre classificadores lineares.

4. Chame um método de treinamento, avaliação ou inferência

Todos os Estimadores contam com os métodos train, evaluate e predict.

model = model.train(input_fn=train_input_fn, steps=100)
result = model.evaluate(train_input_fn, steps=10) for key, value in result.items(): print(key, ":", value)
for pred in model.predict(train_input_fn): for key, value in pred.items(): print(key, ":", value) break

Benefícios dos Estimadores pré-criados

Os Estimadores pré-criados seguem as práticas recomendadas, proporcionando os seguintes benefícios:

  • Práticas recomendadas para determinar onde as diferentes partes do grafo computacional devem ser executadas, implementando estratégias em uma única máquina ou em um cluster.

  • Práticas recomendadas para gravação de eventos (resumos) e resumos úteis universalmente.

Se você não utilizar Estimadores pré-criados, precisa implementar os recursos acima por conta própria.

Estimadores personalizados

O núcleo de todo Estimador, seja pré-criado ou personalizado, é sua função do modelo, model_fn, um método que cria grafos para treinamento, avaliação e previsão. Quando você utiliza um Estimador pré-criado, outra pessoa já implementou a função do modelo. Ao usar um Estimador personalizado, você precisa escrever a função do modelo por conta própria.

Observação: uma model_fn personalizada ainda será executada no modo grafo do 1.x. Portanto, não há execução adiantada (eager) e dependências de controle automático. Você deve planejar a migração do tf.estimator com model_fn personalizada. As APIs alternativas são tf.keras e tf.distribute. Se você ainda precisar de um Estimator para alguma parte do treinamento, pode usar o conversor tf.keras.estimator.model_to_estimator para criar um Estimator usando um keras.Model.

Crie um Estimador usando um modelo do Keras

É possível converter modelos existentes do Keras para Estimadores usando tf.keras.estimator.model_to_estimator, o que é útil se você quiser modernizar o código do seu modelo, mas o seu pipeline de treinamento ainda precisar de Estimadores.

Instancie um modelo do Keras MobileNet V2 e compile-o com o otimizador, a perda e as métricas para o treinamento:

keras_mobilenet_v2 = tf.keras.applications.MobileNetV2( input_shape=(160, 160, 3), include_top=False) keras_mobilenet_v2.trainable = False estimator_model = tf.keras.Sequential([ keras_mobilenet_v2, tf.keras.layers.GlobalAveragePooling2D(), tf.keras.layers.Dense(1) ]) # Compile the model estimator_model.compile( optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['accuracy'])

Crie um Estimator usando o modelo do Keras compilado. O estado inicial do modelo do Keras é preservado no Estimator criado:

est_mobilenet_v2 = tf.keras.estimator.model_to_estimator(keras_model=estimator_model)

Use o Estimator derivado da mesma forma que usaria qualquer outro Estimator.

IMG_SIZE = 160 # All images will be resized to 160x160 def preprocess(image, label): image = tf.cast(image, tf.float32) image = (image/127.5) - 1 image = tf.image.resize(image, (IMG_SIZE, IMG_SIZE)) return image, label
def train_input_fn(batch_size): data = tfds.load('cats_vs_dogs', as_supervised=True) train_data = data['train'] train_data = train_data.map(preprocess).shuffle(500).batch(batch_size) return train_data

Para treinar, chame a função train do Estimador:

est_mobilenet_v2.train(input_fn=lambda: train_input_fn(32), steps=50)

De maneira similar, para avaliar, chame a função evaluate do Estimador:

est_mobilenet_v2.evaluate(input_fn=lambda: train_input_fn(32), steps=10)

Confira mais detalhes na documentação de tf.keras.estimator.model_to_estimator.

Como salvar checkpoints baseados em objetos com o Estimador

Por padrão, os Estimadores salvam checkpoints com nomes de variáveis em vez do grafo de objetos descrito no guia de checkpoints. tf.train.Checkpoint lê checkpoints baseados em nomes, mas os nomes das variáveis podem mudar quando partes de um modelo são levados para fora da model_fn do Estimador. Por questões de compatibilidade futura, salvar checkpoints baseados em objetos facilita o treinamento de um modelo dentro de um Estimador e seu uso fora do Estimador.

import tensorflow.compat.v1 as tf_compat
def toy_dataset(): inputs = tf.range(10.)[:, None] labels = inputs * 5. + tf.range(5.)[None, :] return tf.data.Dataset.from_tensor_slices( dict(x=inputs, y=labels)).repeat().batch(2)
class Net(tf.keras.Model): """A simple linear model.""" def __init__(self): super(Net, self).__init__() self.l1 = tf.keras.layers.Dense(5) def call(self, x): return self.l1(x)
def model_fn(features, labels, mode): net = Net() opt = tf.keras.optimizers.Adam(0.1) ckpt = tf.train.Checkpoint(step=tf_compat.train.get_global_step(), optimizer=opt, net=net) with tf.GradientTape() as tape: output = net(features['x']) loss = tf.reduce_mean(tf.abs(output - features['y'])) variables = net.trainable_variables gradients = tape.gradient(loss, variables) return tf.estimator.EstimatorSpec( mode, loss=loss, train_op=tf.group(opt.apply_gradients(zip(gradients, variables)), ckpt.step.assign_add(1)), # Tell the Estimator to save "ckpt" in an object-based format. scaffold=tf_compat.train.Scaffold(saver=ckpt)) tf.keras.backend.clear_session() est = tf.estimator.Estimator(model_fn, './tf_estimator_example/') est.train(toy_dataset, steps=10)

Depois, tf.train.Checkpoint pode carregar os checkpoints a partir de seu diretório model_dir.

opt = tf.keras.optimizers.Adam(0.1) net = Net() ckpt = tf.train.Checkpoint( step=tf.Variable(1, dtype=tf.int64), optimizer=opt, net=net) ckpt.restore(tf.train.latest_checkpoint('./tf_estimator_example/')) ckpt.step.numpy() # From est.train(..., steps=10)

SavedModels de Estimadores

Os Estimadores exportam SavedModels por meio de tf.Estimator.export_saved_model.

input_column = tf.feature_column.numeric_column("x") estimator = tf.estimator.LinearClassifier(feature_columns=[input_column]) def input_fn(): return tf.data.Dataset.from_tensor_slices( ({"x": [1., 2., 3., 4.]}, [1, 1, 0, 0])).repeat(200).shuffle(64).batch(16) estimator.train(input_fn)

Para salvar um Estimator, você precisa criar um serving_input_receiver. Essa função cria uma parte de um tf.Graph que processa os dados brutos recebidos pelo SavedModel.

O módulo tf.estimator.export contém funções para ajudar a criar esses receivers (receptores).

O código abaixo cria um receptor baseado nas feature_columns (colunas de características) que aceita buffers de protocolo tf.Example serializados, que costumam ser usados com tf-serving.

tmpdir = tempfile.mkdtemp() serving_input_fn = tf.estimator.export.build_parsing_serving_input_receiver_fn( tf.feature_column.make_parse_example_spec([input_column])) estimator_base_path = os.path.join(tmpdir, 'from_estimator') estimator_path = estimator.export_saved_model(estimator_base_path, serving_input_fn)

Também é possível carregar e executar esse modelo pelo Python:

imported = tf.saved_model.load(estimator_path) def predict(x): example = tf.train.Example() example.features.feature["x"].float_list.value.extend([x]) return imported.signatures["predict"]( examples=tf.constant([example.SerializeToString()]))
print(predict(1.5)) print(predict(3.5))

tf.estimator.export.build_raw_serving_input_receiver_fn permite criar funções de entrada que recebam tensores brutos em vez de tf.train.Examples.

Uso de tf.distribute.Strategy com o Estimador (suporte limitado)

tf.estimator é uma API do TensorFlow para treinamento distribuído que, originalmente, tinha suporte à estratégia de servidor de parâmetros assíncrono. Agora, tf.estimator tem suporte a tf.distribute.Strategy. Se você estiver usando tf.estimator, pode alterar para treinamento distribuído com pouquíssimas alterações do código. Dessa forma, agora os usuários do Estimador podem fazer treinamento distribuído síncrono em diversas GPUs e diversos workers, além de usar TPUs. Entretanto, esse suporte no Estimador é limitado. Confira mais informações na seção O que tem suporte atualmente abaixo.

Usar tf.distribute.Strategy com o Estimador é um pouco diferente no caso do Keras. Em vez de usar strategy.scope, agora você passa o objeto de estratégia para o RunConfig referente ao Estimador.

Confira mais informações no guia sobre treinamento distribuído.

Veja abaixo um trecho de código que mostra esse caso com um Estimador pré-criado LinearRegressor e a estratégia MirroredStrategy:

mirrored_strategy = tf.distribute.MirroredStrategy() config = tf.estimator.RunConfig( train_distribute=mirrored_strategy, eval_distribute=mirrored_strategy) regressor = tf.estimator.LinearRegressor( feature_columns=[tf.feature_column.numeric_column('feats')], optimizer='SGD', config=config)

Aqui, utilizamos um Estimador pré-criado, mas o mesmo código também funciona com um Estimador personalizado. train_distribute determina como o treinamento será distribuído, e eval_distribute determina como a avaliação será distribuída. Essa é outra diferença do Keras ao usar a mesma estratégia para treinamento e avaliação.

Agora, você pode treinar e avaliar esse Estimador com uma função de entrada:

def input_fn(): dataset = tf.data.Dataset.from_tensors(({"feats":[1.]}, [1.])) return dataset.repeat(1000).batch(10) regressor.train(input_fn=input_fn, steps=10) regressor.evaluate(input_fn=input_fn, steps=10)

Outra diferença que devemos destacar entre o Estimador e o Keras é o tratamento da entrada. No Keras, cada lote do dataset é dividido automaticamente nas diversas réplicas. Entretanto, no Estimador, você não faz a divisão automática em lotes nem fragmenta automaticamente os dados em diferentes workers. Você tem controle total de como deseja que os dados sejam distribuídos nos workers e dispositivos e precisa fornecer uma input_fn para especificar como os dados devem ser distribuídos.

A input_fn é chamada uma vez por worker e, portanto, envia um dataset para cada worker. Então, um lote desse dataset é alimentado em uma réplica nesse worker, consumindo N lotes para N réplicas nesse único worker. Em outras palavras, o dataset retornado por input_fn deve fornecer lotes de tamanho PER_REPLICA_BATCH_SIZE, e o tamanho global de lote para um passo pode ser obtido por PER_REPLICA_BATCH_SIZE * strategy.num_replicas_in_sync.

Ao fazer um treinamento multiworker, você precisa dividir os dados entre os workers ou misturar com uma semente aleatória em cada um deles. Confira um exemplo de como fazer isso no tutorial Treinamento multiworker com Estimador.

De maneira similar, você também pode usar as estratégias de multiworker e de servidor de parâmetros. O código permanece o mesmo, mas você precisa usar tf.estimator.train_and_evaluate e definir as variáveis de ambiente TF_CONFIG para cada binário sendo executado no seu cluster.

O que tem suporte atualmente?

Há suporte limitado para treinamento com Estimador usando todas as estratégias, exceto TPUStrategy. Treinamentos e avaliações básicos deverão funcionar, mas diversos recursos avançados, como v1.train.Scaffold, não deverão funcionar. Também pode haver diversos bugs nessa integração, e não há planos para melhorar o suporte (o foco está no suporte ao Keras e ao loop de treinamento personalizado). Se possível, prefira usar tf.distribute com essas APIs.

API de treinamentoMirroredStrategyTPUStrategyMultiWorkerMirroredStrategyCentralStorageStrategyParameterServerStrategy
API do EstimadorSuporte limitadoSem suporteSuporte limitadoSuporte limitadoSuporte limitado

Exemplos e tutoriais

Veja alguns exemplos do começo ao fim que mostram como usar as diversas estratégias com o Estimador:

  1. O tutorial Treinamento multiworker com Estimador mostra como treinar com vários workers usando MultiWorkerMirroredStrategy no dataset MNIST.

  2. Um exemplo completo de treinamento multiworker com estratégias distribuídas em tensorflow/ecosystem usando modelos de Kubernetes. O exemplo começa com um modelo do Keras, que é convertido em um Estimador usando a API tf.keras.estimator.model_to_estimator

  3. O modelo oficial ResNet50, que pode ser treinado usando MirroredStrategy ou MultiWorkerMirroredStrategy.