Criar scripts de pontuação para implantações em lote

APLICA-SE A:Extensão de ML da CLI do Azure v2 (atual)SDK do Python azure-ai-ml v2 (atual)

Os pontos de extremidade em lote permitem implantar modelos que fazem a inferência de execução longa em escala. Ao implantar modelos, você precisa criar e especificar um script de pontuação (também conhecido como script de driver em lotes) para indicar como precisamos usá-lo nos dados de entrada para criar as previsões. Neste artigo, você aprenderá a usar scripts de pontuação em implantações de modelo para diferentes cenários. Você também conhecerá as melhores práticas para pontos de extremidade em lote.

Dica

Os modelos do MLflow não exigem um script de pontuação. Ele é gerado automaticamente para você. Para saber mais sobre como os pontos de extremidade em lote funcionam com os modelos do MLflow, confira o tutorial sobre o assunto Como usar modelos do MLflow em implantações em lote.

Aviso

Para implantar um modelo de ML automatizado em um ponto de extremidade em lote, observe que o ML automatizado fornece um script de pontuação que funciona apenas para pontos de extremidade online. Esse script de pontuação não foi desenvolvido para a execução em lote. Siga estas diretrizes para obter mais informações sobre como criar um script de pontuação, personalizado para o que o seu modelo faz.

Noções básicas sobre o script de pontuação

O script de pontuação é um arquivo Python (.py) que especifica como executar o modelo e ler os dados de entrada enviados pelo executor da implantação em lote. Cada implantação de modelo fornece o script de pontuação (junto com todas as outras dependências necessárias) no momento da criação. O script de pontuação costuma ter esta aparência:

deployment.yml

code_configuration:
  code: code
  scoring_script: batch_driver.py

O script de pontuação precisa conter dois métodos:

O método init

Use o método init() para qualquer preparação cara ou comum. Por exemplo, use-o para carregar o modelo na memória. O início de todo o trabalho em lotes chama essa função uma vez. Os arquivos do modelo estão disponíveis em um caminho determinado pela variável de ambiente AZUREML_MODEL_DIR. Dependendo de como seu modelo foi registrado, os arquivos podem estar contidos em uma pasta. No próximo exemplo, o modelo tem vários arquivos em uma pasta chamada model. Para obter mais informações, acesse Como você pode determinar a pasta que o modelo usa.

def init():
    global model

    # AZUREML_MODEL_DIR is an environment variable created during deployment
    # The path "model" is the name of the registered model's folder
    model_path = os.path.join(os.environ["AZUREML_MODEL_DIR"], "model")

    # load the model
    model = load_model(model_path)

Neste exemplo, colocamos o modelo na variável global model. Para disponibilizar os ativos necessários para executar a inferência na função de pontuação, use variáveis globais.

O método run

Use o método run(mini_batch: List[str]) -> Union[List[Any], pandas.DataFrame] para tratar a pontuação de cada minilote gerado pela implantação em lote. Esse método é chamado uma vez para cada mini_batch gerado para os dados de entrada. As implantações em lote leem os dados em lotes de acordo com a configuração da implantação.

import pandas as pd
from typing import List, Any, Union

def run(mini_batch: List[str]) -> Union[List[Any], pd.DataFrame]:
    results = []

    for file in mini_batch:
        (...)

    return pd.DataFrame(results)

O método recebe uma lista de caminhos de arquivo como um parâmetro (mini_batch). Você pode usar essa lista para iterar em cada arquivo e processá-lo individualmente ou ler todo o lote e processá-lo de uma só vez. A melhor opção dependerá da memória de computação e da taxa de transferência que você precisa alcançar. Para ver um exemplo que descreve como ler lotes inteiros de dados de uma só vez, acesse Implantações de alta taxa de transferência.

Observação

Como o trabalho é distribuído?

As implantações em lote distribuem o trabalho no nível do arquivo, o que significa que uma pasta que contém 100 arquivos com minilotes de 10 arquivos vai gerar 10 lotes de 10 arquivos cada um. Observe que os tamanhos dos arquivos relevantes não têm importância. Para arquivos grandes demais para serem processados em minilotes grandes, sugerimos que você divida os arquivos em arquivos menores para ter um nível mais alto de paralelismo ou diminua o número de arquivos por minilote. No momento, a implantação em lote não pode considerar distorções na distribuição de tamanho do arquivo.

