ONNX-tunnistus Sparkissä

ONNX (Open Neural Network Exchange) tarjoaa kannettavan, laitteistopohjaisen ajonaikaisen koneoppimismalleille. Muuntamalla mallin ONNX-muotoon voit ajaa eräpäättelyä Sparkilla pienemmällä viiveellä ja ilman riippuvuutta alkuperäisestä koulutuskehyksestä ennustevaiheessa.

Tässä artikkelissa koulutat LightGBM-mallin SynapseML:llä, muunnat sen ONNX-muotoon ja käytät ONNX-mallia päättelyyn Sparkissa Microsoft Fabric -tilassa.

Edellytykset

  • Liitä muistikirjasi Lakehouseen. Muistikirjasi vasemmalla puolella valitse Lisää , jotta voit lisätä olemassa olevan järvimajan tai luoda sellaisen.
  • Fabric Runtime 1.2 tai uudempi.

Tarvittavien pakettien asentaminen

Aja seuraava solu kannettavassasi asentaaksesi tarvittavat paketit. onnxmltools -pakettia ei ole valmiiksi asennettu Fabric ajonaikaan.

%pip install onnxmltools --quiet

Kun asennus on valmis, varmista, että paketit ovat saatavilla:

import onnxmltools
import lightgbm
print(f"onnxmltools version: {onnxmltools.__version__}")
print(f"lightgbm version: {lightgbm.__version__}")

Muistio

lightgbm -paketti on valmiiksi asennettu Fabric Runtime 1.2:een ja uudempiin. Sinun tarvitsee vain asentaa onnxmltools.

Lataa esimerkkitiedot

Lataa bankruptcy prediction dataset from public Azure Blob Storage:

df = (
    spark.read.format("csv")
    .option("header", True)
    .option("inferSchema", True)
    .load(
        "wasbs://publicwasb@mmlspark.blob.core.windows.net/company_bankruptcy_prediction_data.csv"
    )
)

print(f"Rows: {df.count()}, Columns: {len(df.columns)}")
display(df.limit(5))

Näytetty taulukko sisältää sarakkeita, kuten:

Konkurssissa? Nettotulot-merkintä Oma pääoma vastuulle
0 1.0 0.0165
0 1.0 0.0208

Kouluta LightGBM-mallia

Käytä ominaisuussarakkeiden VectorAssembler yhdistämistä ja kouluta a LightGBMClassifier:

from pyspark.ml.feature import VectorAssembler
from synapse.ml.lightgbm import LightGBMClassifier

feature_cols = df.columns[1:]
featurizer = VectorAssembler(inputCols=feature_cols, outputCol="features")

train_data = featurizer.transform(df)["Bankrupt?", "features"]

model = (
    LightGBMClassifier(featuresCol="features", labelCol="Bankrupt?")
    .setDataTransferMode("bulk")
    .setEarlyStoppingRound(300)
    .setLambdaL1(0.5)
    .setNumIterations(1000)
    .setNumThreads(-1)
    .setMaxDeltaStep(0.5)
    .setNumLeaves(31)
    .setMaxDepth(-1)
    .setBaggingFraction(0.7)
    .setFeatureFraction(0.7)
    .setBaggingFreq(2)
    .setObjective("binary")
    .setIsUnbalance(True)
    .setMinSumHessianInLeaf(20)
    .setMinGainToSplit(0.01)
)

model = model.fit(train_data)

Varmista onnistuneesti koulutettu malli:

print(f"Model type: {type(model).__name__}")
print(f"Number of features: {len(feature_cols)}")

Mallin muuntaminen ONNX-muotoon

Vie koulutettu malli LightGBM-vahvistimeen ja muunna se sitten ONNX:ksi:

import lightgbm as lgb
from typing import Union
from lightgbm import Booster, LGBMClassifier
from onnxmltools.convert import convert_lightgbm
from onnxmltools.convert.common.data_types import FloatTensorType


def convert_to_onnx(lgbm_model: Union[LGBMClassifier, Booster], input_size: int) -> bytes:
    initial_types = [("input", FloatTensorType([-1, input_size]))]
    onnx_model = convert_lightgbm(
        lgbm_model, initial_types=initial_types, target_opset=13
    )
    return onnx_model.SerializeToString()


booster_model_str = model.getLightGBMBooster().modelStr().get()
booster = lgb.Booster(model_str=booster_model_str)
model_payload_ml = convert_to_onnx(booster, len(feature_cols))

Varmista, että ONNX-muunnos onnistui:

print(f"ONNX model payload size: {len(model_payload_ml)} bytes")
assert len(model_payload_ml) > 0, "ONNX conversion failed: empty payload"

Lähtö näyttää ONNX-mallin hyötykuorman koon tavuina (tyypillisesti noin 800 000 tavua).

