Haz predicciones con modelos de PyTorch en formato ONNX

Open Neural Network Exchange (ONNX) proporciona un formato uniforme diseñado para representar cualquier framework de aprendizaje automático. La compatibilidad de BigQuery ML con ONNX te permite hacer lo siguiente:

  • Entrenar un modelo con tu framework favorito.
  • Convertir el modelo al formato de modelo ONNX. Para obtener más información, consulta Convierte al formato ONNX.
  • Importar el modelo ONNX a BigQuery y hacer predicciones con BigQuery ML

En este instructivo, se muestra cómo importar modelos ONNX entrenados con PyTorch a un conjunto de datos de BigQuery y usarlos para realizar predicciones a partir de una consulta en SQL. Puedes importar modelos de ONNX con estas interfaces:

Para obtener más información sobre la importación de modelos ONNX a BigQuery, incluidos los requisitos de formato y almacenamiento, consulta la declaración CREATE MODEL para importar modelos ONNX.

Objetivos

En este instructivo, podrás:

  • Crear y entrenar modelos con PyTorch.
  • Convierte los modelos al formato ONNX con torch.onnx.
  • Importar los modelos de ONNX a BigQuery y hacer predicciones.

Crea un modelo de visión de PyTorch para la clasificación de imágenes

Importa un resnet18 previamente entrenado de PyTorch que acepte los datos de imagen decodificados que muestran las funciones ML.DECODE_IMAGE y ML.RESIZE_IMAGE de BigQuery ML.

import torch
import torch.nn as nn

# Define model input format to match the output format of
# ML.DECODE_IMAGE function: [height, width, channels]
dummy_input = torch.randn(1, 224, 224, 3, device="cpu")

# Load a pretrained pytorch model for image classification
model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet18', pretrained=True)

# Reshape input format from [batch_size, height, width, channels]
# to [batch_size, channels, height, width]
class ReshapeLayer(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, x):
        x = x.permute(0, 3, 1, 2)  # reorder dimensions
        return x

class ArgMaxLayer(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, x):
       return torch.argmax(x, dim=1)

final_model = nn.Sequential(
    ReshapeLayer(),
    model,
    nn.Softmax(),
    ArgMaxLayer()
)

Convierte el modelo al formato ONNX y guarda

Usa torch.onnx para exportar el modelo de visión de PyTorch a un archivo ONNX llamado resnet18.onnx.

torch.onnx.export(final_model,            # model being run
                  dummy_input,            # model input
                  "resnet18.onnx",        # where to save the model
                  opset_version=10,       # the ONNX version to export the model to
                  input_names = ['input'],         # the model's input names
                  output_names = ['class_label'])  # the model's output names

Sube el modelo ONNX a Cloud Storage.

Crea un bucket de Cloud Storage para almacenar el archivo del modelo ONNX y, luego, sube el archivo del modelo ONNX guardado a tu bucket de Cloud Storage. Para obtener más información, consulta Sube objetos desde un sistema de archivos.

Importa el modelo ONNX a BigQuery

En este paso, se supone que subiste el modelo ONNX a tu bucket de Cloud Storage. Un modelo de ejemplo se almacena en gs://cloud-samples-data/bigquery/ml/onnx/resnet18.onnx.

Console

  1. En la consola de Google Cloud, ve a la página de BigQuery.

    Ir a la página de BigQuery

  2. En el editor de consultas, ingresa una declaración CREATE MODEL como la siguiente.

     CREATE OR REPLACE MODEL `mydataset.mymodel`
      OPTIONS (MODEL_TYPE='ONNX',
       MODEL_PATH='gs://bucket/path/to/onnx_model/*')

    Por ejemplo:

     CREATE OR REPLACE MODEL `example_dataset.imported_onnx_model`
      OPTIONS (MODEL_TYPE='ONNX',
       MODEL_PATH='gs://cloud-samples-data/bigquery/ml/onnx/resnet18.onnx')

    La consulta anterior importa el modelo de ONNX ubicado en gs://cloud-samples-data/bigquery/ml/onnx/resnet18.onnx como un modelo de BigQuery llamado imported_onnx_model.

  3. Tu nuevo modelo ahora debería aparecer en el panel Recursos. A medida que expandes cada uno de los conjuntos de datos en un proyecto, se enumeran los modelos junto con los otros recursos de BigQuery en los conjuntos de datos. Los modelos se indican con el ícono del modelo: ícono del modelo.

  4. Si seleccionas el modelo nuevo en el panel Recursos, la información sobre el modelo aparece debajo del Editor de consultas.

    Información del modelo de Onnx

