Bereitstellen eines ONNX-Modells und Treffen von Vorhersagen damit in der SQL Database Edge-VorschauDeploy and make predictions with an ONNX model in SQL Database Edge Preview

In diesem Schnellstart erfahren Sie, wie Sie ein Modell trainieren, es in ONNX konvertieren, anschließend in Azure SQL Database Edge-Vorschau bereitstellen und dann mithilfe des hochgeladenen ONXX-Modells natives PREDICT für Daten ausführen.In this quickstart, you'll learn how to train a model, convert it to ONNX, deploy it to Azure SQL Database Edge Preview, and then run native PREDICT on data using the uploaded ONNX model. Weitere Informationen finden Sie unter Maschinelles Lernen und KI mit ONNX in SQL Database Edge (Vorschauversion).For more information, see Machine learning and AI with ONNX in SQL Database Edge Preview.

Dieser Schnellstart basiert auf SciKit-learn und verwendet das Boston Housing-Dataset.This quickstart is based on scikit-learn and uses the Boston Housing dataset.

VoraussetzungenBefore you begin

  • Wenn Sie noch kein Azure SQL Database Edge-Modul bereitgestellt haben, führen Sie die Schritte unter Bereitstellen der SQL Database Edge-Vorschau über das Azure-Portal aus.If you haven't deployed an Azure SQL Database Edge module, follow the steps of deploy SQL Database Edge Preview using the Azure portal.

  • Installieren Sie Azure Data Studio.Install Azure Data Studio.

  • Öffnen Sie Azure Data Studio, und führen Sie die folgenden Schritte zum Installieren der für diesen Schnellstart benötigten Pakete aus:Open Azure Data Studio and follow these steps to install the packages needed for this quickstart:

    1. Öffnen Sie Neues Notebook, das mit dem Python 3-Kernel verbunden ist.Open New Notebook connected to the Python 3 Kernel.
    2. Klicken Sie auf Pakete verwalten, suchen Sie unter Neues hinzufügen nach sklearn, und installieren Sie das Paket „SciKit-learn“.Click Manage Packages and under Add New, search for sklearn, and install the scikit-learn package.
    3. Installieren Sie außerdem die Pakete onnxmltools, onnxruntime, skl2onnx und sqlalchemy.Also, install the onnxmltools, onnxruntime, skl2onnx, and sqlalchemy packages.
  • Geben Sie jeden der nachstehenden Skriptteile in eine Zelle im Azure Data Studio-Notebook ein, und führen Sie die Zelle aus.For each script part below, enter it in a cell in the Azure Data Studio notebook and run the cell.

Trainieren einer PipelineTrain a pipeline

Teilen Sie das Dataset auf, um Features zum Vorhersagen des Medians für ein Haus verwenden zu können.Split the dataset to use features to predict the median value of a house.

import numpy as np
import onnxmltools
import onnxruntime as rt
import pandas as pd
import skl2onnx
import sklearn
import sklearn.datasets

from sklearn.datasets import load_boston
boston = load_boston()
boston

df = pd.DataFrame(data=np.c_[boston['data'], boston['target']], columns=boston['feature_names'].tolist() + ['MEDV'])

# x contains all predictors (features)
x = df.drop(['MEDV'], axis = 1)

# y is what we are trying to predict - the median value
y = df.iloc[:,-1]


# Split the data frame into features and target
x_train = df.drop(['MEDV'], axis = 1)
y_train = df.iloc[:,-1]

print("\n*** Training dataset x\n")
print(x_train.head())

print("\n*** Training dataset y\n")
print(y_train.head())

Ausgabe:Output:

*** Training dataset x

        CRIM    ZN  INDUS  CHAS    NOX     RM   AGE     DIS  RAD    TAX  \
