Como exibir modelos de ML do Spark usando a Vertex AI

Last reviewed 2023-07-11 UTC

Os cientistas de dados e os engenheiros de machine learning (ML) geralmente precisam de uma arquitetura de exibição rápida o suficiente para atender às necessidades de geração de previsões on-line (ou em tempo real) com base em modelos de ML. A Vertex AI atende a essa necessidade.

Com a Vertex AI, é possível exibir modelos de uma variedade de frameworks de ML. No caso de bibliotecas como TensorFlow, PyTorch, XGBoost e scikit-learn, a Vertex AI fornece contêineres predefinidos para executar esses modelos de ML. Se você ainda não estiver usando nenhum desses frameworks de ML, precisará criar seu próprio contêiner personalizado para uso pela Vertex AI.

Este documento é destinado aos usuários que precisam criar um contêiner personalizado para exibir os modelos de ML do Spark. Nele, está incluída uma descrição da arquitetura de exibição necessária para contêineres personalizados e uma implementação de referência que a demonstra com relação a um modelo MLib do Spark.

Para aproveitar ao máximo a parte da implementação de referência deste documento, você deve estar familiarizado com a exportação de modelos MLlib do Spark para o formato MLeap, entender como usar a Vertex AI para exibir previsões e ter experiência com o uso de imagens de contêiner.

Arquitetura

Os contêineres predefinidos estão disponíveis para alguns frameworks de ML, mas os usuários de outros frameworks de ML, como o Spark, precisam criar contêineres personalizados em que a Vertex AI possa executar previsões. O diagrama a seguir ilustra a arquitetura de exibição necessária para disponibilizar os modelos MLib do Spark e outros modelos que exigem um contêiner personalizado:

A arquitetura de exibição do modelo usada no documento.

Essa arquitetura inclui os seguintes componentes:

  • Cloud Storage: fornece armazenamento para os artefatos do modelo necessários para executar o modelo. Para o modelo de ML do Spark usado na implementação de referência, os artefatos do modelo consistem em um pacote MLap e um esquema de modelo.
  • Cloud Build: usa a imagem do builder para criar uma imagem de contêiner personalizada chamada imagem de contêiner de exibição. O processo de build compila e empacota o código de exibição do modelo, cria a imagem de contêiner de exibição e a envia ao Artifact Registry.
  • Artifact Registry: contém os seguintes objetos:
    • A imagem de contêiner do builder scala-sbt que o Cloud Build usa para criar a imagem do contêiner de exibição.
    • A imagem do contêiner de exibição criada pelo Cloud Build.
  • Vertex AI: contém o modelo de ML que foi carregado do Cloud Storage. Esse modelo é configurado com o local dos artefatos do modelo no Cloud Storage e o local da imagem do contêiner de exibição no Artifact Registry. A Vertex AI também inclui um endpoint em que o modelo foi implantado. Quando o modelo é implantado no endpoint, a Vertex AI associa a ele recursos físicos, a fim de que ele possa exibir previsões on-line.

Como parte da implementação dessa arquitetura de exibição, você precisa exportar seu modelo de ML para uso por outros aplicativos e definir sua própria imagem de contêiner de exibição. A implementação de referência fornecida neste documento mostra o código usado para definir e criar a imagem do contêiner de exibição. Esse código também inclui os artefatos de um modelo de ML do Spark exportado anteriormente. Com algumas alterações de configuração, é possível usar essa implementação de referência para exibir seus próprios modelos de ML do Spark.

No entanto, também é possível implementar essa arquitetura de exibição por conta própria e não usar a implementação de referência. Se você decidir implementar sua própria arquitetura, será necessário fazer o seguinte:

  • Exporte o modelo para que ele possa ser usado por outros aplicativos. Esse processo depende dos frameworks de ML e das ferramentas que você está usando. Por exemplo, é possível exportar os modelos MLlib do Spark criando um pacote MLeap, conforme descrito na implementação de referência. Confira outros exemplos de como exportar modelos em Exportar artefatos de modelo para previsão.
  • Projete a imagem do contêiner de exibição para atender aos requisitos de contêiner personalizado que a tornam compatível com a Vertex AI. O código pode estar em sua linguagem de programação preferencial.
  • Empacote o código em um formato de arquivo de pacote compatível com a linguagem de programação usada. Por exemplo, é possível usar um arquivo JAR para códigos em Java ou um Python Wheel para códigos em Python.
  • Crie uma imagem de contêiner personalizado capaz de exibir o código do modo personalizado.

Implementação de referência

A implementação de referência a seguir exibe um modelo MLib do Spark que prevê a espécie de íris com base no comprimento e na largura das sépalas e das pétalas da flor.

