1. Visão geral
Neste laboratório, você vai usar a Vertex AI para executar um job de treinamento com vários workers para um modelo do TensorFlow.
Conteúdo do laboratório
Você vai aprender a:
- Modificar o código do aplicativo de treinamento para vários trabalhadores
- Configurar e iniciar um job de treinamento com vários workers usando a interface da Vertex AI
- Configurar e iniciar um job de treinamento de vários workers com o SDK da Vertex
O custo total da execução deste laboratório no Google Cloud é de aproximadamente US$5.
2. Introdução à Vertex AI
Este laboratório usa a mais nova oferta de produtos de IA disponível no Google Cloud. A Vertex AI integra as ofertas de ML do Google Cloud em uma experiência de desenvolvimento intuitiva. Anteriormente, modelos treinados com o AutoML e modelos personalizados eram acessíveis por serviços separados. A nova oferta combina ambos em uma única API, com outros novos produtos. Você também pode migrar projetos existentes para a Vertex AI. Se você tiver algum feedback, consulte a página de suporte.
A Vertex AI inclui vários produtos diferentes para dar suporte a fluxos de trabalho integrais de ML. Os produtos destacados abaixo são o foco deste laboratório: Treinamentos e Workbench.
3. Visão geral do caso de uso
Neste laboratório, você vai usar o aprendizado de transferência para treinar um modelo de classificação de imagens no conjunto de dados da mandioca dos conjuntos de dados do TensorFlow. A arquitetura que você vai usar é um modelo ResNet50 da biblioteca tf.keras.applications
pré-treinado no conjunto de dados Imagenet.
Por que o treinamento distribuído?
Se você tiver apenas uma GPU, o TensorFlow vai usar esse acelerador no treinamento do modelo sem nenhum trabalho extra da sua parte. No entanto, se você quiser aumentar ainda mais o uso de várias GPUs em uma única máquina ou em várias máquinas (cada uma com várias GPUs), será necessário usar tf.distribute
, que é a biblioteca do TensorFlow para executar uma computação em vários dispositivos. Um dispositivo se refere a uma CPU ou um acelerador, como GPUs ou TPUs, em alguma máquina em que o TensorFlow pode executar operações.
A maneira mais simples de começar a usar o treinamento distribuído é em uma única máquina com vários dispositivos GPU. Uma estratégia de distribuição do TensorFlow do módulo tf.distribute
vai gerenciar a coordenação da distribuição de dados e das atualizações de gradiente em todas as GPUs. Se você domina o treinamento de host único e quer aumentar ainda mais o treinamento, adicione várias máquinas ao cluster para melhorar ainda mais a performance. Você pode usar um cluster de máquinas que sejam apenas CPU ou que tenham uma ou mais GPUs. Este laboratório aborda o último caso e demonstra como usar o MultiWorkerMirroredStrategy
para distribuir o treinamento de um modelo do TensorFlow em várias máquinas na Vertex AI.
MultiWorkerMirroredStrategy
é uma estratégia síncrona de carregamento em paralelo de dados que você pode usar com apenas algumas mudanças no código. Uma cópia do modelo é criada em cada dispositivo no cluster. As próximas atualizações de gradientes ocorrerão de maneira síncrona. Isso significa que cada dispositivo de trabalho calcula as transmissões anteriores e posteriores do modelo em uma fração diferente dos dados de entrada. Os gradientes calculados de cada uma dessas frações são agregados em todos os dispositivos em uma máquina e em todas as máquinas do cluster e reduzidos (geralmente, uma média) em um processo conhecido como redução total. Em seguida, o otimizador realiza as atualizações dos parâmetros com esses gradientes reduzidos, mantendo os dispositivos sincronizados. Para saber mais sobre o treinamento distribuído com o TensorFlow, confira o vídeo abaixo:
4. Configurar o ambiente
Para executar este codelab, você vai precisar de um projeto do Google Cloud Platform com o faturamento ativado. Para criar um projeto, siga estas instruções.
Etapa 1: ativar a API Compute Engine
Acesse o Compute Engine e selecione Ativar, caso essa opção ainda não esteja ativada. Você vai precisar disso para criar sua instância de notebook.
Etapa 2: ativar a API Container Registry
Navegue até o Container Registry e selecione Ativar. Use isso para criar um contêiner para seu job de treinamento personalizado.
Etapa 3: ativar a API Vertex AI
Navegue até a seção "Vertex AI" do Console do Cloud e clique em Ativar API Vertex AI.
Etapa 4: criar uma instância do Vertex AI Workbench
Na seção Vertex AI do Console do Cloud, clique em "Workbench":
Ative a API Notebooks, se ela ainda não tiver sido ativada.
Após a ativação, clique em NOTEBOOK GERENCIADO:
Em seguida, selecione NOVO NOTEBOOK.
Dê um nome ao notebook e clique em Configurações avançadas.
Em "Configurações avançadas", ative o encerramento inativo e defina o número de minutos como 60. Isso significa que o notebook será desligado automaticamente quando não estiver sendo usado.
Em Segurança, selecione "Ativar terminal", se essa opção ainda não estiver ativada.
Você pode manter as outras configurações avançadas como estão.
Em seguida, clique em Criar. O provisionamento da instância vai levar alguns minutos.
Quando a instância tiver sido criada, selecione Abrir o JupyterLab.
Na primeira vez que usar uma nova instância, você vai receber uma solicitação de autenticação. Siga as etapas na IU para isso.
5. fazer a conteinerização do código do aplicativo de treinamento
Para enviar este job de treinamento para a Vertex, coloque o código do aplicativo de treinamento em um contêiner do Docker e envie esse contêiner para o Google Container Registry. Nessa abordagem, é possível treinar um modelo criado com qualquer framework.
Para começar, no menu de acesso rápido, abra uma janela de terminal na instância do notebook:
Crie um novo diretório chamado cassava
e coloque cd nele:
mkdir cassava
cd cassava
Etapa 1: criar um Dockerfile
A primeira etapa na conteinerização de seu código é a criação de um Dockerfile. Nesse Dockerfile, você vai incluir todos os comandos necessários à execução da imagem. Ele vai instalar todas as bibliotecas necessárias e configurar o ponto de entrada do código de treinamento.
No seu terminal, crie um Dockerfile vazio:
touch Dockerfile
Abra o Dockerfile e copie o seguinte nele:
FROM gcr.io/deeplearning-platform-release/tf2-gpu.2-7
WORKDIR /
# Copies the trainer code to the docker image.
COPY trainer /trainer
# Sets up the entry point to invoke the trainer.
ENTRYPOINT ["python", "-m", "trainer.task"]
Este Dockerfile usa a imagem do Docker do TensorFlow Enterprise 2.7 GPU no Deep Learning Container. O componente Deep Learning Containers no Google Cloud vem com vários frameworks de ciência de dados já instalados. Após fazer download dessa imagem, este Dockerfile configura o ponto de entrada para o código de treinamento. Você ainda não criou esses arquivos – na próxima etapa, você vai adicionar o código para treinar e ajustar o modelo.
Etapa 2: criar um bucket do Cloud Storage
Neste job de treinamento, você vai exportar o modelo do TensorFlow treinado para o bucket do Cloud Storage No Terminal, execute o comando a seguir e defina uma variável env para o projeto. Lembre-se de substituir your-cloud-project
pelo ID do projeto.
PROJECT_ID='your-cloud-project'
Depois execute o comando a seguir no terminal para criar um novo bucket no projeto:
BUCKET="gs://${PROJECT_ID}-bucket"
gsutil mb -l us-central1 $BUCKET
Etapa 3: adicionar o código de treinamento do modelo
No seu Terminal, execute o seguinte para criar um diretório para o código de treinamento e um arquivo Python onde você vai adicionar o código:
mkdir trainer
touch trainer/task.py
Agora você deve ter o seguinte no diretório cassava/
:
+ Dockerfile
+ trainer/
+ task.py
Depois abra o arquivo task.py
que você acabou de criar e copie o código abaixo. Substitua {your-gcs-bucket}
pelo nome do bucket do Cloud Storage que você acabou de criar.
import tensorflow as tf
import tensorflow_datasets as tfds
import os
PER_REPLICA_BATCH_SIZE = 64
EPOCHS = 2
# TODO: replace {your-gcs-bucket} with the name of the Storage bucket you created earlier
BUCKET = 'gs://{your-gcs-bucket}/mwms'
def preprocess_data(image, label):
'''Resizes and scales images.'''
image = tf.image.resize(image, (300,300))
return tf.cast(image, tf.float32) / 255., label
def create_dataset(batch_size):
'''Loads Cassava dataset and preprocesses data.'''
data, info = tfds.load(name='cassava', as_supervised=True, with_info=True)
number_of_classes = info.features['label'].num_classes
train_data = data['train'].map(preprocess_data,
num_parallel_calls=tf.data.experimental.AUTOTUNE)
train_data = train_data.shuffle(1000)
train_data = train_data.batch(batch_size)
train_data = train_data.prefetch(tf.data.experimental.AUTOTUNE)
# Set AutoShardPolicy
options = tf.data.Options()
options.experimental_distribute.auto_shard_policy = tf.data.experimental.AutoShardPolicy.DATA
train_data = train_data.with_options(options)
return train_data, number_of_classes
def create_model(number_of_classes):
'''Creates and compiles pretrained ResNet50 model.'''
base_model = tf.keras.applications.ResNet50(weights='imagenet', include_top=False)
x = base_model.output
x = tf.keras.layers.GlobalAveragePooling2D()(x)
x = tf.keras.layers.Dense(1016, activation='relu')(x)
predictions = tf.keras.layers.Dense(number_of_classes, activation='softmax')(x)
model = tf.keras.Model(inputs=base_model.input, outputs=predictions)
model.compile(
loss='sparse_categorical_crossentropy',
optimizer=tf.keras.optimizers.Adam(0.0001),
metrics=['accuracy'])
return model
def _is_chief(task_type, task_id):
'''Helper function. Determines if machine is chief.'''
return task_type == 'chief'
def _get_temp_dir(dirpath, task_id):
'''Helper function. Gets temporary directory for saving model.'''
base_dirpath = 'workertemp_' + str(task_id)
temp_dir = os.path.join(dirpath, base_dirpath)
tf.io.gfile.makedirs(temp_dir)
return temp_dir
def write_filepath(filepath, task_type, task_id):
'''Helper function. Gets filepath to save model.'''
dirpath = os.path.dirname(filepath)
base = os.path.basename(filepath)
if not _is_chief(task_type, task_id):
dirpath = _get_temp_dir(dirpath, task_id)
return os.path.join(dirpath, base)
def main():
# Create strategy
strategy = tf.distribute.MultiWorkerMirroredStrategy()
# Get data
global_batch_size = PER_REPLICA_BATCH_SIZE * strategy.num_replicas_in_sync
train_data, number_of_classes = create_dataset(global_batch_size)
# Wrap variable creation within strategy scope
with strategy.scope():
model = create_model(number_of_classes)
model.fit(train_data, epochs=EPOCHS)
# Determine type and task of the machine from
# the strategy cluster resolver
task_type, task_id = (strategy.cluster_resolver.task_type,
strategy.cluster_resolver.task_id)
# Based on the type and task, write to the desired model path
write_model_path = write_filepath(BUCKET, task_type, task_id)
model.save(write_model_path)
if __name__ == "__main__":
main()
Antes de criar o contêiner, vamos analisar o código mais a fundo. Ele usa MultiWorkerMirroredStrategy
da API tf.distribute.Strategy
.
Há alguns componentes no código que são necessários para que ele funcione com MultiWorkerMirroredStrategy
.
- Os dados precisam ser fragmentados, ou seja, cada worker recebe um subconjunto de todo o conjunto de dados. Portanto, em cada etapa, um tamanho de lote global de elementos do conjunto de dados não sobrepostos será processado por cada worker. Essa fragmentação acontece automaticamente com
tf.data.experimental.AutoShardPolicy
, que pode ser definido comoFILE
ouDATA
. Neste exemplo, a funçãocreate_dataset()
defineAutoShardPolicy
comoDATA
porque o conjunto de dados da mandioca não é transferido como vários arquivos. No entanto, se você não definiu a política comoDATA
, a política padrãoAUTO
será ativada e o resultado final será o mesmo. Saiba mais sobre o fragmentação de conjuntos de dados comMultiWorkerMirroredStrategy
. - Na função
main()
, o objetoMultiWorkerMirroredStrategy
é criado. Depois, envolva a criação das variáveis de modelo no escopo da estratégia. Esta etapa crucial informa ao TensorFlow quais variáveis precisam ser espelhadas nas réplicas. - O tamanho do lote é escalonado verticalmente pelo
num_replicas_in_sync
. Isso garante que cada réplica processe o mesmo número de exemplos em cada etapa. O escalonamento do tamanho do lote é uma prática recomendada ao usar estratégias de paralelismo síncrono de dados no TensorFlow. - É um pouco mais complicado salvar seu modelo no caso de vários workers porque o destino precisa ser diferente para cada um. O worker CHIEF vai ser salvo no diretório do modelo desejado, enquanto os demais vão salvar o modelo em diretórios temporários. É importante que esses diretórios temporários sejam únicos para impedir que vários workers gravem no mesmo local. O salvamento pode conter operações coletivas: todos os workers precisam salvar e não apenas o CHIEF. As funções
_is_chief()
,_get_temp_dir()
,write_filepath()
emain()
incluem código boilerplate que ajuda a salvar o modelo.
Se você usou MultiWorkerMirroredStrategy
em um ambiente diferente, talvez tenha configurado a variável de ambiente TF_CONFIG
. A Vertex AI define a variável TF_CONFIG
automaticamente para que você não precise fazer isso em cada máquina no cluster.
Etapa 4: criar o contêiner
No Terminal, execute o comando a seguir e defina uma variável env para o projeto. Lembre-se de substituir your-cloud-project
pelo ID do projeto.
PROJECT_ID='your-cloud-project'
Defina uma variável com o URI da imagem do seu contêiner no Google Container Registry:
IMAGE_URI="gcr.io/$PROJECT_ID/multiworker:cassava"
Configure o Docker.
gcloud auth configure-docker
Agora execute o comando a seguir na raiz do diretório cassava
para criar o diretório:
docker build ./ -t $IMAGE_URI
Por fim, envie para o Google Container Registry:
docker push $IMAGE_URI
Depois que o contêiner for enviado para o Container Registry, estará tudo pronto para você iniciar o job de treinamento.
6. Executar um job de treinamento com vários workers na Vertex AI
Este laboratório usa treinamento personalizado com um contêiner personalizado no Google Container Registry, mas também é possível executar um job de treinamento com os contêineres pré-criados.
Para começar, navegue até a seção Treinamento na seção da Vertex do console do Cloud:
Etapa 1: configurar job de treinamento
Clique em Criar e insira os parâmetros para seu job de treinamento.
- Em Conjunto de dados, selecione Sem conjunto de dados gerenciado.
- Selecione Treinamento personalizado (avançado) como seu método de treinamento e clique em Continuar.
- Insira
multiworker-cassava
(ou como quiser nomear seu modelo) em Nome do modelo. - Clique em Continuar.
Na etapa "Configurações do contêiner", selecione Container personalizado:
Na primeira caixa (Imagem de contêiner), insira sua variável IMAGE_URI
da seção anterior. Ela precisa ser: gcr.io/your-cloud-project/multiworker:cassava
, com seu próprio ID do projeto. Deixe os demais campos em branco e clique em Continuar.
Pule a etapa de hiperparâmetros clicando em Continuar novamente.
Etapa 2: configurar cluster de computação
A Vertex AI tem quatro pools de workers para cobrir diferentes tipos de tarefas de máquina.
O pool de workers 0 configura o principal, CHIEF, programador ou "mestre". Em MultiWorkerMirroredStrategy
, todas as máquinas são classificadas como workers, que são as máquinas físicas em que a computação replicada é executada. Além de cada máquina ser um worker, é preciso que um deles fique encarregado do trabalho extra, como salvar checkpoints e gravar arquivos de resumo no TensorBoard. Essa máquina é conhecida como CHIEF. Como há apenas um worker CHIEF, sua contagem de workers no pool 0 sempre vai ser 1.
Em Computação e preços, deixe a região selecionada como está e configure o Pool de workers 0 da seguinte forma:
O pool 1 é onde você configura os workers do cluster.
Configure o pool de workers 1 da seguinte forma:
Agora o cluster está configurado para ter duas máquinas somente CPU. Quando o código do aplicativo de treinamento é executado, o MultiWorkerMirroredStrategy
distribui o treinamento entre as duas máquinas.
MultiWorkerMirroredStrategy
tem apenas os tipos de tarefa de chefe e worker, então não é necessário configurar os pools de workers adicionais. No entanto, se você usasse o ParameterServerStrategy
do TensorFlow, configuraria os servidores de parâmetros no pool de workers 2. Se você quiser adicionar um avaliador ao cluster, configure essa máquina no pool de workers 3.
Clique em Iniciar treinamento para iniciar o job de ajuste de hiperparâmetros. Na seção "Treinamento" do console, na guia PIPELINES DE TREINAMENTO, você vai encontrar o job recém-iniciado.
Parabéns! 🎉
Você aprendeu a usar a Vertex AI para:
- Iniciar um job de treinamento com vários workers para o código de treinamento fornecido em um contêiner personalizado. Neste exemplo você usou um modelo do TensorFlow, mas é possível treinar um modelo criado com qualquer estrutura usando contêineres personalizados ou integrados.
Para saber mais sobre as diferentes partes da Vertex, consulte a documentação.
7. use o SDK Vertex [Opcional]
A seção anterior mostrou como iniciar o job de treinamento pela interface. Nesta seção, você vai conhecer uma forma alternativa de enviar o job de treinamento usando a API Vertex Python.
Retorne à sua instância do notebook e crie um notebook do TensorFlow 2 na tela de início:
Importe o SDK da Vertex AI.
from google.cloud import aiplatform
Para iniciar o job de treinamento com vários workers, primeiro é necessário definir a especificação do pool de workers. O uso de GPUs na especificação é totalmente opcional, e você pode remover accelerator_type
e accelerator_count
se quiser um cluster somente de CPU, conforme mostrado na seção anterior.
# The spec of the worker pools including machine type and Docker image
# Be sure to replace {YOUR-PROJECT-ID} with your project ID.
worker_pool_specs=[
{
"replica_count": 1,
"machine_spec": {
"machine_type": "n1-standard-8", "accelerator_type": "NVIDIA_TESLA_V100", "accelerator_count": 1
},
"container_spec": {"image_uri": "gcr.io/{YOUR-PROJECT-ID}/multiworker:cassava"}
},
{
"replica_count": 1,
"machine_spec": {
"machine_type": "n1-standard-8", "accelerator_type": "NVIDIA_TESLA_V100", "accelerator_count": 1
},
"container_spec": {"image_uri": "gcr.io/{YOUR-PROJECT-ID}/multiworker:cassava"}
}
]
Em seguida, crie e execute uma CustomJob
. Você vai precisar substituir {YOUR_BUCKET}
por um bucket no seu projeto para a fase de testes. Você pode usar o mesmo bucket criado anteriormente.
# Replace YOUR_BUCKET
my_multiworker_job = aiplatform.CustomJob(display_name='multiworker-cassava-sdk',
worker_pool_specs=worker_pool_specs,
staging_bucket='gs://{YOUR_BUCKET}')
my_multiworker_job.run()
Na seção "Treinamento" do console, seu job de treinamento vai aparecer na guia JOBS PERSONALIZADOS:
8. Limpeza
Como configuramos o notebook para expirar após 60 minutos de inatividade, não precisamos nos preocupar em desligar a instância. Para encerrar a instância manualmente, clique no botão "Parar" na seção "Vertex AI Workbench" do console. Se quiser excluir o notebook completamente, clique no botão "Excluir".
Para excluir o bucket do Storage, use o menu de navegação do console do Cloud, acesse o Storage, selecione o bucket e clique em "Excluir":