0  0.00632  18.0   2.31   0.0  0.538  6.575  65.2  4.0900  1.0  296.0
1  0.02731   0.0   7.07   0.0  0.469  6.421  78.9  4.9671  2.0  242.0
2  0.02729   0.0   7.07   0.0  0.469  7.185  61.1  4.9671  2.0  242.0
3  0.03237   0.0   2.18   0.0  0.458  6.998  45.8  6.0622  3.0  222.0
4  0.06905   0.0   2.18   0.0  0.458  7.147  54.2  6.0622  3.0  222.0

    PTRATIO       B  LSTAT  
0     15.3  396.90   4.98  
1     17.8  396.90   9.14  
2     17.8  392.83   4.03  
3     18.7  394.63   2.94  
4     18.7  396.90   5.33  

*** Training dataset y

0    24.0
1    21.6
2    34.7
3    33.4
4    36.2
Name: MEDV, dtype: float64

Erstellen Sie eine Pipeline zum Trainieren des „LinearRegression“-Modells.Create a pipeline to train the LinearRegression model. Sie können auch andere Regressionsmodelle verwenden.You can also use other regression models.

from sklearn.compose import ColumnTransformer
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import RobustScaler

continuous_transformer = Pipeline(steps=[('scaler', RobustScaler())])

# All columns are numeric - normalize them
preprocessor = ColumnTransformer(
    transformers=[
        ('continuous', continuous_transformer, [i for i in range(len(x_train.columns))])])

model = Pipeline(
    steps=[
        ('preprocessor', preprocessor),
        ('regressor', LinearRegression())])

# Train the model
model.fit(x_train, y_train)

Überprüfen Sie die Genauigkeit des Modells, und berechnen Sie dann den R2-Score und den mittleren quadratischen Fehler.Check the accuracy of the model and then calculate the R2 score and mean squared error.

# Score the model
from sklearn.metrics import r2_score, mean_squared_error
y_pred = model.predict(x_train)
sklearn_r2_score = r2_score(y_train, y_pred)
sklearn_mse = mean_squared_error(y_train, y_pred)
print('*** Scikit-learn r2 score: {}'.format(sklearn_r2_score))
print('*** Scikit-learn MSE: {}'.format(sklearn_mse))

Ausgabe:Output:

*** Scikit-learn r2 score: 0.7406426641094094
*** Scikit-learn MSE: 21.894831181729206

Konvertieren des Modells in ONNXConvert the model to ONNX

Konvertieren Sie die Datentypen in die unterstützten SQL-Datentypen.Convert the data types to the supported SQL data types. Diese Konvertierung ist auch bei anderen DataFrames erforderlich.This conversion will be required for other dataframes as well.

from skl2onnx.common.data_types import FloatTensorType, Int64TensorType, DoubleTensorType

def convert_dataframe_schema(df, drop=None, batch_axis=False):
    inputs = []
    nrows = None if batch_axis else 1
    for k, v in zip(df.columns, df.dtypes):
        if drop is not None and k in drop:
            continue
        if v == 'int64':
            t = Int64TensorType([nrows, 1])
        elif v == 'float32':
            t = FloatTensorType([nrows, 1])
        elif v == 'float64':
            t = DoubleTensorType([nrows, 1])
        else:
            raise Exception("Bad type")
        inputs.append((k, t))
    return inputs

Konvertieren Sie das „LinearRegression“-Modell mithilfe von skl2onnx in das ONNX-Format, und speichern Sie es lokal.Using skl2onnx, convert the LinearRegression model to the ONNX format and save it locally.

# Convert the scikit model to onnx format
onnx_model = skl2onnx.convert_sklearn(model, 'Boston Data', convert_dataframe_schema(x_train))
# Save the onnx model locally
onnx_model_path = 'boston1.model.onnx'
onnxmltools.utils.save_model(onnx_model, onnx_model_path)

Testen des ONNX-ModellsTest the ONNX model