É possível conferir o modelo usado nesta implementação no diretório example_model do repositório vertex-ai-spark-ml-serving.git. O diretório contém os artefatos de modelo usados pelo contêiner de exibição para executar previsões e inclui os seguintes arquivos:

  • O arquivo example_model/model.zip é um modelo de regressão logística criado com o Spark MLlib, treinado com o conjunto de dados Iris e convertido em um pacote do MLeap. O modelo prevê as espécies de uma flor de íris usando o comprimento e as larguras das sépalas e pétalas da flor.
  • O example_model/schema.json é um arquivo JSON que descreve o esquema do modelo. O esquema do modelo descreve os campos de entrada esperados para as instâncias de previsão e os campos de saída para os resultados de previsão necessários para o esquema do MLeap.

Usar seu próprio modelo Mlib

Para usar seu próprio modelo com essa implementação de referência, primeiro verifique se o modelo MLlib do Spark foi exportado para um pacote MLeap. Em seguida, para exibir o modelo MLib do Spark, é preciso fornecer os artefatos de modelo apropriados: o pacote MLeap e o esquema do modelo.

Pacote MLeap

O contêiner de exibição determina o local do pacote do MLeap usando a variável de ambiente AIP_STORAGE_URI que é transmitida da Vertex AI para o contêiner na inicialização. O valor da variável AIP_STORAGE_URI é especificado quando você faz upload do modelo para a Vertex AI.

Esquema do modelo

O esquema do modelo descreve os recursos de entrada e a saída de previsões de um modelo. O esquema do modelo é representado por dados JSON. Confira a seguir o esquema usado nesta implementação de referência para prever a espécie da íris com base no comprimento e na largura das sépalas e das pétalas da flor:

{
  "input": [
    {
      "name": "sepal_length",
      "type": "FLOAT"
    },
    {
      "name": "sepal_width",
      "type": "FLOAT"
    },
    {
      "name": "petal_length",
      "type": "FLOAT"
    },
    {
      "name": "petal_width",
      "type": "FLOAT"
    }
  ],
  "output": [
    {
      "name": "probability",
      "type": "DOUBLE",
      "struct": "VECTOR"
    }
  ]
}

No esquema do modelo, a matriz input contém os campos de entrada (colunas) do modelo, enquanto a matriz output contém os campos de saída (colunas) a serem retornados do modelo. Em ambas as matrizes, cada objeto da matriz contém as seguintes propriedades:

  • name: o nome do campo (coluna).
  • type: o tipo de campo (coluna). Os tipos válidos incluem BOOLEAN, BYTE, DOUBLE, FLOAT, INTEGER, LONG, SHORT e STRING.
  • struct (opcional): a estrutura do campo, como escalar ou matriz. As estruturas válidas incluem BASIC (tipo escalar), ARRAY (Spark Array) e VECTOR (Spark DenseVector). BASIC será usado se o campo struct não estiver presente.

Para transmitir o esquema do modelo para o contêiner de exibição, use um dos seguintes métodos:

  • Especifique os dados JSON que definem o esquema na variável de ambiente MLEAP_SCHEMA. A variável de ambiente MLEAP_SCHEMA precisa conter os dados JSON em si, e não um caminho para um arquivo contendo o esquema JSON.
  • Armazene os dados JSON em um arquivo chamado schema.json e disponibilize esse arquivo no contêiner em ${AIP_STORAGE_URI}/schema.json. Esse é o método usado para o modelo MLib de exemplo fornecido nesta documentação.

Se você usar os dois métodos para transmitir o esquema do modelo para o contêiner de exibição, os dados JSON armazenados na variável de ambiente MLEAP_SCHEMA terão precedência.

Custos

Esta implementação de referência usa os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços.

Ao concluir esta implementação de referência, exclua os recursos criados para evitar o faturamento contínuo. Saiba mais em Limpeza.

Antes de começar

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. Verifique se a cobrança está ativada para o seu projeto do Google Cloud.

  3. Enable the Vertex AI, Cloud Build, Cloud Storage, and Artifact Registry APIs.

    Enable the APIs

  4. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

  5. Encontre o ID do projeto e configure-o no Cloud Shell.
    export PROJECT_ID=YOUR_PROJECT_ID
    gcloud config set project ${PROJECT_ID}
    

    Substitua YOUR_PROJECT_ID pela ID do seu projeto.

Criar a imagem do builder scala-sbt

Use o Cloud Build com o builder de comunidades scala-sbt para criar a imagem do contêiner de exibição. Esse processo de compilação exige a imagem do builder sbt-scala no Container Registry do seu projeto.

  1. No Cloud Shell, clone o repositório cloud-builders-community:

    git clone https://github.com/GoogleCloudPlatform/cloud-builders-community.git
    
  2. Acesse o diretório do projeto:

    cd cloud-builders-community/scala-sbt
    
  3. Crie a imagem do builder scala-sbt e envie-a para o Container Registry:

    gcloud builds submit .
    

