1. Introdução
Neste laboratório, você vai aprender a usar rotinas de previsão personalizadas na Vertex AI para criar uma lógica personalizada de pré e pós-processamento. Embora este exemplo use o Scikit-learn, as rotinas de previsão personalizadas podem funcionar com outros frameworks de ML do Python, como XGBoost, PyTorch e TensorFlow.
O que você vai aprender
- Escrever uma lógica de previsão personalizada com rotinas de previsão personalizadas
- Teste o contêiner de exibição personalizado e o modelo localmente
- Testar o contêiner de exibição personalizado no Vertex AI Predictions
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 para a Vertex AI.
A Vertex AI inclui vários produtos diferentes para dar suporte a fluxos de trabalho integrais de ML. O foco deste laboratório é o Previsões e o Workbench.
3. Visão geral do caso de uso
Neste laboratório, você vai criar um modelo aleatório de regressão de floresta para prever o preço de um diamante com base em atributos como corte, clareza e tamanho.
Crie uma lógica de pré-processamento personalizada para verificar se os dados no momento da disponibilização estão no formato esperado pelo modelo. Você também vai criar uma lógica personalizada de pós-processamento para arredondar as previsões e convertê-las em strings. Para escrever essa lógica, você usará rotinas de previsão personalizadas.
Introdução às rotinas de previsão personalizadas
Os contêineres pré-criados da Vertex AI lidam com solicitações de previsão ao realizar a operação de previsão do framework de machine learning. Antes das rotinas de previsão personalizadas, se você quiser pré-processar a entrada antes da execução da previsão ou pós-processar a previsão do modelo antes de retornar o resultado, será necessário criar um contêiner personalizado.
Criar um contêiner de exibição personalizado requer a gravação de um servidor HTTP que encapsula o modelo treinado, traduz as solicitações HTTP em entradas do modelo e traduza as saídas do modelo em respostas.
Com rotinas de previsão personalizadas, a Vertex AI fornece os componentes relacionados à disponibilização para você, para que você possa se concentrar no seu modelo e nas transformações de dados.
O que você vai criar
Você vai configurar uma rede VPC chamada biasl-vpc, que consiste em uma sub-rede do workbench usada para implantar um notebook gerenciado pelo usuário e acessar a previsão on-line e o endpoint do modelo implantado em us-central1, ilustrados na figura 1 abaixo.
Figure1
4. Ativar APIs do tutorial
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 Artifact Registry
Navegue até o Artifact Registry e selecione "Ativar", se essa opção ainda não estiver ativada. Ele será usado para criar um contêiner de veiculação 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
Ative a API Notebooks se ela ainda não estiver ativada.
5. Crie o goall-vpc
Neste tutorial, usamos as variáveis $variables para ajudar na implementação da configuração da gcloud no Cloud Shell.
No Cloud Shell, faça o seguinte:
gcloud config list project
gcloud config set project [YOUR-PROJECT-NAME]
projectid=YOUR-PROJECT-NAME
echo $projectid
Criar o goall-vpc
No Cloud Shell, faça o seguinte:
gcloud compute networks create aiml-vpc --project=$projectid --subnet-mode=custom
Crie a sub-rede de notebook gerenciada pelo usuário
No Cloud Shell, crie a sub-rede workbench.
gcloud compute networks subnets create workbench-subnet --project=$projectid --range=172.16.10.0/28 --network=aiml-vpc --region=us-central1 --enable-private-ip-google-access
Configuração do Cloud Router e NAT
O Cloud NAT é usado no tutorial para fazer o download de pacotes de software, porque o notebook gerenciado pelo usuário não tem um endereço IP externo. O Cloud NAT oferece recursos de saída de NAT, o que significa que os hosts da Internet não têm permissão para iniciar a comunicação com um notebook gerenciado pelo usuário, o que o torna mais seguro.
No Cloud Shell, crie o Cloud Router regional, us-central1.
gcloud compute routers create cloud-router-us-central1-aiml-nat --network aiml-vpc --region us-central1
No Cloud Shell, crie o gateway cloud nat regional, us-central1.
gcloud compute routers nats create cloud-nat-us-central1 --router=cloud-router-us-central1-aiml-nat --auto-allocate-nat-external-ips --nat-all-subnet-ip-ranges --region us-central1
6. Criar o notebook gerenciado pelo usuário
Criar uma conta de serviço gerenciada pelo usuário (Notebook)
Na seção a seguir, você vai criar uma conta de serviço gerenciada pelo usuário que será associada ao Vertex Workbench (Notebook) usado no tutorial.
No tutorial, a conta de serviço terá as seguintes regras aplicadas:
No Cloud Shell, crie a conta de serviço.
gcloud iam service-accounts create user-managed-notebook-sa \
--display-name="user-managed-notebook-sa"
No Cloud Shell, atualize a conta de serviço com o papel Administrador de armazenamento.
gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:user-managed-notebook-sa@$projectid.iam.gserviceaccount.com" --role="roles/storage.admin"
No Cloud Shell, atualize a conta de serviço com o papel de Usuário da Vertex AI.
gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:user-managed-notebook-sa@$projectid.iam.gserviceaccount.com" --role="roles/aiplatform.user"
No Cloud Shell, atualize a conta de serviço com o papel de Administrador do Artifact Registry.
gcloud projects add-iam-policy-binding $projectid --member="serviceAccount:user-managed-notebook-sa@$projectid.iam.gserviceaccount.com" --role="roles/artifactregistry.admin"
No Cloud Shell, liste a conta de serviço e anote o endereço de e-mail que será usado ao criar o notebook gerenciado pelo usuário.
gcloud iam service-accounts list
Criar o notebook gerenciado pelo usuário
Na seção a seguir, crie um notebook gerenciado pelo usuário que incorpore a conta de serviço criada anteriormente, user-managed-notebook-sa.
No Cloud Shell, crie a instância private-client.
gcloud notebooks instances create workbench-tutorial \
--vm-image-project=deeplearning-platform-release \
--vm-image-family=common-cpu-notebooks \
--machine-type=n1-standard-4 \
--location=us-central1-a \
--shielded-secure-boot \
--subnet-region=us-central1 \
--subnet=workbench-subnet \
--no-public-ip --service-account=user-managed-notebook-sa@$projectid.iam.gserviceaccount.com
7. Escrever o código de treinamento
Etapa 1: criar um bucket do Cloud Storage
Você vai armazenar o modelo e os artefatos de pré-processamento em um bucket do Cloud Storage. Se você já tiver um bucket no projeto que gostaria de usar, pule esta etapa.
Na tela de início, abra uma nova sessão do terminal.
No seu terminal, execute o seguinte comando para definir uma variável env para o projeto. Lembre-se de substituir your-cloud-project pelo ID do seu 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}-cpr-bucket"
gsutil mb -l us-central1 $BUCKET
Etapa 2: treinar o modelo
No terminal, crie um novo diretório chamado cpr-codelab e use cd nele.
mkdir cpr-codelab
cd cpr-codelab
No navegador de arquivos, navegue até o novo diretório cpr-codelab e use o inicializador para criar um novo notebook Python 3 chamado task.ipynb.
O diretório cpr-codelab ficará assim:
+ cpr-codelab/
+ task.ipynb
No notebook, cole o código a seguir.
Primeiro, escreva um arquivo requirements.txt.
%%writefile requirements.txt
fastapi
uvicorn==0.17.6
joblib~=1.1.1
numpy>=1.17.3, <1.24.0
scikit-learn~=1.0.0
pandas
google-cloud-storage>=2.2.1,<3.0.0dev
google-cloud-aiplatform[prediction]>=1.18.2
O modelo que você implantar terá um conjunto diferente de dependências pré-instalados do seu ambiente de notebook. Por isso, convém listar todas as dependências do modelo em requirements.txt e usar o pip para instalar exatamente as mesmas dependências no notebook. Mais tarde, você vai testar o modelo localmente antes de implantá-lo na Vertex AI para verificar se os ambientes correspondem.
Pip instala as dependências no notebook.
!pip install -U --user -r requirements.txt
Você vai precisar reiniciar o kernel depois que a instalação do pip for concluída.
Em seguida, crie os diretórios em que você vai armazenar o modelo e os artefatos de pré-processamento.
USER_SRC_DIR = "src_dir"
!mkdir $USER_SRC_DIR
!mkdir model_artifacts
# copy the requirements to the source dir
!cp requirements.txt $USER_SRC_DIR/requirements.txt
O diretório cpr-codelab ficará assim:
+ cpr-codelab/
+ model_artifacts/
+ scr_dir/
+ requirements.txt
+ task.ipynb
+ requirements.txt
Agora que a estrutura de diretórios está configurada, é hora de treinar um modelo.
Primeiro, importe as bibliotecas.
import seaborn as sns
import numpy as np
import pandas as pd
from sklearn import preprocessing
from sklearn.ensemble import RandomForestRegressor
from sklearn.pipeline import make_pipeline
from sklearn.compose import make_column_transformer
import joblib
import logging
# set logging to see the docker container logs
logging.basicConfig(level=logging.INFO)
Em seguida, defina as variáveis a seguir. Substitua PROJECT_ID pelo seu ID do projeto e BUCKET_NAME pelo bucket que você criou na etapa anterior.
REGION = "us-central1"
MODEL_ARTIFACT_DIR = "sklearn-model-artifacts"
REPOSITORY = "diamonds"
IMAGE = "sklearn-image"
MODEL_DISPLAY_NAME = "diamonds-cpr"
# Replace with your project
PROJECT_ID = "{PROJECT_ID}"
# Replace with your bucket
BUCKET_NAME = "gs://{BUCKET_NAME}"
Carregue os dados da biblioteca seaborn e crie dois data frames, um com os atributos e outro com o rótulo.
data = sns.load_dataset('diamonds', cache=True, data_home=None)
label = 'price'
y_train = data['price']
x_train = data.drop(columns=['price'])
Vamos analisar os dados de treinamento. Observe que cada linha representa um losango.
x_train.head()
E os rótulos, que são os preços correspondentes.
y_train.head()
Agora, defina uma transformação de coluna do sklearn para uma codificação quente dos atributos categóricos e dimensione os atributos numéricos
column_transform = make_column_transformer(
(preprocessing.OneHotEncoder(sparse=False), [1,2,3]),
(preprocessing.StandardScaler(), [0,4,5,6,7,8]))
Definir o modelo de floresta aleatória
regr = RandomForestRegressor(max_depth=10, random_state=0)
Em seguida, crie um pipeline sklearn. Isso significa que os dados alimentados a esse pipeline primeiro serão codificados/escalonados e, em seguida, transmitidos para o modelo.
my_pipeline = make_pipeline(column_transform, regr)
Ajustar o pipeline aos dados de treinamento
my_pipeline.fit(x_train, y_train)
Vamos testar o modelo para ter certeza de que está funcionando como esperado. Chame o método de previsão no modelo, transmitindo um exemplo de teste.
my_pipeline.predict([[0.23, 'Ideal', 'E', 'SI2', 61.5, 55.0, 3.95, 3.98, 2.43]])
Agora podemos salvar o pipeline no diretório model_artifacts e copiá-lo para o bucket do Cloud Storage
joblib.dump(my_pipeline, 'model_artifacts/model.joblib')
!gsutil cp model_artifacts/model.joblib {BUCKET_NAME}/{MODEL_ARTIFACT_DIR}/
Etapa 3: salvar um artefato de pré-processamento
Em seguida, você criará um artefato de pré-processamento. Esse artefato será carregado no contêiner personalizado quando o servidor de modelo for iniciado. O artefato de pré-processamento pode ter praticamente qualquer formato (como um arquivo pickle), mas nesse caso você gravará um dicionário em um arquivo JSON.
clarity_dict={"Flawless": "FL",
"Internally Flawless": "IF",
"Very Very Slightly Included": "VVS1",
"Very Slightly Included": "VS2",
"Slightly Included": "S12",
"Included": "I3"}
O recurso de clareza nos dados de treinamento sempre esteve na forma abreviada (ou seja, "FL" em vez de "Flawless"). No momento da veiculação, queremos verificar se os dados desse atributo também estão abreviados. Isso ocorre porque o modelo sabe como fazer a codificação quente "FL" mas não "Sem falhas". Você vai criar essa lógica de pré-processamento personalizada mais tarde. Mas, por enquanto, salve essa tabela de consulta em um arquivo JSON e a grave no bucket do Cloud Storage.
import json
with open("model_artifacts/preprocessor.json", "w") as f:
json.dump(clarity_dict, f)
!gsutil cp model_artifacts/preprocessor.json {BUCKET_NAME}/{MODEL_ARTIFACT_DIR}/
O diretório local cpr-codelab terá esta aparência:
+ cpr-codelab/
+ model_artifacts/
+ model.joblib
+ preprocessor.json
+ scr_dir/
+ requirements.txt
+ task.ipynb
+ requirements.txt
8. Crie um contêiner de veiculação personalizado usando o servidor do modelo de CPR
Agora que o modelo foi treinado e o artefato de pré-processamento foi salvo, é hora de criar o contêiner de exibição personalizado. Normalmente, a criação de um contêiner de exibição requer a gravação do código do servidor do modelo. No entanto, com rotinas de previsão personalizadas, o Vertex AI Previsões gera um servidor de modelo e cria uma imagem de contêiner personalizada para você.
Um contêiner de veiculação personalizada contém as três partes de código a seguir:
- Servidor de modelo (gerado automaticamente pelo SDK e armazenado em scr_dir/)
- Servidor HTTP que hospeda o modelo
- Responsável por configurar rotas/portas/etc.
- Responsável por aspectos do servidor da Web relacionados ao tratamento de uma solicitação, como desserialização do corpo da solicitação e serialização da resposta, definição de cabeçalhos de resposta etc.
- Neste exemplo, você vai usar o gerenciador padrão, google.cloud.aiplatform.prediction.handler.PredictionHandler, fornecido no SDK.
- Responsável pela lógica de ML para processar uma solicitação de previsão.
Cada um desses componentes pode ser personalizado com base nos requisitos do seu caso de uso. Neste exemplo, você vai implementar apenas o preditor.
O preditor é responsável pela lógica de ML para processar uma solicitação de previsão, como pré-processamento personalizado e pós-processamento. Para criar uma lógica de previsão personalizada, você vai criar uma subclasse da interface do Preditor da Vertex AI.
Essa versão das rotinas de previsão personalizadas vem com preditores XGBoost e Sklearn reutilizáveis, mas se você precisar usar um framework diferente, crie uma subclasse do preditor base.
Veja um exemplo do preditor do Sklearn abaixo. Esse é todo o código que você precisa escrever para criar esse servidor de modelo personalizado.
No seu notebook, cole o código a seguir abaixo para criar uma subclasse para SklearnPredictor e grave-o em um arquivo Python em src_dir/. Neste exemplo, estamos personalizando apenas os métodos de carregamento, pré-processamento e pós-processamento, e não o de previsão.
%%writefile $USER_SRC_DIR/predictor.py
import joblib
import numpy as np
import json
from google.cloud import storage
from google.cloud.aiplatform.prediction.sklearn.predictor import SklearnPredictor
class CprPredictor(SklearnPredictor):
def __init__(self):
return
def load(self, artifacts_uri: str) -> None:
"""Loads the sklearn pipeline and preprocessing artifact."""
super().load(artifacts_uri)
# open preprocessing artifact
with open("preprocessor.json", "rb") as f:
self._preprocessor = json.load(f)
def preprocess(self, prediction_input: np.ndarray) -> np.ndarray:
"""Performs preprocessing by checking if clarity feature is in abbreviated form."""
inputs = super().preprocess(prediction_input)
for sample in inputs:
if sample[3] not in self._preprocessor.values():
sample[3] = self._preprocessor[sample[3]]
return inputs
def postprocess(self, prediction_results: np.ndarray) -> dict:
"""Performs postprocessing by rounding predictions and converting to str."""
return {"predictions": [f"${value}" for value in np.round(prediction_results)]}
Vamos analisar melhor cada um desses métodos.
- O método de carregamento é carregado no artefato de pré-processamento, que, neste caso, é um dicionário que mapeia os valores de clareza do diamante para as respectivas abreviações.
- O método de pré-processamento usa esse artefato para garantir que, no momento da disponibilização, o recurso de clareza esteja no formato abreviado. Caso contrário, ele converte a string completa para sua abreviação.
- O método de pós-processamento retorna o valor previsto como uma string com um sinal $ e arredonda o valor.
Em seguida, use o SDK da Vertex AI para Python para criar a imagem. Usando rotinas de previsão personalizadas, o Dockerfile será gerado e uma imagem será criada para você.
from google.cloud import aiplatform
aiplatform.init(project=PROJECT_ID, location=REGION)
import os
from google.cloud.aiplatform.prediction import LocalModel
from src_dir.predictor import CprPredictor # Should be path of variable $USER_SRC_DIR
local_model = LocalModel.build_cpr_model(
USER_SRC_DIR,
f"{REGION}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY}/{IMAGE}",
predictor=CprPredictor,
requirements_path=os.path.join(USER_SRC_DIR, "requirements.txt"),
)
Escreva um arquivo de teste com dois exemplos para previsão. Uma das instâncias tem o nome abreviado, mas a outra precisa ser convertida antes.
import json
sample = {"instances": [
[0.23, 'Ideal', 'E', 'VS2', 61.5, 55.0, 3.95, 3.98, 2.43],
[0.29, 'Premium', 'J', 'Internally Flawless', 52.5, 49.0, 4.00, 2.13, 3.11]]}
with open('instances.json', 'w') as fp:
json.dump(sample, fp)
Teste o contêiner localmente implantando um modelo local.
with local_model.deploy_to_local_endpoint(
artifact_uri = 'model_artifacts/', # local path to artifacts
) as local_endpoint:
predict_response = local_endpoint.predict(
request_file='instances.json',
headers={"Content-Type": "application/json"},
)
health_check_response = local_endpoint.run_health_check()
Para conferir os resultados da previsão, use:
predict_response.content
9. Implantar o modelo na Vertex AI
Agora que você testou o contêiner localmente, é hora de enviar a imagem para o Artifact Registry e fazer upload do modelo para o Vertex AI Model Registry.
Primeiro, configure o Docker para acessar o Artifact Registry.
!gcloud artifacts repositories create {REPOSITORY} --repository-format=docker \
--location=us-central1 --description="Docker repository"
!gcloud auth configure-docker {REGION}-docker.pkg.dev --quiet
Em seguida, envie a imagem.
local_model.push_image()
E fazer upload do modelo.
model = aiplatform.Model.upload(local_model = local_model,
display_name=MODEL_DISPLAY_NAME,
artifact_uri=f"{BUCKET_NAME}/{MODEL_ARTIFACT_DIR}",)
Quando o modelo for enviado, ele vai aparecer no console:
Em seguida, implante o modelo para usá-lo nas previsões on-line. As rotinas de previsão personalizadas também funcionam com a previsão em lote. Portanto, se o caso de uso não exigir previsões on-line, não será necessário implantar o modelo.
Em seguida, envie a imagem.
endpoint = model.deploy(machine_type="n1-standard-2")
Por fim, receba uma previsão para testar o modelo implantado.
endpoint.predict(instances=[[0.23, 'Ideal', 'E', 'VS2', 61.5, 55.0, 3.95, 3.98, 2.43]])
Parabéns! 🎉
Você aprendeu a usar a Vertex AI para:
- Escrever uma lógica personalizada de pré e pós-processamento com rotinas de previsão personalizadas
A Cosmopup acha que os codelabs são incríveis!
Qual é a próxima etapa?
Leia mais e Vídeos
- O que é a Vertex AI?
- Como começar a usar a Vertex AI
- Qual solução de IA/ML da Vertex AI é ideal para mim?
- Como criar um sistema de respostas a perguntas com a Vertex AI