Sdílet prostřednictvím


Odvození ONNX ve Sparku

V tomto příkladu vytrénujete model LightGBM a převedete ho na formát ONNX . Po převodu použijete model k odvození některých testovacích dat ve Sparku.

Tento příklad používá tyto balíčky a verze Pythonu:

  • onnxmltools==1.7.0
  • lightgbm==3.2.1

Požadavky

  • Připojte poznámkový blok k jezeru. Na levé straně vyberte Přidat a přidejte existující jezero nebo vytvořte jezero.
  • Možná budete muset nainstalovat onnxmltools. K tomu přidejte !pip install onnxmltools==1.7.0 do buňky s kódem v poznámkovém bloku a poté tuto buňku spusťte.
  • Možná budete muset nainstalovat lightgbm. cs-CZ: Uděláte to tak, že přidáte !pip install lightgbm==3.2.1 do buňky s kódem poznámkového bloku a poté buňku spustíte.

Načtení ukázkových dat

Pokud chcete načíst ukázková data, přidejte tyto příklady kódu do buněk v poznámkovém bloku a pak tyto buňky spusťte:

from pyspark.sql import SparkSession

# Bootstrap Spark Session
spark = SparkSession.builder.getOrCreate()

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

display(df)

Výstup by měl vypadat podobně jako v následující tabulce. Zobrazené konkrétní sloupce, počet řádků a skutečné hodnoty v tabulce se můžou lišit:

Poměr pokrytí úroku Příznak čistého příjmu Vlastní kapitál vůči závazkům
0.5641 1.0 0.0165
0.5702 1.0 0.0208
0.5673 1.0 0.0165

Trénování modelu pomocí LightGBM

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?", dataTransferMode="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)

Převod modelu do formátu ONNX

Následující kód exportuje trénovaný model do boosteru LightGBM a pak převede model do formátu ONNX:

import lightgbm as lgb
from lightgbm import Booster, LGBMClassifier


def convertModel(lgbm_model: LGBMClassifier or Booster, input_size: int) -> bytes:
    from onnxmltools.convert import convert_lightgbm
    from onnxconverter_common.data_types import FloatTensorType

    initial_types = [("input", FloatTensorType([-1, input_size]))]
    onnx_model = convert_lightgbm(
        lgbm_model, initial_types=initial_types, target_opset=9
    )
    return onnx_model.SerializeToString()


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

Po převodu načtěte datovou část ONNX do objektu ONNXModela zkontrolujte vstupy a výstupy modelu:

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

Namapujte vstup modelu na název sloupce (FeedDict) vstupního datového rámce a namapujte názvy sloupců výstupního datového rámce na výstupy modelu (FetchDict):

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

Použití modelu k odvozování

Pokud chcete provést odvozování s modelem, vytvoří následující kód testovací data a transformuje data prostřednictvím modelu ONNX:

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

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

display(onnx_ml.transform(testDf))

Výstup by měl vypadat podobně jako v následující tabulce, i když se hodnoty a počet řádků můžou lišit:

Rejstřík Vlastnosti Předpověď Pravděpodobnost
1 "{"type":1,"values":[0.105... 0 "{"0":0.835...
2 "{"type":1,"values":[0.814... 0 "{"0":0.658...