Rotinas de previsão personalizadas

As rotinas de previsão personalizadas permitem determinar qual código é executado quando você envia uma solicitação de previsão on-line para o AI Platform Prediction.

Quando você implanta um recurso de versão no AI Platform Prediction sem usar uma rotina de previsão personalizada, ele manipula as solicitações de previsão por meio da execução da operação de previsão do framework de machine learning usado para treinamento.

Porém, ao implantar uma rotina de previsão personalizada como recurso de versão, você instrui o AI Platform Prediction a executar um código Python personalizado em resposta a cada solicitação de previsão que ele recebe. É possível processar a entrada de previsão antes que o modelo treinado a execute ou processar a previsão do modelo posteriormente, antes de enviar o resultado dela.

Para criar uma rotina de previsão personalizada, inclua dois elementos no AI Platform Prediction ao criar a versão do modelo:

  • Um diretório de modelo no Cloud Storage, que contém todos os artefatos que precisam ser usados na previsão.

  • Um pacote de distribuição de origem .tar.gz do Python no Cloud Storage contendo a implementação da interface do Predictor e qualquer outro código personalizado que você queira que o AI Platform Prediction use no momento da previsão.

Só é possível implantar uma rotina de predição personalizada quando você usa um tipo de máquina legado (MLS1) para a versão do modelo.

Fazer upload de artefatos de modelo no diretório

Siga o guia de implantação de modelos para fazer upload do modelo treinado para o Cloud Storage, com quaisquer outros arquivos que incluam dados ou informações de estado para o AI Platform Prediction usar durante a previsão.

O tamanho total do arquivo dos artefatos do modelo que você implementa na previsão do AI Platform precisa ser de 500 MB ou menos.

É possível fazer o upload do seu modelo de machine learning treinado para o diretório como um SavedModel do TensorFlow, um arquivo model.joblib, um arquivo model.pkl ou um arquivo model.bst. Também é possível fornecer o modelo como um arquivo HDF5 contendo um modelo tf.keras treinado (em inglês) ou em um formato serializado diferente.

Além disso, é possível incluir um arquivo pickle com uma instância de classe de pré-processador personalizada que contém o estado serializado do treinamento.

Por exemplo, considere o pré-processador a seguir, definido no arquivo chamado preprocess.py:

import numpy as np

class ZeroCenterer(object):
    """Stores means of each column of a matrix and uses them for preprocessing."""

    def __init__(self):
        """On initialization, is not tied to any distribution."""
        self._means = None

    def preprocess(self, data):
        """Transforms a matrix.

        The first time this is called, it stores the means of each column of
        the input. Then it transforms the input so each column has mean 0. For
        subsequent calls, it subtracts the stored means from each column. This
        lets you 'center' data at prediction time based on the distribution of
        the original training data.

        Args:
            data: A NumPy matrix of numerical data.

        Returns:
            A transformed matrix with the same dimensions as the input.
        """
        if self._means is None:  # during training only
            self._means = np.mean(data, axis=0)
        return data - self._means

Durante o treinamento em um conjunto de dados numérico, o pré-processador centraliza os dados em torno de 0, subtraindo a média de cada coluna de todos os valores dela. Em seguida, é possível exportar a instância do pré-processador como um arquivo pickle, preprocessor.pkl, que preserva as médias de cada coluna calculadas a partir dos dados de treinamento.

Durante a previsão, uma rotina personalizada pode carregar o pré-processador desse arquivo para executar uma transformação idêntica com base na entrada da previsão.

Para saber como usar um pré-processador com estado como esse na rotina de predição personalizada, leia a próxima seção, que descreve como implementar a interface do Predictor.

Para praticar com um exemplo completo do uso de pré-processador com estado durante o treinamento e a previsão, leia Como criar uma rotina de previsão personalizada com o Keras ou Como criar uma rotina de previsão personalizada com o scikit-learn.

Criar o Predictor

Forneça uma classe do Predictor para informar ao AI Platform Prediction como lidar com solicitações de previsão. Essa classe implementa a interface abaixo:

class Predictor(object):
    """Interface for constructing custom predictors."""

    def predict(self, instances, **kwargs):
        """Performs custom prediction.

        Instances are the decoded values from the request. They have already
        been deserialized from JSON.

        Args:
            instances: A list of prediction input instances.
            **kwargs: A dictionary of keyword args provided as additional
                fields on the predict request body.

        Returns:
            A list of outputs containing the prediction results. This list must
            be JSON serializable.
        """
        raise NotImplementedError()

    @classmethod
    def from_path(cls, model_dir):
        """Creates an instance of Predictor using the given path.

        Loading of the predictor should be done in this method.

        Args:
            model_dir: The local directory that contains the exported model
                file along with any additional files uploaded when creating the
                version resource.

        Returns:
            An instance implementing this Predictor class.
        """
        raise NotImplementedError()

