O Dia da Comunidade de ML é dia 9 de novembro! Junte-nos para atualização de TensorFlow, JAX, e mais Saiba mais

Treinamento de modelos Keras com TensorFlow Cloud

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

Introdução

TensorFlow Nuvem é um pacote Python que fornece APIs para uma transição suave da depuração local de treinamento distribuídos em Google Cloud. Ele simplifica o processo de treinamento de modelos do TensorFlow na nuvem em uma única chamada de função simples, exigindo configuração mínima e nenhuma alteração em seu modelo. O TensorFlow Cloud lida com tarefas específicas da nuvem, como a criação de instâncias de VM e estratégias de distribuição para seus modelos automaticamente. Este guia demonstrará como fazer a interface com o Google Cloud por meio do TensorFlow Cloud e a ampla variedade de funcionalidades fornecidas no TensorFlow Cloud. Começaremos com o caso de uso mais simples.

Configurar

Começaremos instalando o TensorFlow Cloud e importando os pacotes de que precisaremos neste guia.

pip install -q tensorflow_cloud
import tensorflow as tf
import tensorflow_cloud as tfc

from tensorflow import keras
from tensorflow.keras import layers
2021-07-27 22:07:16.348453: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudart.so.11.0

Visão geral da API: um primeiro exemplo de ponta a ponta

Vamos começar com um script de treinamento de modelo Keras, como o seguinte CNN:

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()

model = keras.Sequential(
    [
        keras.Input(shape=(28, 28)),
        # Use a Rescaling layer to make sure input values are in the [0, 1] range.
        layers.experimental.preprocessing.Rescaling(1.0 / 255),
        # The original images have shape (28, 28), so we reshape them to (28, 28, 1)
        layers.Reshape(target_shape=(28, 28, 1)),
        # Follow-up with a classic small convnet
        layers.Conv2D(32, 3, activation="relu"),
        layers.MaxPooling2D(2),
        layers.Conv2D(32, 3, activation="relu"),
        layers.MaxPooling2D(2),
        layers.Conv2D(32, 3, activation="relu"),
        layers.Flatten(),
        layers.Dense(128, activation="relu"),
        layers.Dense(10),
    ]
)

model.compile(
    optimizer=keras.optimizers.Adam(),
    loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=keras.metrics.SparseCategoricalAccuracy(),
)

model.fit(x_train, y_train, epochs=20, batch_size=128, validation_split=0.1)

Para treinar este modelo no Google Cloud só precisamos adicionar uma chamada para run() no início do script, antes das importações:

tfc.run()

Você não precisa se preocupar com tarefas específicas da nuvem, como a criação de instâncias de VM e estratégias de distribuição ao usar o TensorFlow Cloud. A API inclui padrões inteligentes para todos os parâmetros - tudo é configurável, mas muitos modelos podem contar com esses padrões.

No ligando run() , TensorFlow nuvem:

  • Prepare seu script Python ou notebook para distribuição.
  • Converta-o em uma imagem Docker com dependências necessárias.
  • Execute o job de treinamento em uma VM equipada com GPU do GCP.
  • Transmita registros relevantes e informações de trabalho.

A configuração padrão da VM é 1 chefe e 0 trabalhadores com 8 núcleos de CPU e 1 GPU Tesla T4.

Configuração do Google Cloud

A fim de facilitar os caminhos adequados para o treinamento em nuvem, você precisará fazer algumas configurações iniciais. Se você for um novo usuário do Google Cloud, existem algumas etapas preliminares que você precisará seguir:

  1. Crie um projeto GCP;
  2. Habilite os serviços do AI Platform;
  3. Crie uma conta de serviço;
  4. Baixe uma chave de autorização;
  5. Crie um intervalo do Cloud Storage.

Instruções de instalação detalhadas pela primeira vez pode ser encontrada no TensorFlow Nuvem README , e um exemplo de configuração adicional é mostrado no Blog TensorFlow .

