Opetusohjelma: Kohotusmallin luominen, harjoittaminen ja arvioiminen

Tämä opas esittelee kokonaisvaltaisen esimerkin Data Science -työnkulusta, Microsoft Fabric -tilassa. Opit luomaan, kouluttamaan ja arvioimaan kohotusmalleja ja käyttämään kohotuksen mallinnustekniikoita.

Edellytykset

  • Hanki Microsoft Fabric -tilaus. Voit myös rekisteröityä microsoft fabric -kokeiluversion maksuttomaan .

  • Kirjaudu sisään Microsoft Fabric .

  • Vaihda Fabric-tilaan käyttämällä etusivun vasemmassa alakulmassa olevaa kokemuskytkintä.

    Kuvakaappaus, joka näyttää kankaan valinnan kokemusvaihtovalikossa.

Seuraa mukana muistikirjassa

Voit seurata muistikirjassa kahdella tavalla:

  • Avaa ja suorita sisäinen muistikirja.
  • Lataa muistikirja GitHubista.

Avaa sisäinen muistikirja

Tämän opetusohjelman mukana on esimerkki Uplift-mallinnus muistikirja.

  1. Avaa tätä opetusohjelmaa varten näytemuistikirja noudattamalla ohjeita kohdassa Järjestelmän valmisteleminen datatieteen opetusohjelmia varten.

  2. Varmista, että liittää lakehouse- ennen kuin aloitat koodin suorittamisen.

Tuo muistikirja GitHubista

AIsample - Uplift Modelling.ipynb -muistikirja sisältyy tähän tutoriaaliin.

Jos haluat avata tämän opetusohjelman liitteenä olevan muistikirjan, tuo muistikirja työtilaasi noudattamalla ohjeita kohdassa Järjestelmän valmisteleminen datatieteen opetusohjelmia.

Jos haluat kopioida ja liittää koodin tältä sivulta, voit luoda uuden muistikirjan.

Muista liittää muistikirjaan lakehouse- ennen kuin aloitat koodin suorittamisen.

Vaihe 1: Lataa tiedot

Dataset

Criteo AI Lab loi tietojoukon. Kyseisessä tietojoukossa on 13 miljoonaa riviä. Jokainen rivi edustaa yhtä käyttäjää. Jokaisella rivillä on 12 ominaisuutta, hoitoilmaisin ja kaksi binaaritunnistetta, jotka sisältävät vierailun ja muunnoksen.

näyttökuva, jossa näkyy Criteo AI Lab -tietojoukon rakenne.

  • f0 - f11: ominaisuusarvot (tiheät, kelluvat arvot)
  • hoidon: oliko käyttäjä satunnaisesti hoitokohde (esimerkiksi mainonta) (1 = hoito, 0 = ohjausobjekti)
  • muuntaminen: tapahtuiko muunto (esimerkiksi osto) käyttäjälle (binaarinen selite)
  • Visit: Kävikö käyttäjä verkkokaupassa (binääri, etiketti)

Lainaus

Tässä muistikirjassa käytetty tietojoukko edellyttää tätä BibTex-lainausmerkkiä:

@inproceedings{Diemert2018,
author = {{Diemert Eustache, Betlei Artem} and Renaudin, Christophe and Massih-Reza, Amini},
title={A Large Scale Benchmark for Uplift Modeling},
publisher = {ACM},
booktitle = {Proceedings of the AdKDD and TargetAd Workshop, KDD, London,United Kingdom, August, 20, 2018},
year = {2018}
}

Juomaraha

Määrittämällä seuraavat parametrit voit käyttää tätä muistikirjaa eri tietojoukoissa helposti.

IS_CUSTOM_DATA = False  # If True, the user must upload the dataset manually
DATA_FOLDER = "Files/uplift-modelling"
DATA_FILE = "criteo-research-uplift-v2.1.csv"

# Data schema
FEATURE_COLUMNS = [f"f{i}" for i in range(12)]
TREATMENT_COLUMN = "treatment"
LABEL_COLUMN = "visit"

EXPERIMENT_NAME = "aisample-upliftmodelling"  # MLflow experiment name

Tuontikirjastot

Ennen käsittelyä tuo tarvittavat Spark- ja SynapseML-kirjastot. Sinun täytyy myös tuoda datan visualisointikirjasto, kuten Seaborn, joka on Python-datan visualisointikirjasto. Tietojen visualisointikirjasto tarjoaa korkean tason käyttöliittymän visuaalisten resurssien luomiseen DataFrame-kehyksissä ja matriiseissa. Lue lisätietoja Spark, SynapseML, ja Seaborn.

