nasazení a vytvoření předpovědi pomocí modelu ONNX a SQL strojového učení
v tomto rychlém startu se dozvíte, jak vytvořit model, převést ho na ONNX, nasadit ho do Azure SQL Edgea pak spustit nativní prediktivní zpracování dat pomocí nahraného ONNX modelu.
Tento rychlý Start je založený na scikit-učení a používá datovou sadu Boston.
Než začnete
pokud používáte azure SQL edge a ještě nemáte nasazený modul azure SQL Edge, postupujte podle pokynů v části nasazení SQL Edge pomocí Azure Portal.
nainstalujte Azure Data Studio.
Nainstalujte balíčky Pythonu potřebné pro tento rychlý Start:
- Otevřete Nový Poznámkový blok připojený k jádru Python 3.
- Klikněte na Spravovat balíčky .
- Na kartě nainstalované vyhledejte v seznamu nainstalovaných balíčků následující balíčky Pythonu. Pokud některý z těchto balíčků není nainstalován, vyberte kartu Přidat novou , vyhledejte balíček a klikněte na tlačítko nainstalovat.
- scikit-learn
- numpy
- onnxmltools
- onnxruntime
- pyodbc
- setuptools
- skl2onnx
- sqlalchemy
u každého skriptu níže ho zadejte do buňky na poznámkovém bloku Azure Data Studio a pak buňku spusťte.
Výuka kanálu
Rozdělit datovou sadu, aby používala funkce pro předpověď střední hodnoty domu.
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'])
target_column = 'MEDV'
# Split the data frame into features and target
x_train = pd.DataFrame(df.drop([target_column], axis = 1))
y_train = pd.DataFrame(df.iloc[:,df.columns.tolist().index(target_column)])
print("\n*** Training dataset x\n")
print(x_train.head())
print("\n*** Training dataset y\n")
print(y_train.head())
Výstup:
*** 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
Vytvořte kanál pro výuku modelu LinearRegression. Můžete také použít další regresní modely.
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)
Zkontrolujte přesnost modelu a pak Vypočítejte výsledek R2 a střední chybu.
# 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))
Výstup:
*** Scikit-learn r2 score: 0.7406426641094094
*** Scikit-learn MSE: 21.894831181729206
Převést model na ONNX
převeďte datové typy na podporované SQL datové typy. Tento převod bude vyžadován i pro jiné datarámy.
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
Pomocí skl2onnx , převeďte LinearRegression model na formát ONNX a uložte ho místně.
# Convert the scikit model to onnx format
onnx_model = skl2onnx.convert_sklearn(model, 'Boston Data', convert_dataframe_schema(x_train), final_types=[('variable1',FloatTensorType([1,1]))])
# Save the onnx model locally
onnx_model_path = 'boston1.model.onnx'
onnxmltools.utils.save_model(onnx_model, onnx_model_path)
Testování modelu ONNX
Po převedení modelu na formát ONNX je potřeba, aby se v modelu zobrazovala malá a žádná snížení výkonu.
Poznámka
ONNX runtime používá Floaty namísto Double, takže je možné malé nedostatky.
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()
Výstup:
*** Onnx r2 score: 0.7406426691136831
*** Onnx MSE: 21.894830759270633
R2 Scores are equal
MSE are equal
Vložení modelu ONNX
uloží model do Azure SQL Edge v models tabulce v databázi onnx . V připojovacím řetězci zadejte adresu serveru, uživatelské jméno a heslo.
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()
Načtení dat
Načtěte data do SQL.
Nejdřív vytvořte dvě tabulky, funkce a cíl a uložte podmnožiny datové sady Boston.
- Funkce obsahují všechna data, která se používají k předpovědi cíle a mediánu hodnoty.
- Cíl obsahuje medián hodnoty pro každý záznam v datové sadě.
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())
Nakonec použijte sqlalchemy k vložení x_train a y_train pandasí dataframes do tabulek a v features target uvedeném pořadí.
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)
Nyní můžete zobrazit data v databázi.
Spuštění PREDIKTIVNÍho použití modelu ONNX
pomocí modelu v SQL spusťte nativní předpověď dat pomocí nahraného modelu ONNX.
Poznámka
chcete-li spustit zbývající buňku, změňte jádro poznámkového bloku na SQL.
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 [dbo].[features]
)
SELECT predict_input.id
, p.variable1 AS MEDV
FROM PREDICT(MODEL = @model, DATA = predict_input, RUNTIME=ONNX) WITH (variable1 FLOAT) AS p;