Fluxos de trabalho comuns e armazenamento em nuvem

Na maioria dos casos, você desejará recuperar seu modelo após o treinamento no Google Cloud. Para isso, é fundamental redirecionar o salvamento e o carregamento para o Cloud Storage durante o treinamento remoto. Podemos direcionar o TensorFlow Cloud ao nosso intervalo do Cloud Storage para uma variedade de tarefas. O intervalo de armazenamento pode ser usado para salvar e carregar grandes conjuntos de dados de treinamento, armazenar logs de retorno de chamada ou pesos de modelo e salvar arquivos de modelo treinados. Para começar, vamos configure fit() para salvar o modelo para a Cloud Storage e configurar TensorBoard monitoramento para acompanhar o progresso de treinamento.

def create_model():
    model = keras.Sequential(
        [
            keras.Input(shape=(28, 28)),
            layers.experimental.preprocessing.Rescaling(1.0 / 255),
            layers.Reshape(target_shape=(28, 28, 1)),
            layers.Conv2D(32, 3, activation="relu"),
            layers.MaxPooling2D(2),
            layers.Conv2D(32, 3, activation="relu"),
            layers.MaxPooling2D(2),
            layers.Conv2D(32, 3, activation="relu"),
            layers.Flatten(),
            layers.Dense(128, activation="relu"),
            layers.Dense(10),
        ]
    )

    model.compile(
        optimizer=keras.optimizers.Adam(),
        loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
        metrics=keras.metrics.SparseCategoricalAccuracy(),
    )
    return model

Vamos salvar os registros do TensorBoard e os pontos de verificação do modelo gerados durante o treinamento em nosso intervalo de armazenamento em nuvem.

import datetime
import os

# Note: Please change the gcp_bucket to your bucket name.
gcp_bucket = "keras-examples"

checkpoint_path = os.path.join("gs://", gcp_bucket, "mnist_example", "save_at_{epoch}")

tensorboard_path = os.path.join(  # Timestamp included to enable timeseries graphs
    "gs://", gcp_bucket, "logs", datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
)

callbacks = [
    # TensorBoard will store logs for each epoch and graph performance for us.
    keras.callbacks.TensorBoard(log_dir=tensorboard_path, histogram_freq=1),
    # ModelCheckpoint will save models after each epoch for retrieval later.
    keras.callbacks.ModelCheckpoint(checkpoint_path),
    # EarlyStopping will terminate training when val_loss ceases to improve.
    keras.callbacks.EarlyStopping(monitor="val_loss", patience=3),
]