import os
import gzip

import pyspark.sql.functions as F
from pyspark.sql.window import Window
from pyspark.sql.types import *

import numpy as np
import pandas as pd

import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.style as style
import seaborn as sns

%matplotlib inline

from synapse.ml.featurize import Featurize
from synapse.ml.core.spark import FluentAPI
from synapse.ml.lightgbm import *
from synapse.ml.train import ComputeModelStatistics

import mlflow

Lataa tietojoukko ja lataa se Lakehouseen

Tämä koodi lataa tietojoukosta julkisesti saatavilla olevan version ja tallentaa sitten kyseisen tietoresurssin Fabric lakehouse -järjestelmään.

Tärkeä

Varmista, että Lisää lakehouse- muistikirjaan ennen sen suorittamista. Jos et tee niin, tapahtuu virhe.

if not IS_CUSTOM_DATA:
    # Download demo data files into lakehouse if not exist
    import os, requests

    remote_url = "http://go.criteo.net/criteo-research-uplift-v2.1.csv.gz"
    download_file = "criteo-research-uplift-v2.1.csv.gz"
    download_path = f"/lakehouse/default/{DATA_FOLDER}/raw"

    if not os.path.exists("/lakehouse/default"):
        raise FileNotFoundError("Default lakehouse not found, please add a lakehouse and restart the session.")
    os.makedirs(download_path, exist_ok=True)
    if not os.path.exists(f"{download_path}/{DATA_FILE}"):
        r = requests.get(f"{remote_url}", timeout=30)
        with open(f"{download_path}/{download_file}", "wb") as f:
            f.write(r.content)
        with gzip.open(f"{download_path}/{download_file}", "rb") as fin:
            with open(f"{download_path}/{DATA_FILE}", "wb") as fout:
                fout.write(fin.read())
    print("Downloaded demo data files into lakehouse.")

Aloita muistikirjan suorituspalvelun tallennus.

# Record the notebook running time
import time

ts = time.time()

MLflow-kokeilujen seurannan määrittäminen

Jos haluat laajentaa MLflow-kirjaustoimintoja, automaattinen käyttöönotto tallentaa automaattisesti koneoppimismallin syöteparametrien arvot ja tulostemittarit sen harjoittamisen aikana. Voit kirjata tämän tiedon työtilaan, jossa MLflow-rajapinnat tai vastaava koe työtilassa voivat käyttää ja visualisoida ne. Lisätietoja löytyy Apache Spark MLflow -autologingista Microsoft Fabric-tiedostossa.

# Set up the MLflow experiment
import mlflow

mlflow.set_experiment(EXPERIMENT_NAME)
mlflow.autolog(disable=True)  # Disable MLflow autologging

Muistiinpano

Jos haluat poistaa Microsoft Fabricin automaattisen lokerauksen käytöstä muistikirjaistunnossa, kutsu mlflow.autolog() ja määritä disable=True.

Tietojen lukeminen Lakehousesta

Lue raakatiedot Lakehouse-Files -osasta ja lisää sarakkeita eri päivämääräosille. Käytä samoja tietoja luodaksesi osioidun delta-taulukon.

raw_df = spark.read.csv(f"{DATA_FOLDER}/raw/{DATA_FILE}", header=True, inferSchema=True).cache()

Vaihe 2: Valmisteleva tietoanalyysi

display-komennon avulla voit tarkastella tietojoukkoa koskevia korkean tason tilastotietoja. Voit myös näyttää kaavionäkymät, joiden avulla voit helposti visualisoida tietojoukon alijoukkoja.

display(raw_df.limit(20))

Tarkista käyvien käyttäjien prosenttiosuus, muuntavien käyttäjien prosenttiosuus ja kääntyvien kävijöiden prosenttiosuus.

raw_df.select(
    F.mean("visit").alias("Percentage of users that visit"),
    F.mean("conversion").alias("Percentage of users that convert"),
    (F.sum("conversion") / F.sum("visit")).alias("Percentage of visitors that convert"),
).show()