Os nós de previsão do AI Platform Prediction usam o método da classe from_path para carregar uma instância do Predictor. Esse método precisa carregar os artefatos salvos no diretório de modelo de onde o conteúdo é copiado do Cloud Storage para um local especificado pelo argumento model_dir.

Sempre que a implantação recebe uma solicitação de previsão on-line, a instância da classe do Predictor retornada por from_path usa o método predict para gerar previsões. O AI Platform Prediction serializa o valor de retorno desse método para JSON e o envia como a resposta à solicitação de previsão.

Observe que o método predict não precisa converter a entrada do JSON em objetos Python nem converter a saída em JSON. O AI Platform Prediction lida com isso fora do método predict.

O AI Platform Prediction fornece o argumento instances analisando o campo instances do corpo da solicitação predict para a API AI Platform Training and Prediction. Ele analisa outros campos do corpo da solicitação e os fornece ao método predict como entradas no dicionário **kwargs. Para saber mais, leia sobre como estruturar uma solicitação predict na API AI Platform Training and Prediction.

Continuando o exemplo da seção anterior, suponha que o diretório do modelo contenha preprocessor.pkl (a instância em pickled da classe ZeroCenterer) e um modelo tf.keras treinado exportado como model.h5 ou um modelo scikit-learn treinado exportado como model.joblib.

Dependendo do framework de machine learning usado, implemente uma das classes do Predictor em um arquivo chamado predictor.py:

TensorFlow

import os
import pickle

import numpy as np
from tensorflow import keras

class MyPredictor(object):
    """An example Predictor for an AI Platform custom prediction routine."""

    def __init__(self, model, preprocessor):
        """Stores artifacts for prediction. Only initialized via `from_path`."""
        self._model = model
        self._preprocessor = preprocessor

    def predict(self, instances, **kwargs):
        """Performs custom prediction.

        Preprocesses inputs, then performs prediction using the trained Keras
        model.

        Args:
            instances: A list of prediction input instances.
            **kwargs: A dictionary of keyword args provided as additional
                fields on the predict request body.

        Returns:
            A list of outputs containing the prediction results.
        """
        inputs = np.asarray(instances)
        preprocessed_inputs = self._preprocessor.preprocess(inputs)
        outputs = self._model.predict(preprocessed_inputs)
        return outputs.tolist()

    @classmethod
    def from_path(cls, model_dir):
        """Creates an instance of MyPredictor using the given path.

        This loads artifacts that have been copied from your model directory in
        Cloud Storage. MyPredictor uses them during prediction.

        Args:
            model_dir: The local directory that contains the trained Keras
                model and the pickled preprocessor instance. These are copied
                from the Cloud Storage model directory you provide when you
                deploy a version resource.

        Returns:
            An instance of `MyPredictor`.
        """
        model_path = os.path.join(model_dir, "model.h5")
        model = keras.models.load_model(model_path)

        preprocessor_path = os.path.join(model_dir, "preprocessor.pkl")
        with open(preprocessor_path, "rb") as f:
            preprocessor = pickle.load(f)

        return cls(model, preprocessor)

scikit-learn

import os
import pickle

import numpy as np
from sklearn.externals import joblib

class MyPredictor(object):
    """An example Predictor for an AI Platform custom prediction routine."""

    def __init__(self, model, preprocessor):
        """Stores artifacts for prediction. Only initialized via `from_path`."""
        self._model = model
        self._preprocessor = preprocessor

    def predict(self, instances, **kwargs):
        """Performs custom prediction.

        Preprocesses inputs, then performs prediction using the trained
        scikit-learn model.

        Args:
            instances: A list of prediction input instances.
            **kwargs: A dictionary of keyword args provided as additional
                fields on the predict request body.

        Returns:
            A list of outputs containing the prediction results.
        """
        inputs = np.asarray(instances)
        preprocessed_inputs = self._preprocessor.preprocess(inputs)
        outputs = self._model.predict(preprocessed_inputs)
        return outputs.tolist()

    @classmethod
    def from_path(cls, model_dir):
        """Creates an instance of MyPredictor using the given path.

        This loads artifacts that have been copied from your model directory in
        Cloud Storage. MyPredictor uses them during prediction.

        Args:
            model_dir: The local directory that contains the trained
                scikit-learn model and the pickled preprocessor instance. These
                are copied from the Cloud Storage model directory you provide
                when you deploy a version resource.

        Returns:
            An instance of `MyPredictor`.
        """
        model_path = os.path.join(model_dir, "model.joblib")
        model = joblib.load(model_path)

        preprocessor_path = os.path.join(model_dir, "preprocessor.pkl")
        with open(preprocessor_path, "rb") as f:
            preprocessor = pickle.load(f)

        return cls(model, preprocessor)