model = create_model()
2021-07-27 22:07:18.825259: I tensorflow/core/profiler/lib/profiler_session.cc:126] Profiler session initializing.
2021-07-27 22:07:18.825306: I tensorflow/core/profiler/lib/profiler_session.cc:141] Profiler session started.
2021-07-27 22:07:18.826514: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcuda.so.1
2021-07-27 22:07:19.524654: I tensorflow/core/profiler/internal/gpu/cupti_tracer.cc:1611] Profiler found 1 GPUs
2021-07-27 22:07:19.569799: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcupti.so.11.2
2021-07-27 22:07:19.574795: I tensorflow/core/profiler/lib/profiler_session.cc:159] Profiler session tear down.
2021-07-27 22:07:19.574958: I tensorflow/core/profiler/internal/gpu/cupti_tracer.cc:1743] CUPTI activity buffer flushed
2021-07-27 22:07:19.590994: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-27 22:07:19.592061: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1733] Found device 0 with properties: 
pciBusID: 0000:00:05.0 name: Tesla V100-SXM2-16GB computeCapability: 7.0
coreClock: 1.53GHz coreCount: 80 deviceMemorySize: 15.78GiB deviceMemoryBandwidth: 836.37GiB/s
2021-07-27 22:07:19.592100: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudart.so.11.0
2021-07-27 22:07:19.595897: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublas.so.11
2021-07-27 22:07:19.595991: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublasLt.so.11
2021-07-27 22:07:19.597230: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcufft.so.10
2021-07-27 22:07:19.597581: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcurand.so.10
2021-07-27 22:07:19.598756: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcusolver.so.11
2021-07-27 22:07:19.599746: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcusparse.so.11
2021-07-27 22:07:19.599930: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudnn.so.8
2021-07-27 22:07:19.600043: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-27 22:07:19.601088: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-27 22:07:19.602037: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1871] Adding visible gpu devices: 0
2021-07-27 22:07:19.602416: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 AVX512F FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2021-07-27 22:07:19.603033: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-27 22:07:19.604024: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1733] Found device 0 with properties: 
pciBusID: 0000:00:05.0 name: Tesla V100-SXM2-16GB computeCapability: 7.0
coreClock: 1.53GHz coreCount: 80 deviceMemorySize: 15.78GiB deviceMemoryBandwidth: 836.37GiB/s
2021-07-27 22:07:19.604096: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-27 22:07:19.605089: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-27 22:07:19.606005: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1871] Adding visible gpu devices: 0
2021-07-27 22:07:19.606052: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudart.so.11.0
2021-07-27 22:07:20.242028: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1258] Device interconnect StreamExecutor with strength 1 edge matrix:
2021-07-27 22:07:20.242067: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1264]      0 
2021-07-27 22:07:20.242076: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1277] 0:   N 
2021-07-27 22:07:20.242317: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-27 22:07:20.243478: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-27 22:07:20.244412: I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:937] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
2021-07-27 22:07:20.245277: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1418] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 14646 MB memory) -> physical GPU (device: 0, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:05.0, compute capability: 7.0)
WARNING:tensorflow:Please add `keras.layers.InputLayer` instead of `keras.Input` to Sequential model. `keras.Input` is intended to be used by Functional model.
WARNING:tensorflow:Please add `keras.layers.InputLayer` instead of `keras.Input` to Sequential model. `keras.Input` is intended to be used by Functional model.

Aqui, carregaremos nossos dados de Keras diretamente. Em geral, é uma prática recomendada armazenar seu conjunto de dados no intervalo do Cloud Storage, mas o TensorFlow Cloud também pode acomodar conjuntos de dados armazenados localmente. Isso é abordado na seção de vários arquivos deste guia.

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()

O TensorFlow Nuvem API fornece o remote() função para determinar se o código está sendo executado localmente ou na nuvem. Isto permite a designação separada de fit() parâmetros para execução local e remota, e fornece meios para depuração fácil sem sobrecarregar sua máquina local.

if tfc.remote():
    epochs = 100
    callbacks = callbacks
    batch_size = 128
else:
    epochs = 5
    batch_size = 64
    callbacks = None

model.fit(x_train, y_train, epochs=epochs, callbacks=callbacks, batch_size=batch_size)
2021-07-27 22:07:21.458608: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:176] None of the MLIR Optimization Passes are enabled (registered 2)
2021-07-27 22:07:21.459072: I tensorflow/core/platform/profile_utils/cpu_utils.cc:114] CPU Frequency: 2000170000 Hz
Epoch 1/5
2021-07-27 22:07:21.885085: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcudnn.so.8
2021-07-27 22:07:23.986122: I tensorflow/stream_executor/cuda/cuda_dnn.cc:359] Loaded cuDNN version 8100
2021-07-27 22:07:29.307903: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublas.so.11
2021-07-27 22:07:29.684317: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublasLt.so.11
938/938 [==============================] - 12s 3ms/step - loss: 0.2065 - sparse_categorical_accuracy: 0.9374
Epoch 2/5
938/938 [==============================] - 3s 3ms/step - loss: 0.0577 - sparse_categorical_accuracy: 0.9822
Epoch 3/5
938/938 [==============================] - 3s 3ms/step - loss: 0.0415 - sparse_categorical_accuracy: 0.9868
Epoch 4/5
938/938 [==============================] - 3s 3ms/step - loss: 0.0332 - sparse_categorical_accuracy: 0.9893
Epoch 5/5
938/938 [==============================] - 3s 3ms/step - loss: 0.0275 - sparse_categorical_accuracy: 0.9915
<tensorflow.python.keras.callbacks.History at 0x7f7b0c66a390>