Nachdem Sie das Modell in das ONNX-Format konvertiert haben, bewerten Sie es, um zu zeigen, dass die Leistung wenig bis gar nicht beeinträchtigt wurde.After converting the model to ONNX format, score the model to show little to no degradation in performance.

Hinweis

Weil ONNX-Runtime „float“- statt „double“-Werte verwendet, sind geringfügige Abweichungen möglich.ONNX Runtime uses floats instead of doubles so small discrepancies are possible.

import onnxruntime as rt
sess = rt.InferenceSession(onnx_model_path)

y_pred = np.full(shape=(len(x_train)), fill_value=np.nan)

for i in range(len(x_train)):
    inputs = {}
    for j in range(len(x_train.columns)):
        inputs[x_train.columns[j]] = np.full(shape=(1,1), fill_value=x_train.iloc[i,j])

    sess_pred = sess.run(None, inputs)
    y_pred[i] = sess_pred[0][0][0]

onnx_r2_score = r2_score(y_train, y_pred)
onnx_mse = mean_squared_error(y_train, y_pred)

print()
print('*** Onnx r2 score: {}'.format(onnx_r2_score))
print('*** Onnx MSE: {}\n'.format(onnx_mse))
print('R2 Scores are equal' if sklearn_r2_score == onnx_r2_score else 'Difference in R2 scores: {}'.format(abs(sklearn_r2_score - onnx_r2_score)))
print('MSE are equal' if sklearn_mse == onnx_mse else 'Difference in MSE scores: {}'.format(abs(sklearn_mse - onnx_mse)))
print()

Ausgabe:Output:

*** Onnx r2 score: 0.7406426691136831
*** Onnx MSE: 21.894830759270633

R2 Scores are equal
MSE are equal

Einfügen des ONNX-ModellsInsert the ONNX model

Speichern Sie das Modell in Azure SQL Database Edge, und zwar in einer models-Tabelle in einer Datenbank vom Typ onnx.Store the model in Azure SQL Database Edge, in a models table in a database onnx. Geben Sie in der Verbindungszeichenfolge die Serveradresse, den Benutzernamen und das Kennwort an.In the connection string, specify the server address, username, and password.

import pyodbc

server = '' # SQL Server IP address
username = '' # SQL Server username
password = '' # SQL Server password

# Connect to the master DB to create the new onnx database
connection_string = "Driver={ODBC Driver 17 for SQL Server};Server=" + server + ";Database=master;UID=" + username + ";PWD=" + password + ";"

conn = pyodbc.connect(connection_string, autocommit=True)
cursor = conn.cursor()

database = 'onnx'
query = 'DROP DATABASE IF EXISTS ' + database
cursor.execute(query)
conn.commit()

# Create onnx database
query = 'CREATE DATABASE ' + database
cursor.execute(query)
conn.commit()

# Connect to onnx database
db_connection_string = "Driver={ODBC Driver 17 for SQL Server};Server=" + server + ";Database=" + database + ";UID=" + username + ";PWD=" + password + ";"

conn = pyodbc.connect(db_connection_string, autocommit=True)
cursor = conn.cursor()

table_name = 'models'

# Drop the table if it exists
query = f'drop table if exists {table_name}'
cursor.execute(query)
conn.commit()

# Create the model table
query = f'create table {table_name} ( ' \
    f'[id] [int] IDENTITY(1,1) NOT NULL, ' \
    f'[data] [varbinary](max) NULL, ' \
    f'[description] varchar(1000))'
cursor.execute(query)
conn.commit()

# Insert the ONNX model into the models table
query = f"insert into {table_name} ([description], [data]) values ('Onnx Model',?)"

model_bits = onnx_model.SerializeToString()

insert_params  = (pyodbc.Binary(model_bits))
cursor.execute(query, insert_params)
conn.commit()

Laden der DatenLoad the data

Laden Sie die Daten in Azure SQL Database Edge.Load the data into Azure SQL Database Edge.