Important

Käyttö from onnxmltools.convert.common.data_types import FloatTensorType tyypin määrittelyyn. Vanhempi tuontipolku from onnxconverter_common.data_types import FloatTensorType ei ole yhteensopiva nykyisten versioiden onnxmltoolskanssa.

Lataa ja konfiguroi ONNX-malli

Lataa ONNX-hyötykuorma SynapseML ONNXModel :ään ja tarkasta mallin tulot ja -lähtöt:

from synapse.ml.onnx import ONNXModel

onnx_ml = ONNXModel().setModelPayload(model_payload_ml)

print("Model inputs:" + str(onnx_ml.getModelInputs()))
print("Model outputs:" + str(onnx_ml.getModelOutputs()))

Ulostulo listaa mallin syöte- ja lähtösolmut.

Määritä malli kartoittamalla syöttö- ja lähtösarakkeet. Se FeedDict yhdistää ONNX-mallin syötteen nimet DataFrame-sarakkeiden nimiin. Halutut ulostulosarakkeen nimet FetchDict kuvataan ONNX-mallin lähtönimiin:

onnx_ml = (
    onnx_ml.setDeviceType("CPU")
    .setFeedDict({"input": "features"})
    .setFetchDict({"probability": "probabilities", "prediction": "label"})
    .setMiniBatchSize(5000)
)

Juoksupäättely

Luo testidata ja muunna se ONNX-mallin avulla:

from pyspark.ml.feature import VectorAssembler
import pandas as pd
import numpy as np

n = 10000
m = 95
test = np.random.rand(n, m)
testPdf = pd.DataFrame(test)
cols = list(map(str, testPdf.columns))
testDf = spark.createDataFrame(testPdf)
testDf = testDf.repartition(4)
testDf = (
    VectorAssembler()
    .setInputCols(cols)
    .setOutputCol("features")
    .transform(testDf)
    .drop(*cols)
    .cache()
)

display(onnx_ml.transform(testDf))

Muistio

Koska testidata generoidaan satunnaisesti, ennustearvot eivät edusta todellisia tuloksia. Tämä osio osoittaa, että ONNX-malli toimii oikein Sparkilla.

Tuloksen tulisi sisältää sarakkeet , featuresprediction, ja probability:

Ominaisuudet ennustaminen todennäköisyys
{"type":1,"values":[0.105... 0 {"0":0.835...
{"type":1,"values":[0.814... 0 {"0":0.658...

Varmista tuotetut päättelytulokset:

results = onnx_ml.transform(testDf)
print(f"Result count: {results.count()}")
print(f"Output columns: {results.columns}")
assert "prediction" in results.columns, "Missing prediction column"
assert "probability" in results.columns, "Missing probability column"

Tulos vahvistaa, että kaikki testirivit on pisteytetty ja tulos DataFrame sisältää features, prediction, ja probability sarakkeet.

Vianmääritys

Ongelma Syy Ratkaisu
ModuleNotFoundError: No module named 'onnxmltools' Pakettia ei ole valmiiksi asennettu Fabric-ajonaikaan. Käynnistä %pip install onnxmltools --quiet ja käynnistä Python-ydin uudelleen.
RuntimeError: Operator LgbmClassifier got an input with a wrong type Väärä tuontipolku .FloatTensorType Käytä from onnxmltools.convert.common.data_types import FloatTensorType sen sijaan, että tuottaisit .onnxconverter_common.data_types
ModuleNotFoundError: No module named 'onnx.mapping' Yhteensopimaton onnxmltools versio 1.7.0 tai sitä vanhempi nykyisen onnx paketin kanssa. Asenna yhteensopiva versio.%pip install onnxmltools --upgrade --quiet
ONNX conversion returns empty payload Booster-mallin merkkijonojen poimiminen epäonnistui. Varmista, että model.getLightGBMBooster().modelStr().get() se palauttaa ei-tyhjän merkkijonon ennen muuntamista.
Feature (Column_) appears more than one time aikana model.fit() Tietoaineiston sarakkeet, joissa on erikoismerkit, tuottavat kaksoisnimiä LightGBM-puhdistuksen jälkeen. Lisää .setDataTransferMode("bulk") kokoonpanoon LightGBMClassifier . Bulk-tila käyttää Apache Arrowta ja välttää sarakkeen nimen puhdistusongelman.
AssertionError SparkContext -sivustolla ONNXModel() Spark-istuntoa ei ole käynnistetty. Aja tämä koodi Fabric-muistikirjassa, johon on liitetty järvenrakennus. Muuttuja spark on esialustettu suoritusaikaan.

Puhdista resurssit

Jos et enää tarvitse välimuistissa olevaa testi-DataFramea, poista se vapautuaksesi klusterimuistista:

testDf.unpersist()