Vamos salvar o modelo no GCS após a conclusão do treinamento.

save_path = os.path.join("gs://", gcp_bucket, "mnist_example")

if tfc.remote():
    model.save(save_path)

Também podemos usar este intervalo de armazenamento para a construção de imagens Docker, em vez de sua instância Docker local. Para isso, basta adicionar o seu balde para o docker_image_bucket_name parâmetro.

tfc.run(docker_image_bucket_name=gcp_bucket)

Depois de treinar o modelo, podemos carregar o modelo salvo e visualizar nossos registros do TensorBoard para monitorar o desempenho.

model = keras.models.load_model(save_path)
!tensorboard dev upload --logdir "gs://keras-examples-jonah/logs/fit" --name "Guide MNIST"

Projetos de grande escala

Em muitos casos, seu projeto contendo um modelo Keras pode abranger mais de um script Python ou pode envolver dados externos ou dependências específicas. O TensorFlow Cloud é totalmente flexível para implantação em grande escala e oferece várias funcionalidades inteligentes para auxiliar seus projetos.

Pontos de entrada: suporte para scripts Python e notebooks Jupyter

Sua chamada para o run() API não vai ser sempre contido dentro do mesmo script Python como o seu Código de treinamento do modelo. Para isso, nós fornecemos uma entry_point parâmetro. O entry_point parâmetro pode ser usado para especificar o script Python ou notebook em que o seu modelo de vida do código de treinamento. Ao chamar run() a partir do mesmo script como seu modelo, use o entry_point padrão de None .

pip dependências

Se as chamadas de projeto sobre adicionais pip dependências, é possível especificar as bibliotecas necessárias adicionais, incluindo um requirements.txt arquivo. Neste arquivo, basta colocar uma lista de todas as dependências necessárias e o TensorFlow Cloud fará a integração delas em sua compilação de nuvem.

Cadernos Python

O TensorFlow Cloud também pode ser executado a partir de notebooks Python. Além disso, seu especificado entry_point pode ser um notebook, se necessário. Há duas diferenças principais a serem lembradas entre o TensorFlow Cloud em notebooks e scripts:

  • Ao chamar run() de dentro de um notebook, um balde Cloud Storage deve ser especificado para construir e armazenar sua imagem Docker.
  • A autenticação do GCloud ocorre inteiramente por meio de sua chave de autenticação, sem especificação de projeto. Um exemplo de fluxo de trabalho usando TensorFlow Cloud em um notebook é fornecido na seção "Juntando tudo" deste guia.

Projetos de vários arquivos

Se o seu modelo depender de arquivos adicionais, você só precisa garantir que esses arquivos residam no mesmo diretório (ou subdiretório) do ponto de entrada especificado. Cada arquivo que é armazenado no mesmo diretório que o especificado entry_point será incluído na imagem Docker, bem como todos os arquivos armazenados em subdiretórios adjacentes ao entry_point . Isto também é verdade para as dependências que você pode precisar que não podem ser adquiridas através do pip

Para um exemplo de um costume entrada pontos e projeto multi-arquivo com dependências pip adicionais, dê uma olhada neste exemplo multi-arquivo no Repositório Nuvem TensorFlow . Para abreviar, vamos incluir o exemplo run() chamada:

tfc.run(
    docker_image_bucket_name=gcp_bucket,
    entry_point="train_model.py",
    requirements="requirements.txt"
)

Configuração da máquina e treinamento distribuído

