使用 ONNX 格式的 PyTorch 模型进行预测

开放神经网络交换 (ONNX) 提供了一种用于表示任何机器学习框架的统一格式。BigQuery ML 对 ONNX 的支持让您可以:

  • 使用您偏好的框架训练模型。
  • 将模型转换为 ONNX 模型格式。如需了解详情,请参阅转换为 ONNX 格式
  • 将 ONNX 模型导入 BigQuery 并使用 BigQuery ML 进行预测。

本教程介绍了如何将使用 PyTorch 训练的 ONNX 模型导入 BigQuery 数据集,并使用这些模型通过 SQL 查询进行预测。您可以使用以下界面导入 ONNX 模型:

如需详细了解如何将 ONNX 模型导入 BigQuery,包括格式和存储要求,请参阅用于导入 ONNX 模型的 CREATE MODEL 语句

目标

在此教程中,您将学习以下操作:

  • 使用 PyTorch 创建和训练模型。
  • 使用 torch.onnx 将模型转换为 ONNX 格式。
  • 将 ONNX 模型导入 BigQuery 并进行预测。

创建用于图片分类的 PyTorch 视觉模型

导入 PyTorch 预训练的 resnet18,以接受 BigQuery ML ML.DECODE_IMAGEML.RESIZE_IMAGE 函数返回的解码图片数据。

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()
)

将模型转换为 ONNX 格式并保存

使用 torch.onnx 将 PyTorch 视觉模型导出到名为 resnet18.onnx 的 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

将 ONNX 模型上传到 Cloud Storage

创建一个 Cloud Storage 存储桶来存储 ONNX 模型文件,然后将已保存的 ONNX 模型文件上传到您的 Cloud Storage 存储桶。如需了解详情,请参阅从文件系统上传对象

将 ONNX 模型导入 BigQuery

此步骤假定您已将 ONNX 模型上传到 Cloud Storage 存储桶。示例模型存储在 gs://cloud-samples-data/bigquery/ml/onnx/resnet18.onnx

控制台

  1. 在 Google Cloud 控制台中,转到 BigQuery 页面。

    前往 BigQuery 页面

  2. 在查询编辑器中输入 CREATE MODEL 语句,如下所示。

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

    例如:

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

    上述查询会导入位于 gs://cloud-samples-data/bigquery/ml/onnx/resnet18.onnx 的 ONNX 模型作为名为 imported_onnx_model 的 BigQuery 模型。

  3. 现在,您的新模型应显示在资源面板中。在展开项目中的每个数据集时,模型将与数据集中的其他 BigQuery 资源一起列出。模型由模型图标 模型图标 表示。

  4. 如果您在资源面板中选择该新模型,则模型相关信息将显示在查询编辑器下方。

    onnx 模型信息

bq

如需从 Cloud Storage 导入 ONNX 模型,请输入如下命令来运行批量查询:

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

例如:

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')"

导入模型后,它应该显示在 bq ls [dataset_name] 的输出中:

$ bq ls example_dataset

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

API

插入新作业并填充 jobs#configuration.query 属性,如以下请求正文所示:

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

在 BigQuery 中创建对象表以访问图片数据

如需访问 BigQuery 中的非结构化数据,您需要创建一个对象表。如需查看详细说明,请参阅创建对象表

在存储于 gs://mybucket/goldfish.jpg 的金鱼图片上创建名为 goldfish_image_table 的对象表。

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');

使用导入的 ONNX 模型进行预测

控制台

  1. 在 Google Cloud 控制台中,转到 BigQuery 页面。

    前往 BigQuery 页面

  2. 在查询编辑器中,使用 ML.PREDICT 输入查询,如下所示:

     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) )
     

    上述查询会使用当前项目的数据集 example_dataset 中名为 imported_onnx_model 的模型,以根据输入对象表 goldfish_image_table 中的图片数据进行预测。 您必须使用 ML.DECODE_IMAGE 函数来解码图片数据,以便 ML.PREDICT 可对其进行解释。此外,还会调用 ML.RESIZE_IMAGE 函数来调整图片大小,使其适合模型输入的大小 (224*224)。如需详细了解如何对图片对象表运行推断,请参阅对图片对象表运行推断

    此查询会根据 ImageNet 标签字典输出输入图片的预测类标签。

    查询结果

bq

如需根据表 input_data 中的输入数据进行预测,请使用导入的 ONNX 模型 my_model 输入如下所示的命令:

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

API

插入新作业并填充 jobs#configuration.query 属性,如以下请求正文所示:

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

后续步骤