Analyysin mukaan 4,9% hoitoryhmän käyttäjistä - käyttäjät, jotka saivat hoidon tai mainonnan - vierailivat verkkokaupassa. Vain 3,8% ohjausryhmän käyttäjistä - käyttäjät, jotka eivät koskaan saaneet hoitoa tai joita ei koskaan tarjottu tai paljastettu mainonnalle - tekivät samoin. Lisäksi 0,31% kaikista hoitoryhmän käyttäjistä muunnettuna tai tehnyt ostoksen , mutta vain 0,19% hallintaryhmän käyttäjistä teki niin. Tämän seurauksena oston tehneiden kävijöiden, jotka olivat myös hoitoryhmän jäseniä, konversioprosentti on 6,36%, kun taas kontrolliryhmän käyttäjillä vain 5,07% . Näiden tulosten perusteella hoito voi mahdollisesti parantaa käyntinopeutta noin 1%, ja kävijöiden muuntamisnopeutta noin 1,3%. Hoito johtaa merkittävään parannukseen.

Vaihe 3: Määritä malli harjoittamista varten

Valmistele koulutus ja testaa tietojoukkoja

Tässä esimerkissä sovitat Featurize-muuntimen raw_df DataFrameen, jotta voit poimia ominaisuuksia määritetyistä syötesarakkeista ja tulostaa nämä ominaisuudet uuteen sarakkeeseen nimeltä features.

DataFrame tallennetaan uuteen DataFrameen nimeltä df.

transformer = Featurize().setOutputCol("features").setInputCols(FEATURE_COLUMNS).fit(raw_df)
df = transformer.transform(raw_df)
# Split the DataFrame into training and test sets, with a 80/20 ratio and a seed of 42
train_df, test_df = df.randomSplit([0.8, 0.2], seed=42)

# Print the training and test dataset sizes
print("Size of train dataset: %d" % train_df.count())
print("Size of test dataset: %d" % test_df.count())

# Group the training dataset by the treatment column, and count the number of occurrences of each value
train_df.groupby(TREATMENT_COLUMN).count().show()

Käsittelyn ja tietojoukkojen hallinnan valmisteleminen

Kun olet luonut harjoitus- ja testitietojoukot, sinun täytyy muodostaa myös hoito- ja hallintatietojoukot, jotta voit harjoittaa koneoppimismalleja nousun mittaamiseksi.

# Extract the treatment and control DataFrames
treatment_train_df = train_df.where(f"{TREATMENT_COLUMN} > 0")
control_train_df = train_df.where(f"{TREATMENT_COLUMN} = 0")

Nyt kun olet valmistellut tietosi, voit jatkaa mallin harjoittamista LightGBM:llä.

Uplift-mallinnus: T-Learner LightGBM:llä

Metaoppijat ovat joukko algoritmeja, jotka on kehitetty koneoppimisalgoritmien, kuten LightGBM: n, Xgboostin, päälle. Ne auttavat arvioimaan ehdollista keskimääräistä hoitovaikutusta, tai ne CATE. T-learner on meta-oppija, joka ei käytä yksittäistä mallia. Sen sijaan T-learner käyttää yhtä mallia käsittelymuuttujaa kohden. Siksi kehitetään kaksi mallia, ja meta-oppijaan viitataan T-learner-parametrina. T-learner käyttää useita koneoppimismalleja ratkaistakseen ongelman, joka ilmenee, kun hän hylkää hoidon kokonaan pakottamalla oppijan jakamaan sen ensimmäisen kerran.

mlflow.autolog(exclusive=False)
classifier = (
    LightGBMClassifier(dataTransferMode="bulk")
    .setFeaturesCol("features")  # Set the column name for features
    .setNumLeaves(10)  # Set the number of leaves in each decision tree
    .setNumIterations(100)  # Set the number of boosting iterations
    .setObjective("binary")  # Set the objective function for binary classification
    .setLabelCol(LABEL_COLUMN)  # Set the column name for the label
)

# Start a new MLflow run with the name "uplift"
active_run = mlflow.start_run(run_name="uplift")

# Start a new nested MLflow run with the name "treatment"
with mlflow.start_run(run_name="treatment", nested=True) as treatment_run:
    treatment_run_id = treatment_run.info.run_id  # Get the ID of the treatment run
    treatment_model = classifier.fit(treatment_train_df)  # Fit the classifier on the treatment training data

# Start a new nested MLflow run with the name "control"
with mlflow.start_run(run_name="control", nested=True) as control_run:
    control_run_id = control_run.info.run_id  # Get the ID of the control run
    control_model = classifier.fit(control_train_df)  # Fit the classifier on the control training data
     

Käytä ennusteena testitietojoukkoa