bq

Para importar un modelo de ONNX desde Cloud Storage, ejecuta una consulta por lotes mediante un comando como el siguiente:

bq query \
--use_legacy_sql=false \
"CREATE MODEL
  `mydataset.mymodel`
OPTIONS
  (MODEL_TYPE='ONNX',
   MODEL_PATH='gs://bucket/path/to/onnx_model/*')"

Por ejemplo:

bq query --use_legacy_sql=false \
"CREATE OR REPLACE MODEL
  `example_dataset.imported_onnx_model`
OPTIONS
  (MODEL_TYPE='ONNX',
   MODEL_PATH='gs://cloud-samples-data/bigquery/ml/onnx/resnet18.onnx')"

Después de importar el modelo, debe aparecer en el resultado de bq ls [dataset_name]:

$ bq ls example_dataset

       tableId          Type    Labels   Time Partitioning
 --------------------- ------- -------- -------------------
  imported_onnx_model   MODEL

API

Inserta un nuevo trabajo y propaga la propiedad jobs#configuration.query como en el cuerpo de la solicitud siguiente:

{
  "query": "CREATE MODEL `project_id:mydataset.mymodel` OPTIONS(MODEL_TYPE='ONNX' MODEL_PATH='gs://bucket/path/to/onnx_model/*')"
}

Crea una tabla de objetos en BigQuery para acceder a los datos de imágenes

Para acceder a datos no estructurados en BigQuery, debes crear una tabla de objetos. Consulta Crea tablas de objetos para obtener instrucciones detalladas.

Crea una tabla de objetos llamada goldfish_image_table en una imagen de pez dorado almacenada en gs://mybucket/goldfish.jpg.

CREATE EXTERNAL TABLE `example_dataset.goldfish_image_table`
WITH CONNECTION `us.my-connection`
OPTIONS(
  object_metadata = 'SIMPLE',
  uris = ['gs://mybucket/goldfish.jpg'],
  max_staleness = INTERVAL 1 DAY,
  metadata_cache_mode = 'AUTOMATIC');

Realiza predicciones con el modelo ONNX importado

Console

  1. En la consola de Google Cloud, ve a la página de BigQuery.

    Ir a la página de BigQuery

  2. En el editor de consultas, ingresa una consulta con ML.PREDICT como la que se muestra a continuación.

     SELECT
       class_label
     FROM
       ML.PREDICT(MODEL example_dataset.imported_onnx_model,
         (
         SELECT
           ML.RESIZE_IMAGE(ML.DECODE_IMAGE(DATA),
             224,
             224,
             FALSE) AS input
         FROM
           example_dataset.goldfish_image_table) )
     

    La consulta anterior usa el modelo llamado imported_onnx_model en el conjunto de datos example_dataset del proyecto actual para realizar predicciones a partir de datos de imagen en la tabla de objetos de entrada goldfish_image_table. La función ML.DECODE_IMAGE es necesaria para decodificar los datos de imagen para que ML.PREDICT los interprete. Además, se llama a la función ML.RESIZE_IMAGE para cambiar el tamaño de la imagen para que se ajuste al tamaño de la entrada del modelo (224*224). Para obtener más información sobre cómo ejecutar inferencias en tablas de objetos de imagen, consulta Ejecuta la inferencia en las tablas de objetos de imagen.

    Esta consulta genera la etiqueta de clase prevista de la imagen de entrada según el diccionario de etiquetas de ImageNet.

    Resultados de la consulta

bq

Para realizar predicciones a partir de datos de entrada en la tabla input_data, ingresa un comando como el siguiente con el modelo de TensorFlow importado my_model:

bq query \
--use_legacy_sql=false \
'SELECT *
 FROM ML.PREDICT(
   MODEL `my_project.my_dataset.my_model`,
   (SELECT * FROM input_data))'

API

Inserta un nuevo trabajo y propaga la propiedad jobs#configuration.query como en el cuerpo de la solicitud siguiente:

{
  "query": "SELECT * FROM ML.PREDICT(MODEL `my_project.my_dataset.my_model`, (SELECT * FROM input_data))"
}

¿Qué sigue?