Criar a imagem do contêiner de exibição

A Vertex AI usa o contêiner de exibição para executar solicitações de previsão para o modelo de exemplo. A primeira etapa na criação da imagem do contêiner de exibição é criar um repositório do Docker no Artifact Registry para armazenar a imagem. Em seguida, você precisa conceder à Vertex AI permissão para extrair a imagem do contêiner de exibição do repositório. Depois de criar o repositório e conceder as permissões, é possível criar a imagem do contêiner de exibição e enviar a imagem para o Artifact Registry.

  1. No Cloud Shell, crie um repositório do Docker no Artifact Registry:

    REPOSITORY="vertex-ai-prediction"
    LOCATION="us-central1"
    
    gcloud artifacts repositories create $REPOSITORY \
        --repository-format=docker \
        --location=$LOCATION
    
  2. Conceda o papel Leitor do Artifact Registry ao agente de serviço da Vertex AI:

    PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
        --format="value(projectNumber)")
    SERVICE_ACCOUNT="service-$PROJECT_NUMBER@gcp-sa-aiplatform.iam.gserviceaccount.com"
    
    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member="serviceAccount:$SERVICE_ACCOUNT" \
        --role="roles/artifactregistry.reader"
    
  3. Clone o repositório spark-ml-serving:

    git clone https://github.com/GoogleCloudPlatform/vertex-ai-spark-ml-serving.git
    
  4. Acesse o diretório do projeto:

    cd vertex-ai-spark-ml-serving
    
  5. Crie a imagem do contêiner de exibição no projeto:

    IMAGE=spark-ml-serving
    
    gcloud builds submit --config=cloudbuild.yaml \
        --substitutions="_LOCATION=$LOCATION,_REPOSITORY=$REPOSITORY,_IMAGE=$IMAGE" .
    

    O arquivo cloudbuild.yaml especifica dois builders: o builder scala-sbt e o builder de imagem docker. O Cloud Build usa o builder scala-sbt para compilar o código de exibição do modelo do Cloud Storage e empacotar o código compilado em um arquivo JAR executável. O Cloud Build usa o builder docker para criar a imagem do contêiner de exibição que contém o arquivo JAR. Depois que a imagem do contêiner de exibição é criada, a imagem é enviada para o Artifact Registry.

Importar o modelo para a Vertex AI