O método run() retornará um DataFrame do Pandas ou uma matriz/lista. Cada elemento de saída retornado indica uma execução bem-sucedida de um elemento de entrada na entrada mini_batch. No caso de ativos de dados de arquivo ou pasta, cada linha/elemento retornado representa um arquivo individual processado. No caso de um ativo de dados de tabela, cada linha/elemento retornado representa uma linha em um arquivo processado.

Importante

Como escrever previsões?

Tudo o que a função run() retornará será acrescentado ao arquivo de previsões de saída gerado pelo trabalho em lote. É importante retornar o tipo de dados correto dessa função. Retorne matrizes quando precisar gerar uma única previsão. Retorne DataFrames do Pandas quando precisar retornar várias informações. Por exemplo, para dados de tabela, o ideal é acrescentar suas previsões ao registro original. Use um DataFrame do Pandas para fazer isso. Embora um DataFrame do Pandas possa conter nomes de colunas, o arquivo de saída não inclui esses nomes.

Para escrever previsões de uma forma diferente, personalize as saídas em implantações em lote.

Aviso

Na função run, não gere tipos de dados complexos (ou listas de tipos de dados complexos) em vez de pandas.DataFrame. Essas saídas serão transformadas em cadeia de caracteres e ficarão difíceis de ler.

O DataFrame ou a matriz resultante é acrescentado ao arquivo de saída indicado. Não há nenhum requisito sobre a cardinalidade dos resultados. Um arquivo pode gerar uma ou várias linhas/elementos na saída. Todos os elementos no DataFrame ou matriz de resultados serão gravados no arquivo de saída no estado em que se encontram (desde que output_action não seja summary_only).

Pacotes do Python para pontuação

É preciso indicar qualquer biblioteca que o script de pontuação exija para ser executado no ambiente em que a implantação em lote é executada. Quanto aos scripts de pontuação, os ambientes são indicados por implantação. Normalmente, você indica seus requisitos usando um arquivo de dependências conda.yml, que pode ter a seguinte aparência:

mnist/environment/conda.yaml

name: mnist-env
channels:
  - conda-forge
dependencies:
  - python=3.8.5
  - pip<22.0
  - pip:
    - torch==1.13.0
    - torchvision==0.14.0
    - pytorch-lightning
    - pandas
    - azureml-core
    - azureml-dataset-runtime[fuse]

Acesse Criar uma implantação em lote para obter mais informações sobre como indicar o ambiente para seu modelo.

Gravar previsões de uma maneira diferente

Por padrão, a implantação em lote grava as previsões do modelo em um arquivo, conforme indicado na implantação. No entanto, em alguns casos, você precisa escrever as previsões em vários arquivos. Por exemplo, para dados de entrada particionados, provavelmente, o ideal também é gerar uma saída particionada. Nesses casos, é possível Personalizar as saídas nas implantações em lote para indicar:

  • O formato de arquivo (CSV, Parquet, JSON etc.) usado para escrever as previsões
  • A maneira como os dados são particionados na saída

Acesse Personalizar as saídas nas implantações em lote para obter mais informações sobre como fazer isso.

Controle do código-fonte dos scripts de pontuação

É altamente recomendável colocar os scripts de pontuação sob o controle do código-fonte.

Melhores práticas para gravar scripts de pontuação

Ao gravar scripts de pontuação que funcionam com grandes volumes de dados, você precisa considerar vários fatores, incluindo

  • O tamanho de cada arquivo
  • O volume de dados em cada arquivo
  • A quantidade de memória necessária para ler cada arquivo
  • A quantidade de memória necessária para ler um lote inteiro de arquivos
  • O volume de memória do modelo
  • O volume de memória do modelo durante a execução nos dados de entrada
  • A memória disponível na computação

As implantações em lote distribuem o trabalho no nível do arquivo. Isso significa que uma pasta que contém 100 arquivos, em minilotes de dez arquivos, gera dez lotes de dez arquivos cada um (independentemente do tamanho dos arquivos envolvidos). Para arquivos grandes demais para serem processados em minilotes grandes, sugerimos que você divida os arquivos em arquivos menores para ter um nível mais alto de paralelismo ou diminua o número de arquivos por minilote. No momento, a implantação em lote não pode considerar distorções na distribuição de tamanho do arquivo.

Relação entre o grau de paralelismo e o script de pontuação

A configuração de implantação controla o tamanho de cada minilote e o número de trabalhos em cada nó. Isso passa a ser importante quando você decide se deve ou não ler todo o minilote para executar a inferência, executar o arquivo de inferência por arquivo ou executar a linha de inferência por linha (para tabela). Acesse Como executar a inferência no nível do minilote, do arquivo ou da linha para obter mais informações.

