Membuat, melatih, dan mengevaluasi model uplift di Microsoft Fabric
Dalam artikel ini, pelajari cara membuat, melatih, dan mengevaluasi model peningkatan dan menerapkan teknik pemodelan peningkatan.
Penting
Microsoft Fabric saat ini dalam PRATINJAU. Informasi ini berkaitan dengan produk prarilis yang mungkin dimodifikasi secara substansial sebelum dirilis. Microsoft tidak memberikan jaminan, dinyatakan atau tersirat, sehubungan dengan informasi yang diberikan di sini.
Apa itu pemodelan yang lebih baik?
Ini adalah keluarga teknologi inferensi kausal yang menggunakan model pembelajaran mesin untuk memperkirakan efek kausal dari beberapa perawatan pada perilaku individu.
- Persuadables hanya merespons positif terhadap perawatan
- Sleeping-dogs memiliki respons negatif yang kuat terhadap perawatan
- Kehilangan penyebab tidak pernah mencapai hasil bahkan dengan perawatan
- Yakin hal-hal selalu mencapai hasil dengan atau tanpa perawatan
Tujuan pemodelan uplift adalah untuk mengidentifikasi "persuadables", tidak membuang-buang upaya pada "yakin hal-hal" dan "kehilangan penyebab", dan menghindari mengganggu "anjing tidur"
Bagaimana cara kerja pemodelan uplift?
- Meta Learner: memprediksi perbedaan antara perilaku individu ketika ada perawatan dan ketika tidak ada perawatan
- Uplift Tree: algoritma berbasis pohon di mana kriteria pemisahan didasarkan pada perbedaan peningkatan
- Model berbasis NN:model jaringan neural yang biasanya berfungsi dengan data pengamatan
Di mana pemodelan yang dapat ditingkatkan berfungsi?
- Pemasaran: membantu mengidentifikasi persuadables untuk menerapkan perawatan seperti kupon atau iklan online
- Perawatan Medis: membantu memahami bagaimana perawatan dapat memengaruhi kelompok tertentu secara berbeda
Prasyarat
- Pemahaman tentang Cara menggunakan notebook Microsoft Fabric.
- Sebuah Lakehouse. Lakehouse digunakan untuk menyimpan data untuk contoh ini. Untuk informasi selengkapnya, lihat Menambahkan Lakehouse ke buku catatan Anda.
Langkah 1: Muat data
Tip
Contoh berikut mengasumsikan bahwa Anda menjalankan kode dari sel di buku catatan. Untuk informasi tentang membuat dan menggunakan buku catatan, lihat Cara menggunakan buku catatan.
Konfigurasi buku catatan
Dengan menentukan parameter di bawah ini, Anda dapat menerapkan contoh ini ke himpunan data yang berbeda.
IS_CUSTOM_DATA = False # if True, dataset has to be uploaded manually by user
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
Mengimpor dependensi
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 os
import gzip
import mlflow
Mengunduh himpunan data dan mengunggah ke Lakehouse
Penting
Tambahkan Lakehouse ke buku catatan Anda sebelum menjalankannya.
Deskripsi himpunan data: Criteo AI Lab membuat himpunan data ini. Himpunan data terdiri dari baris 13M, masing-masing mewakili pengguna dengan 12 fitur, indikator perawatan dan 2 label biner (kunjungan dan konversi).
- f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11: nilai fitur (padat, mengambang)
- perawatan: grup perawatan (1 = dirawat, 0 = kontrol) yang menunjukkan apakah pelanggan ditargetkan oleh iklan secara acak
- konversi: apakah konversi terjadi untuk pengguna ini (biner, label)
- kunjungi: apakah kunjungan terjadi untuk pengguna ini (biner, label)
Beranda himpunan data: https://ailab.criteo.com/criteo-uplift-prediction-dataset/
Rujukan:
@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} }
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.")
Membaca data dari Lakehouse
raw_df = spark.read.csv(
f"{DATA_FOLDER}/raw/{DATA_FILE}", header=True, inferSchema=True
).cache()
display(raw_df.limit(20))
Langkah 2: Menyiapkan himpunan data
Eksplorasi data
Tingkat keseluruhan pengguna yang mengunjungi/mengonversi
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()
Efek pengobatan rata-rata keseluruhan pada kunjungan
raw_df.groupby("treatment").agg( F.mean("visit").alias("Mean of visit"), F.sum("visit").alias("Sum of visit"), F.count("visit").alias("Count"), ).show()
Efek perawatan rata-rata keseluruhan pada konversi
raw_df.groupby("treatment").agg( F.mean("conversion").alias("Mean of conversion"), F.sum("conversion").alias("Sum of conversion"), F.count("conversion").alias("Count"), ).show()
Memisahkan himpunan data uji pelatihan
transformer = (
Featurize().setOutputCol("features").setInputCols(FEATURE_COLUMNS).fit(raw_df)
)
df = transformer.transform(raw_df)
train_df, test_df = df.randomSplit([0.8, 0.2], seed=42)
print("Size of train dataset: %d" % train_df.count())
print("Size of test dataset: %d" % test_df.count())
train_df.groupby(TREATMENT_COLUMN).count().show()
Memisahkan himpunan data kontrol perawatan
treatment_train_df = train_df.where(f"{TREATMENT_COLUMN} > 0")
control_train_df = train_df.where(f"{TREATMENT_COLUMN} = 0")
Langkah 3: Pelatihan dan evaluasi model
Pemodelan uplift: T-Learner dengan LightGBM
classifier = (
LightGBMClassifier()
.setFeaturesCol("features")
.setNumLeaves(10)
.setNumIterations(100)
.setObjective("binary")
.setLabelCol(LABEL_COLUMN)
)
treatment_model = classifier.fit(treatment_train_df)
control_model = classifier.fit(control_train_df)
Memprediksi himpunan data pengujian
getPred = F.udf(lambda v: float(v[1]), FloatType())
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(test_pred_df.limit(20))
Evaluasi model
Karena peningkatan aktual tidak dapat diamati untuk setiap individu, ukur peningkatan atas sekelompok pelanggan.
- Kurva Peningkatan: memplot peningkatan kumulatif nyata di seluruh populasi
Pertama, beri peringkat urutan dataframe pengujian berdasarkan peningkatan prediksi.
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))
Selanjutnya, hitung persentase kumulatif kunjungan di setiap kelompok (perawatan atau kontrol).
C = test_ranked_df.where(f"{TREATMENT_COLUMN} == 0").count()
T = test_ranked_df.where(f"{TREATMENT_COLUMN} != 0").count()
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(test_ranked_df.limit(20))
Terakhir, hitung peningkatan grup pada setiap persentase.
test_ranked_df = test_ranked_df.withColumn(
"group_uplift", F.col("treatment_cumsum") - F.col("control_cumsum")
).cache()
display(test_ranked_df.limit(20))
Sekarang Anda dapat memplot kurva peningkatan pada prediksi himpunan data pengujian. Anda perlu mengonversi dataframe pyspark ke dataframe pandas sebelum merencanakan.
def uplift_plot(uplift_df):
"""
Plot the uplift curve
"""
gain_x = uplift_df.percent_rank
gain_y = uplift_df.group_uplift
# plot the data
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("Porportion Targeted")
plt.ylabel("Uplift")
plt.grid(b=True, which="major")
return ax
test_ranked_pd_df = test_ranked_df.select(
["pred_uplift", "percent_rank", "group_uplift"]
).toPandas()
uplift_plot(test_ranked_pd_df)
Dari kurva peningkatan dalam contoh sebelumnya, perhatikan bahwa populasi 20% teratas yang diberi peringkat oleh prediksi Anda memiliki keuntungan besar jika mereka diberi perawatan, yang berarti mereka adalah yang dibujuk. Oleh karena itu, Anda dapat mencetak skor cutoff pada persentase 20% untuk mengidentifikasi pelanggan target.
cutoff_percentage = 0.2
cutoff_score = test_ranked_pd_df.iloc[int(len(test_ranked_pd_df) * cutoff_percentage)][
"pred_uplift"
]
print("Uplift score higher than {:.4f} are Persuadables".format(cutoff_score))
Mencatat dan memuat model dengan MLflow
Sekarang setelah Anda memiliki model terlatih, simpan untuk digunakan nanti. Dalam contoh berikut, MLflow digunakan untuk mencatat metrik dan model. Anda juga dapat menggunakan API ini untuk memuat model untuk prediksi.
# setup mlflow
mlflow.set_experiment(EXPERIMENT_NAME)
# log model, metrics and params
with mlflow.start_run() as run:
print("log model:")
mlflow.spark.log_model(
treatment_model,
f"{EXPERIMENT_NAME}-treatmentmodel",
registered_model_name=f"{EXPERIMENT_NAME}-treatmentmodel",
dfs_tmpdir="Files/spark",
)
mlflow.spark.log_model(
control_model,
f"{EXPERIMENT_NAME}-controlmodel",
registered_model_name=f"{EXPERIMENT_NAME}-controlmodel",
dfs_tmpdir="Files/spark",
)
model_uri = f"runs:/{run.info.run_id}/{EXPERIMENT_NAME}"
print("Model saved in run %s" % run.info.run_id)
print(f"Model URI: {model_uri}-treatmentmodel")
print(f"Model URI: {model_uri}-controlmodel")
# load model back
loaded_treatmentmodel = mlflow.spark.load_model(
f"{model_uri}-treatmentmodel", dfs_tmpdir="Files/spark"
)