Erstellen Sie zuerst zwei Tabellen – Features und Ziel – zum Speichern von Teilmengen des Boston Housing-Datasets.First, create two tables, features and target, to store subsets of the Boston housing dataset.

  • Features enthält alle Daten, die zum Vorhersagen des Ziels, „Median“, verwendet werden.Features contains all data being used to predict the target, median value.
  • Ziel enthält den Median für jeden Datensatz im Dataset.Target contains the median value for each record in the dataset.
import sqlalchemy
from sqlalchemy import create_engine
import urllib

db_connection_string = "Driver={ODBC Driver 17 for SQL Server};Server=" + server + ";Database=" + database + ";UID=" + username + ";PWD=" + password + ";"

conn = pyodbc.connect(db_connection_string)
cursor = conn.cursor()

features_table_name = 'features'

# Drop the table if it exists
query = f'drop table if exists {features_table_name}'
cursor.execute(query)
conn.commit()

# Create the features table
query = \
    f'create table {features_table_name} ( ' \
    f'    [CRIM] float, ' \
    f'    [ZN] float, ' \
    f'    [INDUS] float, ' \
    f'    [CHAS] float, ' \
    f'    [NOX] float, ' \
    f'    [RM] float, ' \
    f'    [AGE] float, ' \
    f'    [DIS] float, ' \
    f'    [RAD] float, ' \
    f'    [TAX] float, ' \
    f'    [PTRATIO] float, ' \
    f'    [B] float, ' \
    f'    [LSTAT] float, ' \
    f'    [id] int)'

cursor.execute(query)
conn.commit()

target_table_name = 'target'

# Create the target table
query = \
    f'create table {target_table_name} ( ' \
    f'    [MEDV] float, ' \
    f'    [id] int)'

x_train['id'] = range(1, len(x_train)+1)
y_train['id'] = range(1, len(y_train)+1)

print(x_train.head())
print(y_train.head())

Verwenden Sie schließlich sqlalchemy zum Einfügen der Pandas-DataFrames x_train und y_train in die Tabellen features bzw. target.Finally, use sqlalchemy to insert the x_train and y_train pandas dataframes into the tables features and target, respectively.

db_connection_string = 'mssql+pyodbc://' + username + ':' + password + '@' + server + '/' + database + '?driver=ODBC+Driver+17+for+SQL+Server'
sql_engine = sqlalchemy.create_engine(db_connection_string)
x_train.to_sql(features_table_name, sql_engine, if_exists='append', index=False)
y_train.to_sql(target_table_name, sql_engine, if_exists='append', index=False)

Jetzt können Sie die Daten in der Datenbank anzeigen.Now you can view the data in the database.

Ausführen von PREDICT mithilfe des ONNX-ModellsRun PREDICT using the ONNX model

Führen Sie mit dem Modell in Azure SQL Database Edge natives PREDICT für die Daten aus, und verwenden Sie dazu das hochgeladene ONNX-Modell.With the model in Azure SQL Database Edge, run native PREDICT on the data using the uploaded ONNX model.

Hinweis

Ändern Sie den Notebook-Kernel in SQL, um die verbleibende Zelle auszuführen.Change the notebook kernel to SQL to run the remaining cell.

USE onnx

DECLARE @model VARBINARY(max) = (
        SELECT DATA
        FROM dbo.models
        WHERE id = 1
        );

WITH predict_input
AS (
    SELECT TOP (1000) [id]
        , CRIM
        , ZN
        , INDUS
        , CHAS
        , NOX
        , RM
        , AGE
        , DIS
        , RAD
        , TAX
        , PTRATIO
        , B
        , LSTAT
    FROM [onnx].[dbo].[features]
    )
SELECT predict_input.id
    , p.variable1 AS MEDV
FROM PREDICT(MODEL = @model, DATA = predict_input) WITH (variable1 FLOAT) AS p

Nächste SchritteNext Steps