Ao executar vários trabalhos na mesma instância, leve em consideração que a memória é compartilhada entre todos os trabalhos. Um aumento do número de trabalhos por nó deve ser geralmente acompanhado por uma diminuição no tamanho do minilote ou por uma alteração na estratégia de pontuação, caso o tamanho dos dados e o SKU de computação continuem os mesmos.

Executar inferência no minilote, arquivo ou nível de linha

Os pontos de extremidade em lote chamam a função run() em um script de pontuação uma vez por minilote. No entanto, você pode decidir se deseja executar a inferência em todo o lote, mais de um arquivo por vez ou mais de uma linha por vez para dados de tabela.

Nível de minilote

Normalmente, o ideal é executar a inferência no lote de uma só vez para obter uma alta taxa de transferência no processo de pontuação em lote. Isso ocorre se você executar a inferência em uma GPU na qual deseja obter a saturação do dispositivo de inferência. Você também pode contar com um carregador de dados que pode lidar com o envio em lote se os dados não se ajustarem à memória, como os carregadores de dados TensorFlow ou PyTorch. Nesses casos, o ideal é executar a inferência em todo o lote.

Aviso

Executar a inferência no nível do lote pode exigir um controle rígido sobre o tamanho dos dados de entrada para levar em conta corretamente os requisitos de memória e evitar exceções de memória insuficiente. A capacidade ou não de carregar todo o minilote na memória dependerá do tamanho do minilote, do tamanho das instâncias no cluster, do número de trabalhos em cada nó e do tamanho do minilote.

Acesse Implantações de alta taxa de transferência para saber como fazer isso. Este exemplo processa um lote inteiro de arquivos por vez.

Nível de arquivo

Uma das formas mais fáceis de executar a inferência é iterando sobre todos os arquivos no minilote e executando o modelo neles. Em alguns casos, por exemplo, o processamento de imagens, essa pode ser uma boa ideia. Para dados de tabela, talvez seja necessário fazer uma boa estimativa sobre o número de linhas de cada arquivo. Essa estimativa pode mostrar se o modelo pode ou não lidar com os requisitos de memória para carregar os dados inteiros na memória e executar a inferência neles. Alguns modelos (especialmente esses modelos baseados em redes neurais recorrentes) se desdobram e apresentam um volume de memória com uma contagem de linhas potencialmente não linear. No caso de um modelo com alta despesa de memória, considere a execução da inferência no nível da linha.

Dica

Considere a divisão de arquivos muito grandes para serem lidos de uma só vez em vários arquivos menores, a fim de gerar uma melhor paralelização.

Acesse Processamento de imagens com implantações em lote para saber como fazer isso. Esse exemplo processa um arquivo de cada vez.

Nível de linha (tabular)

Para os modelos que apresentam desafios com tamanhos de entrada, o ideal é executar a inferência no nível da linha. Sua implantação em lote ainda fornece o script de pontuação com um minilote de arquivos. No entanto, você lerá um arquivo, uma linha de cada vez. Isso pode parecer ineficiente, mas para alguns modelos de aprendizado profundo, essa pode ser a única maneira de executar a inferência sem aumentar seus recursos de hardware.

Acesse Processamento de texto com implantações em lote para saber como fazer isso. Esse exemplo processa uma linha de cada vez.

Usar modelos que são pastas

A variável de ambiente AZUREML_MODEL_DIR contém o caminho para o local do modelo selecionado e a função init() normalmente a usa para carregar o modelo na memória. No entanto, alguns modelos pode conter os arquivos em uma pasta e talvez seja necessário considerar isso ao carregá-los. Você pode identificar a estrutura de pasta do seu modelo, conforme mostrado:

  1. Acesse Portal de Interface do usuário do Azure Machine Learning.

  2. Vá para a seção Modelos.

  3. Selecione o modelo que deseja implantar e escolha a guia Artefatos.

  4. Anote a pasta exibida. Essa pasta foi indicada quando o modelo foi registrado.

    Captura de tela mostrando a pasta em que os artefatos do modelo são colocados.

Use este caminho para carregar o modelo:

def init():
    global model

    # AZUREML_MODEL_DIR is an environment variable created during deployment
    # The path "model" is the name of the registered model's folder
    model_path = os.path.join(os.environ["AZUREML_MODEL_DIR"], "model")

    model = load_model(model_path)

Próximas etapas