Tässä käytetään aiemmin määritettyjä treatment_model ja control_modeltestitietojoukon muuntamiseen test_df testitietojoukkoa. Sitten lasket ennustetun nousun. Määrität ennustetun nousun siten, että se eroaa ennustetun hoitotuloksen ja ennustetun ohjausobjektituloksen välillä. Mitä suurempi tämä ennustettu kohotusero, sitä parempi on hoidon tehokkuus (esimerkiksi mainonta) yksilössä tai alaryhmässä.

getPred = F.udf(lambda v: float(v[1]), FloatType())

# Cache the resulting DataFrame for easier access
test_pred_df = (
    test_df.mlTransform(treatment_model)
    .withColumn("treatment_pred", getPred("probability"))
    .drop("rawPrediction", "probability", "prediction")
    .mlTransform(control_model)
    .withColumn("control_pred", getPred("probability"))
    .drop("rawPrediction", "probability", "prediction")
    .withColumn("pred_uplift", F.col("treatment_pred") - F.col("control_pred"))
    .select(TREATMENT_COLUMN, LABEL_COLUMN, "treatment_pred", "control_pred", "pred_uplift")
    .cache()
)

# Display the first twenty rows of the resulting DataFrame
display(test_pred_df.limit(20))

Mallin arvioinnin suorittaminen

Koska et voi havaita todellista nousua jokaiselle yksilölle, mittaa nousu ryhmässä. Käytä Uplift-käyrää, joka kuvaa todellisen, kumulatiivisen nousun koko väestössä.

Näyttökuva kaaviosta, joka näyttää normalisoidun kohotusmallin käyrän verrattuna satunnaiseen hoitoon.

X-akseli edustaa hoitoa varten valitun populaation suhdetta. Arvo 0 ei viittaa siihen, että hoitoryhmää ei tarjota - kukaan ei altistu hoidolle tai tarjoa sitä. Arvo 1 viittaa täyteen hoitoryhmään - kaikki altistuvat hoidolle tai heille tarjotaan. Y-akselilla näkyy nostuksen mittari. Tarkoituksena on löytää hoitoryhmän koko tai prosenttiosuus väestöstä, joka tarjottaisiin tai altistettaisiin hoidolle (esimerkiksi mainonta). Tämä lähestymistapa optimoi kohdevalinnan tuloksen optimoimiseksi.

Aseta ensin testin DataFrame-järjestys järjestykseen ennustetun nousun mukaan. Ennustettu kohotus on ennustetun hoitotuloksen ja ennustetun hallinnan tuloksen välinen ero.

# Compute the percentage rank of the predicted uplift values in descending order, and display the top twenty rows
test_ranked_df = test_pred_df.withColumn("percent_rank", F.percent_rank().over(Window.orderBy(F.desc("pred_uplift"))))

display(test_ranked_df.limit(20))

Laske seuraavaksi käyntien kumulatiivinen prosenttiosuus sekä hoito- että ohjausryhmissä.

# Calculate the number of control and treatment samples
C = test_ranked_df.where(f"{TREATMENT_COLUMN} == 0").count()
T = test_ranked_df.where(f"{TREATMENT_COLUMN} != 0").count()

# Add columns to the DataFrame to calculate the control and treatment cumulative sum
test_ranked_df = (
    test_ranked_df.withColumn(
        "control_label",
        F.when(F.col(TREATMENT_COLUMN) == 0, F.col(LABEL_COLUMN)).otherwise(0),
    )
    .withColumn(
        "treatment_label",
        F.when(F.col(TREATMENT_COLUMN) != 0, F.col(LABEL_COLUMN)).otherwise(0),
    )
    .withColumn(
        "control_cumsum",
        F.sum("control_label").over(Window.orderBy("percent_rank")) / C,
    )
    .withColumn(
        "treatment_cumsum",
        F.sum("treatment_label").over(Window.orderBy("percent_rank")) / T,
    )
)

# Display the first 20 rows of the dataframe
display(test_ranked_df.limit(20))

Laske lopuksi kunkin prosenttiosuuden kohdalla ryhmän nousu erotuksena käsittelyn ja ohjausobjektiryhmien välisen käyntien kumulatiivisen prosenttiosuuden välillä.

test_ranked_df = test_ranked_df.withColumn("group_uplift", F.col("treatment_cumsum") - F.col("control_cumsum")).cache()
display(test_ranked_df.limit(20))

Piirtää nyt testitietojoukon ennusteen kohotuskäyrän. Muunna PySpark DataFrame Pandas DataFrameksi ennen piirtoa.