O contêiner de exibição lê os artefatos de modelo do Cloud Storage. É preciso criar um local de armazenamento para esses artefatos antes de importar o modelo para a Vertex AI. Ao importar o modelo, você precisa do local de armazenamento dos artefatos do modelo e da imagem do contêiner de exibição no Artifact Registry.

  1. No Cloud Shell, crie um bucket para os artefatos do modelo:

    REGION="us-central1"
    BUCKET="YOUR_BUCKET_NAME"
    gcloud storage buckets create gs://$BUCKET --location=$REGION
    

    Substitua YOUR_BUCKET_NAME pelo nome do bucket.

  2. Copie os artefatos do modelo no bucket:

    gcloud storage cp example_model/* gs://$BUCKET/example_model/
    
  3. Importe o modelo para a Vertex AI:

    DISPLAY_NAME="iris-$(date +'%Y%m%d%H%M%S')"
    IMAGE_URI="${LOCATION}-docker.pkg.dev/$PROJECT_ID/${REPOSITORY}/${IMAGE}"
    ARTIFACT_URI="gs://$BUCKET/example_model/"
    
    gcloud ai models upload \
        --region=$REGION \
        --display-name=$DISPLAY_NAME \
        --container-image-uri=$IMAGE_URI \
        --artifact-uri=$ARTIFACT_URI \
        --container-health-route="/health" \
        --container-predict-route="/predict"
    

    No comando gcloud ai models upload, o valor do parâmetro --artifact-uri especifica o valor da variável AIP_STORAGE_URI. Essa variável fornece o local do pacote do MLeap que está sendo importado para a Vertex AI.

Implantar o modelo em um novo endpoint

Para que a Vertex AI execute previsões, o modelo importado precisa ser implantado em um endpoint. Ao implantar o modelo, você precisa dos IDs do endpoint e do modelo.

  1. No Cloud Shell, crie o endpoint do modelo:

    gcloud ai endpoints create \
        --region=$REGION \
        --display-name=$DISPLAY_NAME
    

    A ferramenta de linha de comando gcloud pode levar alguns segundos para criar o endpoint.

  2. Consiga o ID do endpoint recém-criado:

    ENDPOINT_ID=$(gcloud ai endpoints list \
        --region=$REGION \
        --filter=display_name=$DISPLAY_NAME \
        --format='value(name)')
    
    # Print ENDPOINT_ID to the console
    echo "Your endpoint ID is: $ENDPOINT_ID"
    
  3. Consiga o ID do modelo importado na seção Importar o modelo para a Vertex AI:

    MODEL_ID=$(gcloud ai models list \
        --region=$REGION \
        --filter=display_name=$DISPLAY_NAME \
        --format='value(name)')
    
    # Print MODEL_ID to the console
    echo "Your model ID is: $MODEL_ID"
    
  4. Implante o modelo no endpoint:

    gcloud ai endpoints deploy-model $ENDPOINT_ID \
        --region=$REGION \
        --model=$MODEL_ID \
        --display-name=$DISPLAY_NAME \
        --traffic-split="0=100"
    

    O comando do gcloud implanta o modelo no endpoint. Os valores padrão são usados para o tipo de recurso da máquina, os números mínimo e máximo de nós e outras opções de configuração. Saiba mais sobre as opções de implantação de modelos na documentação da Vertex AI.

Testar o endpoint

Depois de implantar o modelo no endpoint, é possível testar a implementação. Para testar o endpoint, use o cliente de exemplo incluído no código da implementação de referência. O cliente de exemplo gera instâncias de previsão e envia solicitações de previsão ao endpoint. Cada instância de previsão contém valores aleatórios para sepal_length, sepal_width, petal_length e petal_width. Por padrão, o cliente de exemplo combina várias instâncias de previsão em uma única solicitação. A resposta do endpoint inclui uma previsão para cada instância que é enviada na solicitação. A previsão contém as probabilidades de cada classe no conjunto de dados Íris (setosa, versicolor e virginica).

  • No Cloud Shell, execute o exemplo de cliente de previsão:

    cd example_client
    ./run_client.sh --project $PROJECT_ID \
        --location $LOCATION \
        --endpoint $ENDPOINT_ID
    

    Quando você executa o script pela primeira vez, ele cria um ambiente virtual do Python e instala dependências. Depois de instalar as dependências, o script executa o cliente de exemplo. Para cada solicitação, o cliente imprime as instâncias de previsão e as probabilidades de classe correspondentes no terminal. Veja a seguir um trecho da saída:

    Sending 10 asynchronous prediction requests with 3 instances per request ...
    
    ==> Response from request #10:
    
    Instance 1:     sepal_length:   5.925825137450266
                    sepal_width:    4.5047557888651
                    petal_length:   1.0432434310300223
                    petal_width:    0.5050397721287457
    
    Prediction 1:   setosa:         0.2036041134824573
                    versicolor:     0.6062980065549213
                    virginica:      0.1900978799626214
    
    Instance 2:     sepal_length:   6.121228622484405
                    sepal_width:    3.406317728235072
                    petal_length:   3.178583759980504
                    petal_width:    2.815141143581328
    
    Prediction 2:   setosa:         0.471811302254083
                    versicolor:     0.2063720436033448
                    virginica:      0.3218166541425723
    
    Instance 3:     sepal_length:   7.005781590327274
                    sepal_width:    2.532116893508745
                    petal_length:   2.6351337947193474
                    petal_width:    2.270855223519198
    
    Prediction 3:   setosa:         0.453579051699638
                    versicolor:     0.2132869980698818
                    virginica:      0.3331339502304803
    

Limpar

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados na implementação de referência, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.

Excluir o projeto

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Excluir recursos individuais

  1. No Cloud Shell, cancele a implantação do modelo no endpoint:

    DEPLOYED_MODEL_ID=$(gcloud ai endpoints describe $ENDPOINT_ID \
        --region=$REGION \
        --format='value(deployedModels.id)')
    
    gcloud ai endpoints undeploy-model $ENDPOINT_ID \
        --region=$REGION \
        --deployed-model-id=$DEPLOYED_MODEL_ID
    
  2. Exclua o endpoint:

    gcloud ai endpoints delete $ENDPOINT_ID \
        --region=$REGION \
        --quiet
    
  3. Exclua o modelo:

    gcloud ai models delete $MODEL_ID \
        --region=$REGION
    
  4. Exclua a imagem do contêiner de exibição:

    gcloud artifacts docker images delete \
        $LOCATION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$IMAGE \
        --delete-tags \
        --quiet
    
  5. Exclua o contêiner do builder scala-sbt:

    gcloud container images delete gcr.io/$PROJECT_ID/scala-sbt \
        --force-delete-tags \
        --quiet
    
  6. Exclua todos os buckets do Cloud Storage que não são mais necessários:

    gcloud storage rm YOUR_BUCKET_NAME --recursive
    

    A exclusão de um bucket também exclui todos os objetos armazenados nele. Depois da exclusão, não é possível recuperar os buckets e objetos.

A seguir