O treinamento do modelo pode exigir uma ampla gama de recursos diferentes, dependendo do tamanho do modelo ou do conjunto de dados. Ao contabilizar para configurações com várias GPUs, torna-se fundamental para escolher um ajuste estratégia de distribuição . Aqui, descrevemos algumas configurações possíveis:

Distribuição multi-trabalhadores

Aqui, podemos usar COMMON_MACHINE_CONFIGS para designar 1 principais CPU e 4 trabalhadores GPUs.

tfc.run(
    docker_image_bucket_name=gcp_bucket,
    chief_config=tfc.COMMON_MACHINE_CONFIGS['CPU'],
    worker_count=2,
    worker_config=tfc.COMMON_MACHINE_CONFIGS['T4_4X']
)

Por padrão, TensorFlow Nuvem escolhe a melhor estratégia de distribuição para a sua configuração de máquina com uma fórmula simples usando o chief_config , worker_config e worker_count parâmetros fornecidos.

Distribuição TPU

Vamos treinar o mesmo modelo na TPU, conforme mostrado:

tfc.run(
    docker_image_bucket_name=gcp_bucket,
    chief_config=tfc.COMMON_MACHINE_CONFIGS["CPU"],
    worker_count=1,
    worker_config=tfc.COMMON_MACHINE_CONFIGS["TPU"]
)

Estratégia de distribuição personalizada

Para especificar uma estratégia de distribuição personalizada, formatar seu código normalmente como você faria de acordo com o guia de treinamento distribuídos e conjunto distribution_strategy para None . A seguir, especificaremos nossa própria estratégia de distribuição para o mesmo modelo MNIST.

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()

mirrored_strategy = tf.distribute.MirroredStrategy()
with mirrored_strategy.scope():
  model = create_model()

if tfc.remote():
    epochs = 100
    batch_size = 128
else:
    epochs = 10
    batch_size = 64
    callbacks = None

model.fit(
    x_train, y_train, epochs=epochs, callbacks=callbacks, batch_size=batch_size
)

tfc.run(
    docker_image_bucket_name=gcp_bucket,
    chief_config=tfc.COMMON_MACHINE_CONFIGS['CPU'],
    worker_count=2,
    worker_config=tfc.COMMON_MACHINE_CONFIGS['T4_4X'],
    distribution_strategy=None
)

Imagens personalizadas do Docker

Por padrão, TensorFlow Nuvem usa uma imagem base Docker fornecido pelo Google e que corresponde a sua versão atual TensorFlow. No entanto, você também pode especificar uma imagem Docker personalizada para atender aos seus requisitos de compilação, se necessário. Para este exemplo, especificaremos a imagem Docker de uma versão mais antiga do TensorFlow:

tfc.run(
    docker_image_bucket_name=gcp_bucket,
    base_docker_image="tensorflow/tensorflow:2.1.0-gpu"
)

Métricas adicionais

Você pode achar útil marcar seus jobs na nuvem com rótulos específicos ou transmitir os registros do seu modelo durante o treinamento na nuvem. É uma boa prática manter a rotulagem adequada em todos os trabalhos na nuvem, para manutenção de registros. Para este fim, run() aceita um dicionário de etiquetas de até 64 pares de valor-chave, que são visíveis a partir dos logs de construção nuvem. Logs como desempenho época e salvando modelo internos podem ser acessados usando o link fornecido por meio da execução tfc.run ou impresso para o seu terminal local usando o stream_logs bandeira.

job_labels = {"job": "mnist-example", "team": "keras-io", "user": "jonah"}

tfc.run(
    docker_image_bucket_name=gcp_bucket,
    job_labels=job_labels,
    stream_logs=True
)

Juntando tudo

Para uma profunda Colab que utiliza muitas das características descritas neste guia, acompanhar este exemplo para treinar um modelo de estado-of-the-art para reconhecer raças de cães de fotos usando a extração de características.