def uplift_plot(uplift_df):
    """
    Plot the uplift curve
    """
    gain_x = uplift_df.percent_rank
    gain_y = uplift_df.group_uplift
    # Plot the data
    fig = plt.figure(figsize=(10, 6))
    mpl.rcParams["font.size"] = 8

    ax = plt.plot(gain_x, gain_y, color="#2077B4", label="Normalized Uplift Model")

    plt.plot(
        [0, gain_x.max()],
        [0, gain_y.max()],
        "--",
        color="tab:orange",
        label="Random Treatment",
    )
    plt.legend()
    plt.xlabel("Proportion Targeted")
    plt.ylabel("Uplift")
    plt.grid()

    return fig, ax


test_ranked_pd_df = test_ranked_df.select(["pred_uplift", "percent_rank", "group_uplift"]).toPandas()
fig, ax = uplift_plot(test_ranked_pd_df)

mlflow.log_figure(fig, "UpliftCurve.png")

Näyttökuva kaaviosta, joka näyttää normalisoidun kohotusmallin käyrän verrattuna satunnaiseen hoitoon.

Analyysi ja kohotuskäyrä osoittavat, että ennusteen mukaan paremmuusjärjestyksessä 20% populaatiolla olisi ennusteen mukaan suuri voitto, jos he saisivat hoitoa. Tämä havainto tarkoittaa, että väestön 20 parasta% edustaa vakuutettavien ryhmää. Aseta halutun hoitoryhmän koon rajapisteeksi 20%, jotta tunnistetaan kohdeasiakkaat suurimman vaikutuksen saavuttamiseksi.

cutoff_percentage = 0.2
cutoff_score = test_ranked_pd_df.iloc[int(len(test_ranked_pd_df) * cutoff_percentage)][
    "pred_uplift"
]

print("Uplift scores that exceed {:.4f} map to Persuadables.".format(cutoff_score))
mlflow.log_metrics(
    {"cutoff_score": cutoff_score, "cutoff_percentage": cutoff_percentage}
)

Vaihe 4: Rekisteröi lopullinen ML-malli

Käytä MLflow'ta seuraamaan ja kirjaamaan kaikki kokeet sekä hoito- että kontrolliryhmille. Tämä seuranta- ja lokitusprosessi sisältää vastaavat parametrit, mittarit ja mallit. Kirjaa nämä tiedot kokeen nimeen työtilassa myöhempää käyttöä varten.

# Register the model
treatment_model_uri = "runs:/{}/model".format(treatment_run_id)
mlflow.register_model(treatment_model_uri, f"{EXPERIMENT_NAME}-treatmentmodel")

control_model_uri = "runs:/{}/model".format(control_run_id)
mlflow.register_model(control_model_uri, f"{EXPERIMENT_NAME}-controlmodel")

mlflow.end_run()

Voit tarkastella kokeitasi:

  1. Valitse vasemmassa paneelissa työtilasi.
  2. Etsi ja valitse kokeilun nimi, tässä tapauksessa aisample-upliftmodelling-.

Näyttökuva, joka näyttää erinomaiset mallinnuskokeilutulokset.

Vaihe 5: Tallenna ennustetulokset

Microsoft Fabric tarjoaa PREDICT-toiminnon, skaalautuvan toiminnon, joka tukee eräpisteytystä missä tahansa laskentamoottorissa. Sen avulla asiakkaat voivat operationalisoida koneoppimismalleja. Käyttäjät voivat luoda eräennusteita suoraan muistikirjasta tai tietyn mallin kohdesivulta. Lisätietoja PREDICTistä ja sen käytöstä Microsoft Fabric -sovelluksessa löydät Koneoppimismallien pisteytyksestä PREDICTillä.

# Load the model back
loaded_treatmentmodel = mlflow.spark.load_model(treatment_model_uri, dfs_tmpdir="Files/spark")
loaded_controlmodel = mlflow.spark.load_model(control_model_uri, dfs_tmpdir="Files/spark")

# Make predictions
batch_predictions_treatment = loaded_treatmentmodel.transform(test_df)
batch_predictions_control = loaded_controlmodel.transform(test_df)
batch_predictions_treatment.show(5)
# Save the predictions in the lakehouse
batch_predictions_treatment.write.format("delta").mode("overwrite").save(
    f"{DATA_FOLDER}/predictions/batch_predictions_treatment"
)
batch_predictions_control.write.format("delta").mode("overwrite").save(
    f"{DATA_FOLDER}/predictions/batch_predictions_control"
)
# Determine the entire runtime
print(f"Full run cost {int(time.time() - ts)} seconds.")