O método predict converte os resultados da previsão em uma lista com o método tolist antes de retorná-los. As matrizes NumPy não são serializáveis por JSON. Portanto, converta-as em listas de números (que são serializáveis por JSON). Caso contrário, o AI Platform Prediction não enviará a resposta da previsão.

Empacotar o Preditor e as respectivas dependências

Inclua o Preditor em um pacote de distribuição .tar.gz de origem. Como NumPy, TensorFlow e scikit-learn estão inclusos na imagem do ambiente de execução do AI Platform Prediction, não é necessário incluir essas dependências no tarball. Entretanto, inclua todas as dependências do Predictor que não estejam pré-instaladas no AI Platform Prediction.

No caso do exemplo acima, inclua preprocess.py no pacote de distribuição de origem, mesmo que o Predictor não o importe explicitamente. Caso contrário, preprocessor = pickle.load(f) falhará porque o Python não reconhecerá a classe da instância ZeroCenterer no arquivo pickle.

O item setup.py a seguir mostra uma maneira de empacotar esses scripts:

from setuptools import setup

setup(name="my_custom_code", version="0.1", scripts=["predictor.py", "preprocess.py"])

Para empacotar e fazer upload do exemplo de código personalizado descrito nesta página, faça isto:

  1. Crie os arquivos preprocess.py, predictor.py e setup.py descritos nas seções anteriores, todos no mesmo diretório. Navegue até esse diretório no shell.

  2. Execute python setup.py sdist --formats=gztar para criar dist/my_custom_code-0.1.tar.gz.

  3. Faça upload do tarball para um local de preparo no Cloud Storage.

    Não precisa ser o mesmo local que o diretório de modelo. Se você pretende iterar e implantar várias versões da rotina de previsão personalizada, convém fazer upload dos pacotes de códigos personalizados em um diretório de preparo designado. É possível incrementar o argumento version em setup.py quando você atualizar o código para acompanhar diferentes versões.

    O comando a seguir mostra uma maneira de fazer upload do pacote de distribuição de origem no Cloud Storage:

    gsutil cp dist/my_custom_code-0.1.tar.gz gs://YOUR_BUCKET/PATH_TO_STAGING_DIR/
    

É possível fornecer o código para sua rotina de previsão personalizada em um ou mais pacotes.

Implantar a rotina de previsão personalizada

Primeiro, selecione uma região onde a previsão on-line esteja disponível e use gcloud para criar um recurso de modelo:

gcloud ai-platform models create MODEL_NAME{"</var>"}} \
  --regions CHOSEN_REGION

Verifique se o componente gcloud beta está atualizado e, em seguida, crie um recurso de versão com atenção especial para os sinalizadores gcloud a seguir:

  • --origin: o caminho para o diretório do modelo no Cloud Storage.
  • --package-uris: uma lista separada por vírgulas de tarballs de código de usuário no Cloud Storage, incluindo a que contém sua classe Predictor.
  • --prediction-class: o nome totalmente qualificado da classe Predictor (MODULE_NAME.CLASS_NAME).
  • --framework: não especifique um framework ao implantar uma rotina de previsão personalizada.
  • --runtime-version: as rotinas de previsão personalizadas estão disponíveis da versão 1.4 à 2.11 do ambiente de execução.

No comando a seguir, mostramos como criar um recurso de versão com base nos arquivos de exemplo descritos nas seções anteriores:

gcloud components install beta

gcloud beta ai-platform versions create VERSION_NAME \
  --model MODEL_NAME{"</var>"}} \
  --runtime-version 2.11 \
  --python-version 3.7 \
  --origin gs://YOUR_BUCKET/PATH_TO_MODEL_DIR \
  --package-uris gs://YOUR_BUCKET/PATH_TO_STAGING_DIR/my_custom_code-0.1.tar.gz \
  --prediction-class predictor.MyPredictor

Para saber mais sobre como criar modelos e versões em detalhes ou para aprender a criá-los usando o Console do Google Cloud Platform em vez da CLI gcloud, consulte o guia para implantar modelos.

Especificar uma conta de serviço

Ao criar um recurso de versão, você tem a opção de especificar uma conta de serviço para ser usada pela sua rotina de previsão personalizada durante a previsão. Isso permite que você personalize as permissões para acessar outros recursos do Google Cloud. Saiba mais sobre como especificar uma conta de serviço para sua rotina de previsão personalizada.

A seguir

  • Siga o tutorial sobre como usar rotinas de previsão personalizadas com Keras ou com scikit-learn para ver um exemplo mais completo de como treinar e implantar um modelo usando esse tipo de rotina.
  • Leia o guia sobre como exportar modelos para saber mais sobre a exportação de artefatos para previsão sem usar uma rotina de previsão personalizada.
  • Leia o guia para implantar modelos para saber mais detalhes sobre a implantação de recursos model e version no AI Platform Prediction para exibir previsões.