Tutorial: Erstellen, Auswerten und Bewerten eines Churn-Erkennungsmodells

Dieses Tutorial stellt ein umfassendes Beispiel für einen Synapse Data Science-Workflow in Microsoft Fabric vor. In dem Szenario wird ein Modell erstellen, um vorherzusagen, ob Bankkunden abwandern. Die Abwanderungs- oder Schwundrate entspricht der Rate, mit der Bankkunden ihre Geschäftsbeziehung mit der Bank beenden.

Dieses Tutorial umfasst die folgenden Schritte:

  • Installieren von benutzerdefinierten Bibliotheken
  • Laden der Daten
  • Verstehen und Verarbeiten der Daten durch explorative Datenanalyse und Darstellung der Verwendung des Fabric Data Wrangler-Features
  • Trainieren von Machine Learning-Modellen mit Scikit-Learn und LightGBM und Nachverfolgen von Experimenten mit den automatischen Protokollierungsfunktionen von MLflow und Fabric
  • Auswerten und Speichern des endgültigen Machine Learning-Modells
  • Darstellen der Modellleistung mit Power BI-Visualisierungen

Voraussetzungen

Notebook für das Tutorial

Für das Notebook können Sie eine der folgenden Optionen wählen:

  • Öffnen Sie das integrierte Notebook in der Data Science-Umgebung, und führen Sie es aus
  • Laden Sie Ihr Notebook von GitHub in die Data Science-Umgebung hoch

Öffnen des integrierten Notebooks

Das Beispiel Kundenabwanderung ist das Notebook, das dieses Tutorial begleitet.

So öffnen Sie das integrierte Beispiel-Notebook für das Tutorial in der Synapse Data Science-Umgebung:

  1. Wechseln Sie zur Synapse Data Science-Startseite.

  2. Wählen Sie Beispiel verwenden aus.

  3. Wählen Sie das zugehörige Beispiel aus:

    • Wählen Sie es auf der Standardregisterkarte End-to-End-Workflows (Python) aus, wenn es sich bei dem Beispiel um ein Python-Tutorial handelt.
    • Wählen Sie es auf der Registerkarte End-to-End-Workflows (R) aus, wenn es sich bei dem Beispiel um ein R-Tutorial handelt.
    • Wählen Sie es auf der Registerkarte Schnelltutorials aus, wenn es sich bei dem Beispiel um ein Schnelltutorial handelt.
  4. Fügen Sie ein Lakehouse an das Notebook an, bevor Sie mit der Ausführung von Code beginnen.

Importieren des Notebooks von GitHub

AIsample – Bank Customer Churn.ipynb ist das Notebook, das dieses Tutorial begleitet.

Befolgen Sie zum Öffnen des zugehörigen Notebooks für dieses Tutorial die Anweisungen unter Vorbereiten Ihres Systems für Data Science-Tutorials zum Importieren des Notebooks in Ihren Arbeitsbereich.

Wenn Sie den Code lieber von dieser Seite kopieren und einfügen möchten, können Sie auch ein neues Notebook erstellen.

Fügen Sie unbedingt ein Lakehouse an das Notebook an, bevor Sie mit der Ausführung von Code beginnen.

Schritt 1: Installieren von benutzerdefinierten Bibliotheken

Für die Entwicklung eines Machine Learning-Modells oder für Ad-hoc-Datenanalysen müssen Sie u. U. schnell eine benutzerdefinierte Bibliothek für Ihre Apache Spark-Sitzung installieren. Sie haben zwei Optionen zum Installieren von Bibliotheken.

  • Verwenden Sie die Inline-Installationsfunktionen (%pip oder %conda) Ihres Notebooks zum Erstellen einer Bibliothek nur in Ihrem aktuellen Notebook.
  • Alternativ können Sie eine Fabric-Umgebung erstellen, Bibliotheken aus öffentlichen Quellen installieren oder benutzerdefinierte Bibliotheken darauf hochladen, und dann kann Ihr Arbeitsbereichsadministrator die Umgebung als Standard für den Arbeitsbereich anfügen. Alle Bibliotheken in der Umgebung werden dann für die Verwendung in allen Notebooks und Spark-Auftragsdefinitionen im Arbeitsbereich verfügbar. Weitere Informationen zu Umgebungen finden Sie unter Erstellen, Konfigurieren und Verwenden einer Umgebung in Microsoft Fabric.

Verwenden Sie für dieses Tutorial %pip install zum Installieren der imblearn-Bibliothek in Ihrem Notebook.

Hinweis

Der PySpark-Kernel startet neu, nachdem %pip install gelaufen ist. Installieren Sie die benötigten Bibliotheken, bevor Sie andere Zellen ausführen.

# Use pip to install libraries
%pip install imblearn

Schritt 2: Laden der Daten

Das Dataset in churn.csv enthält den Abwanderungsstatus von 10.000 Kunden mit 14 Attributen wie:

  • Kreditwürdigkeit
  • Geografischer Standort (Deutschland, Frankreich, Spanien)
  • Geschlecht (männlich, weiblich)
  • Age
  • Zugehörigkeit (Anzahl der Jahre, in denen die Person Kunde dieser Bank war)
  • Kontostand
  • Geschätztes Gehalt
  • Anzahl der Produkte, die ein Kunde über die Bank erworben hat
  • Kreditkartenstatus (ob ein Kunde über eine Kreditkarte verfügt oder nicht)
  • Aktiver Mitgliedsstatus (ob die Person ein aktiver Bankkunde ist oder nicht)

Das Dataset enthält auch die Zeilennummer und die Spalten Kunden-ID und Nachname des Kunden. Die Werte in diesen Spalten sollten keinen Einfluss auf die Entscheidung eines Kunden haben, die Bank zu verlassen.

Die Abwanderung eines Kunden ist durch das Schließen seines Bankkontos definiert. Die Dataset-Spalte Exited bezieht sich auf die Abwanderung des Kunden. Da wir nur wenig Kontext zu diesen Attributen haben, benötigen wir keine Hintergrundinformationen zum Dataset. Wir möchten verstehen, wie diese Attribute zum Exited-Status beitragen.

Von diesen 10.000 Kunden haben nur 2037 Kunden (rund 20 %) die Bank verlassen. Angesichts des Klassenungleichgewichts empfehlen wir das Generieren synthetischer Daten. Die Genauigkeit der Konfusionsmatrix ist für die unausgeglichene Klassifizierung eventuell nicht relevant. Wir sollten die Genauigkeit vielleicht mithilfe der Area Under the Precision-Recall Curve (AUPRC) messen.

  • Diese Tabelle enthält eine Vorschau der churn.csv-Daten:
CustomerID Surname CreditScore Geografie Gender (Geschlecht): Age (Alter) – Beschäftigungsdauer Saldo NumOfProducts HasCrCard IsActiveMember EstimatedSalary Ausgetreten
15634602 Hargrave 619 Frankreich Weiblich 42 2 0,00 1 1 1 101348.88 1
15647311 Hill 608 Spanien Weiblich 41 1 83807.86 1 0 1 112542.58 0

Herunterladen des Datensatzes und Hochladen in Lakehouse

Durch Definieren dieser Parameter können Sie dieses Notebook auf verschiedene Datasets anwenden:

IS_CUSTOM_DATA = False  # If TRUE, the dataset has to be uploaded manually

IS_SAMPLE = False  # If TRUE, use only SAMPLE_ROWS of data for training; otherwise, use all data
SAMPLE_ROWS = 5000  # If IS_SAMPLE is True, use only this number of rows for training

DATA_ROOT = "/lakehouse/default"
DATA_FOLDER = "Files/churn"  # Folder with data files
DATA_FILE = "churn.csv"  # Data file name

Dieser Code lädt eine öffentlich verfügbare Version des Datasets herunter und speichert dieses Dataset dann in einem Fabric Lakehouse:

Wichtig

Fügen Sie ein Lakehouse zum Notebook hinzu, bevor Sie es ausführen. Andernfalls kommt es zu einem Fehler.

import os, requests
if not IS_CUSTOM_DATA:
# With an Azure Synapse Analytics blob, this can be done in one line

# Download demo data files into the lakehouse if they don't exist
    remote_url = "https://synapseaisolutionsa.blob.core.windows.net/public/bankcustomerchurn"
    file_list = ["churn.csv"]
    download_path = "/lakehouse/default/Files/churn/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)
    for fname in file_list:
        if not os.path.exists(f"{download_path}/{fname}"):
            r = requests.get(f"{remote_url}/{fname}", timeout=30)
            with open(f"{download_path}/{fname}", "wb") as f:
                f.write(r.content)
    print("Downloaded demo data files into lakehouse.")

Starten Sie die Aufzeichnung der Zeit, die zum Ausführen des Notizbuchs benötigt wird:

# Record the notebook running time
import time

ts = time.time()

Lesen von Rohdaten aus dem Lakehouse

Dieser Code liest die Rohdaten aus dem Abschnitt Dateien des Lakehouse und fügt weitere Spalten für verschiedene Datumsteile hinzu. Zur Erstellung der partitionierten Delta-Tabelle werden diese Informationen verwendet.

df = (
    spark.read.option("header", True)
    .option("inferSchema", True)
    .csv("Files/churn/raw/churn.csv")
    .cache()
)

Erstellen eines Pandas-DataFrames aus dem Datenset

Dieser Code konvertiert den Spark-DataFrame in einen Pandas-DataFrame, um die Verarbeitung und Visualisierung zu vereinfachen:

df = df.toPandas()

Schritt 3: Durchführen einer explorativen Datenanalyse

Anzeigen der Rohdaten

Untersuchen Sie die Rohdaten mit display, berechnen Sie einige grundlegende Statistiken und zeigen Sie Diagrammansichten an. Sie müssen zuerst die erforderlichen Bibliotheken für die Datenvisualisierung importieren, z. B. Seaborn. Seaborn ist eine Python-Datenvisualisierungsbibliothek, die eine allgemeine Schnittstelle zum Erstellen von Visuals für Dataframes und Arrays bietet.

import seaborn as sns
sns.set_theme(style="whitegrid", palette="tab10", rc = {'figure.figsize':(9,6)})
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
from matplotlib import rc, rcParams
import numpy as np
import pandas as pd
import itertools
display(df, summary=True)

Verwenden von Data Wrangler zum Durchführen der anfänglichen Datenbereinigung

Starten Sie Data Wrangler direkt über das Notebook, um Pandas-Dataframes zu untersuchen und zu transformieren. Verwenden Sie auf der Registerkarte Daten des Notebookmenübands die Dropdownaufforderung von Data Wrangler, um die zur Bearbeitung verfügbaren aktivierten Pandas-DataFrames zu durchsuchen. Wählen Sie den DataFrame aus, den Sie in Data Wrangler öffnen möchten.

Hinweis

Data Wrangler kann nicht geöffnet werden, während der Notebookkernel ausgelastet ist. Die Zellenausführung muss vor dem Starten von Data Wrangler beendet sein. Erfahren Sie mehr über Data Wrangler.

Screenshot that shows where to access Data Wrangler.

Nach dem Starten von Data Wrangler wird eine beschreibende Übersicht über das Datenpanel generiert, wie in den folgenden Abbildungen dargestellt. Die Übersicht enthält Informationen zu den Dimensionen des DataFrames, fehlenden Werten usw. Sie können Data Wrangler verwenden, um das Skript zum Entfernen der Zeilen mit fehlenden Werten, der doppelten Zeilen und der Spalten mit bestimmten Namen zu generieren. Anschließend können Sie das Skript in eine Zelle kopieren. Die nächste Zelle zeigt das kopierte Skript an.

Screenshot that shows the Data Wrangler menu.

Screenshot that shows missing data in Data Wrangler.

def clean_data(df):
    # Drop rows with missing data across all columns
    df.dropna(inplace=True)
    # Drop duplicate rows in columns: 'RowNumber', 'CustomerId'
    df.drop_duplicates(subset=['RowNumber', 'CustomerId'], inplace=True)
    # Drop columns: 'RowNumber', 'CustomerId', 'Surname'
    df.drop(columns=['RowNumber', 'CustomerId', 'Surname'], inplace=True)
    return df

df_clean = clean_data(df.copy())

Bestimmen von Attributen

Dieser Code ermittelt kategorisierte, numerische und Zielattribute:

# Determine the dependent (target) attribute
dependent_variable_name = "Exited"
print(dependent_variable_name)
# Determine the categorical attributes
categorical_variables = [col for col in df_clean.columns if col in "O"
                        or df_clean[col].nunique() <=5
                        and col not in "Exited"]
print(categorical_variables)
# Determine the numerical attributes
numeric_variables = [col for col in df_clean.columns if df_clean[col].dtype != "object"
                        and df_clean[col].nunique() >5]
print(numeric_variables)

Anzeigen der fünfzahligen Zusammenfassung

Verwenden von Boxplots zum Anzeigen der fünfzahligen Zusammenfassung

  • minimale Bewertung
  • erstes Quartil
  • Median
  • drittes Quartil
  • maximale Bewertung

für die numerischen Attribute.

df_num_cols = df_clean[numeric_variables]
sns.set(font_scale = 0.7) 
fig, axes = plt.subplots(nrows = 2, ncols = 3, gridspec_kw =  dict(hspace=0.3), figsize = (17,8))
fig.tight_layout()
for ax,col in zip(axes.flatten(), df_num_cols.columns):
    sns.boxplot(x = df_num_cols[col], color='green', ax = ax)
# fig.suptitle('visualize and compare the distribution and central tendency of numerical attributes', color = 'k', fontsize = 12)
fig.delaxes(axes[1,2])

Screenshot that shows a notebook display of the box plot for numerical attributes.

Anzeige der Verteilung abgewanderter und nicht abgewanderter Kunden

Zeigen Sie die Verteilung abgewanderter und nicht abgewanderter Kunden über die kategorisierten Attribute hinweg an:

attr_list = ['Geography', 'Gender', 'HasCrCard', 'IsActiveMember', 'NumOfProducts', 'Tenure']
fig, axarr = plt.subplots(2, 3, figsize=(15, 4))
for ind, item in enumerate (attr_list):
    sns.countplot(x = item, hue = 'Exited', data = df_clean, ax = axarr[ind%2][ind//2])
fig.subplots_adjust(hspace=0.7)

Screenshot that shows a notebook display of the distribution of exited versus non-exited customers.

Anzeige der Verteilung numerischer Attribute

Zeigen Sie anhand eines Histogramms die Häufigkeitsverteilung numerischer Attribute an:

columns = df_num_cols.columns[: len(df_num_cols.columns)]
fig = plt.figure()
fig.set_size_inches(18, 8)
length = len(columns)
for i,j in itertools.zip_longest(columns, range(length)):
    plt.subplot((length // 2), 3, j+1)
    plt.subplots_adjust(wspace = 0.2, hspace = 0.5)
    df_num_cols[i].hist(bins = 20, edgecolor = 'black')
    plt.title(i)
# fig = fig.suptitle('distribution of numerical attributes', color = 'r' ,fontsize = 14)
plt.show()

Screenshot that shows a notebook display of numerical attributes.

Durchführen des Feature Engineerings

Dieses Feature Engineering generiert neue Attribute basierend auf aktuellen Attributen:

df_clean["NewTenure"] = df_clean["Tenure"]/df_clean["Age"]
df_clean["NewCreditsScore"] = pd.qcut(df_clean['CreditScore'], 6, labels = [1, 2, 3, 4, 5, 6])
df_clean["NewAgeScore"] = pd.qcut(df_clean['Age'], 8, labels = [1, 2, 3, 4, 5, 6, 7, 8])
df_clean["NewBalanceScore"] = pd.qcut(df_clean['Balance'].rank(method="first"), 5, labels = [1, 2, 3, 4, 5])
df_clean["NewEstSalaryScore"] = pd.qcut(df_clean['EstimatedSalary'], 10, labels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

Verwenden von Data Wrangler zum Ausführen einer einseitigen Codierung

Verwenden Sie nach den gleichen oben beschriebenen Schritten zum Starten von Data Wrangler den Data Wrangler, um eine einmalige Codierung auszuführen. Diese Zelle zeigt das kopierte generierte Skript für die Codierung für eine einmalige Codierung an:

Screenshot that shows one-hot encoding in Data Wrangler.

Screenshot that shows the selection of columns in Data Wrangler.

df_clean = pd.get_dummies(df_clean, columns=['Geography', 'Gender'])

Erstellen einer Delta-Tabelle zum Generieren des Power BI-Berichts

table_name = "df_clean"
# Create a PySpark DataFrame from pandas
sparkDF=spark.createDataFrame(df_clean) 
sparkDF.write.mode("overwrite").format("delta").save(f"Tables/{table_name}")
print(f"Spark DataFrame saved to delta table: {table_name}")

Zusammenfassung der Beobachtungen aus der explorativen Datenanalyse

  • Die meisten Kunden stammen aus Frankreich. Spanien hat die niedrigste Abwanderungsrate im Vergleich zu Frankreich und Deutschland.
  • Die meisten Kunden haben Kreditkarten
  • Einige Kunden sind sowohl älter als 60 Jahre und haben eine Kreditwürdigkeit unter 400. Sie können jedoch nicht als Ausreißer betrachtet werden
  • Sehr wenige Kunden verfügen über mehr als zwei Produkte der Bank
  • Bei inaktiven Kunden haben ist die Abwanderungsrate höher
  • Geschlecht und Jahre der Zugehörigkeit haben nur einen geringen Einfluss auf die Entscheidung des Kunden, das Bankkonto zu schließen

Schritt 4: Ausführen von Training und Verfolgung des Modells

Da die Daten jetzt vorhanden sind, können Sie das Modell definieren. Wenden Sie in diesem Notebook Random Forest- und LightGBM-Modelle an.

Verwenden Sie die Scikit-Learn- und LightGBM-Bibliotheken, um die Modelle mit wenigen Codezeilen zu implementieren. Verwenden Sie zudem die automatische Protokollierung in MLfLow und Fabric, um die Experimente nachzuverfolgen.

In diesem Codebeispiel wird die Delta-Tabelle aus dem Lakehouse geladen. Sie können andere Delta-Tabellen verwenden, die ihrerseits Lakehouse als Quelle nutzen.

SEED = 12345
df_clean = spark.read.format("delta").load("Tables/df_clean").toPandas()

Generieren eines Experiments zum Nachverfolgen und Protokollieren der Modelle mithilfe von MLflow

Dieser Abschnitt beschreibt das Generieren eines Experiments und gibt die Modell- und Trainingsparameter sowie die Bewertungsmetriken an. Darüber hinaus wird gezeigt, wie Sie die Modelle trainieren, protokollieren und die trainierten Modelle zur späteren Verwendung speichern können.

import mlflow

# Set up the experiment name
EXPERIMENT_NAME = "sample-bank-churn-experiment"  # MLflow experiment name

Die automatische Protokollierung erfasst automatisch sowohl die Werte von Eingabeparametern als auch die Ausgabemetriken eines Machine Learning-Modells, während es trainiert wird. Diese Informationen werden dann in Ihrem Arbeitsbereich protokolliert, wo die MLflow-APIs oder das entsprechende Experiment in Ihrem Arbeitsbereich auf sie zugreifen und sie visualisieren können.

Wenn das Experiment abgeschlossen ist, sieht es ähnlich wie auf diesem Bild aus:

Screenshot that shows the experiment page for the bank churn experiment.

Alle Experimente mit ihren jeweiligen Namen werden protokolliert, und Sie können ihre Parameter und Leistungsmetriken nachverfolgen. Weitere Informationen zur automatischen Protokollierung finden Sie unter Automatische Protokollierung in Microsoft Fabric.

Festlegen von Experiment- und Autoprotokollierungsspezifikationen

mlflow.set_experiment(EXPERIMENT_NAME) # Use a date stamp to append to the experiment
mlflow.autolog(exclusive=False)

Importieren von scikit-learn und LightGBM

# Import the required libraries for model training
from sklearn.model_selection import train_test_split
from lightgbm import LGBMClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, f1_score, precision_score, confusion_matrix, recall_score, roc_auc_score, classification_report

Erstellen von Trainings- und Testdatensätzen

y = df_clean["Exited"]
X = df_clean.drop("Exited",axis=1)
# Train/test separation
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=SEED)

Anwenden von SMOTE auf die Trainingsdaten

Die unausgeglichene Klassifizierung stellt ein Problem dar, weil es zu wenige Beispiele für die Minderheitsklasse für ein Modell gibt, um die Entscheidungsgrenze effektiv zu erlernen. Zum Beheben dieses Problems ist Synthetic Minority Oversampling Technique (SMOTE) der am häufigsten verwendete Ansatz, um neue Stichproben für die Minderheitsklasse zu synthetisieren. Greifen Sie mithilfe der imblearn-Bibliothek, die Sie in Schritt 1 installiert haben, auf SMOTE zu.

Wenden Sie SMOTE auf die Trainingsdaten an. Sie müssen das Testdataset in seiner ursprünglichen unausgeglichenen Verteilung belassen, um ein gültigen Näherungswert für die Modellleistung mit den ursprünglichen Daten zu erhalten. Dieses Experiment stellt die Situation in der Produktion dar.

from collections import Counter
from imblearn.over_sampling import SMOTE

sm = SMOTE(random_state=SEED)
X_res, y_res = sm.fit_resample(X_train, y_train)
new_train = pd.concat([X_res, y_res], axis=1)

Weitere Informationen finden Sie unter SMOTE und From random over-sampling to SMOTE and ADASYN. Diese Ressourcen sind auf der Imbalanced-Learn-Website zu finden.

Modelltraining

Trainieren Sie das Modell mit Random Forest mit einer maximalen Tiefe von vier und mit vier Features:

mlflow.sklearn.autolog(registered_model_name='rfc1_sm')  # Register the trained model with autologging
rfc1_sm = RandomForestClassifier(max_depth=4, max_features=4, min_samples_split=3, random_state=1) # Pass hyperparameters
with mlflow.start_run(run_name="rfc1_sm") as run:
    rfc1_sm_run_id = run.info.run_id # Capture run_id for model prediction later
    print("run_id: {}; status: {}".format(rfc1_sm_run_id, run.info.status))
    # rfc1.fit(X_train,y_train) # Imbalanced training data
    rfc1_sm.fit(X_res, y_res.ravel()) # Balanced training data
    rfc1_sm.score(X_test, y_test)
    y_pred = rfc1_sm.predict(X_test)
    cr_rfc1_sm = classification_report(y_test, y_pred)
    cm_rfc1_sm = confusion_matrix(y_test, y_pred)
    roc_auc_rfc1_sm = roc_auc_score(y_res, rfc1_sm.predict_proba(X_res)[:, 1])

Trainieren Sie das Modell mit Random Forest mit einer maximalen Tiefe von acht und mit sechs Features:

mlflow.sklearn.autolog(registered_model_name='rfc2_sm')  # Register the trained model with autologging
rfc2_sm = RandomForestClassifier(max_depth=8, max_features=6, min_samples_split=3, random_state=1) # Pass hyperparameters
with mlflow.start_run(run_name="rfc2_sm") as run:
    rfc2_sm_run_id = run.info.run_id # Capture run_id for model prediction later
    print("run_id: {}; status: {}".format(rfc2_sm_run_id, run.info.status))
    # rfc2.fit(X_train,y_train) # Imbalanced training data
    rfc2_sm.fit(X_res, y_res.ravel()) # Balanced training data
    rfc2_sm.score(X_test, y_test)
    y_pred = rfc2_sm.predict(X_test)
    cr_rfc2_sm = classification_report(y_test, y_pred)
    cm_rfc2_sm = confusion_matrix(y_test, y_pred)
    roc_auc_rfc2_sm = roc_auc_score(y_res, rfc2_sm.predict_proba(X_res)[:, 1])

Trainieren Sie das Modell mithilfe von LightGBM:

# lgbm_model
mlflow.lightgbm.autolog(registered_model_name='lgbm_sm')  # Register the trained model with autologging
lgbm_sm_model = LGBMClassifier(learning_rate = 0.07, 
                        max_delta_step = 2, 
                        n_estimators = 100,
                        max_depth = 10, 
                        eval_metric = "logloss", 
                        objective='binary', 
                        random_state=42)

with mlflow.start_run(run_name="lgbm_sm") as run:
    lgbm1_sm_run_id = run.info.run_id # Capture run_id for model prediction later
    # lgbm_sm_model.fit(X_train,y_train) # Imbalanced training data
    lgbm_sm_model.fit(X_res, y_res.ravel()) # Balanced training data
    y_pred = lgbm_sm_model.predict(X_test)
    accuracy = accuracy_score(y_test, y_pred)
    cr_lgbm_sm = classification_report(y_test, y_pred)
    cm_lgbm_sm = confusion_matrix(y_test, y_pred)
    roc_auc_lgbm_sm = roc_auc_score(y_res, lgbm_sm_model.predict_proba(X_res)[:, 1])

Anzeigen des Experimentartefakts zur Nachverfolgung der Modellleistung

Die Experimentausführungen werden automatisch im Experimentartefakt gespeichert. Sie finden dieses Artefakt im Arbeitsbereich. Ein Artefaktname basiert auf dem zur Einrichtung des Experiments verwendeten Namen. Alle trainierten Modelle, ihre Ausführungen, Leistungsmetriken und Modellparameter werden auf der Experimentseite protokolliert.

So zeigen Sie Ihre Experimente an:

  1. Wählen Sie im linken Fensterbereich Ihren Arbeitsbereich aus.
  2. Suchen Sie den Namen des Experiments und wählen Sie ihn aus, in diesem Fall sample-bank-churn-experiment.

Screenshot that shows logged values for one of the models.

Schritt 5: Auswerten und Speichern des endgültigen Machine Learning-Modells

Öffnen Sie das gespeicherte Experiment aus dem Arbeitsbereich, um das beste Modell auszuwählen und zu speichern:

# Define run_uri to fetch the model
# MLflow client: mlflow.model.url, list model
load_model_rfc1_sm = mlflow.sklearn.load_model(f"runs:/{rfc1_sm_run_id}/model")
load_model_rfc2_sm = mlflow.sklearn.load_model(f"runs:/{rfc2_sm_run_id}/model")
load_model_lgbm1_sm = mlflow.lightgbm.load_model(f"runs:/{lgbm1_sm_run_id}/model")

Bewerten der Leistung der gespeicherten Modelle im Testdataset

ypred_rfc1_sm = load_model_rfc1_sm.predict(X_test) # Random forest with maximum depth of 4 and 4 features
ypred_rfc2_sm = load_model_rfc2_sm.predict(X_test) # Random forest with maximum depth of 8 and 6 features
ypred_lgbm1_sm = load_model_lgbm1_sm.predict(X_test) # LightGBM

Anzeigen von True/False Positives/Negatives mit einer Konfusionsmatrix

Erstellen Sie zum Bewerten der Genauigkeit ein Skript, das eine Konfusionsmatrix zeichnet. Sie können auch eine Konfusionsmatix mit SynapseML-Tools darstellen, wie im Betrugserkennungsbeispiel gezeigt.

def plot_confusion_matrix(cm, classes,
                          normalize=False,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    print(cm)
    plt.figure(figsize=(4,4))
    plt.rcParams.update({'font.size': 10})
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=45, color="blue")
    plt.yticks(tick_marks, classes, color="blue")

    fmt = '.2f' if normalize else 'd'
    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, format(cm[i, j], fmt),
                 horizontalalignment="center",
                 color="red" if cm[i, j] > thresh else "black")

    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')

Erstellen Sie eine Konfusionsmatix für den Random-Forest-Klassifizierer mit einer maximalen Tiefe von vier und mit vier Features:

cfm = confusion_matrix(y_test, y_pred=ypred_rfc1_sm)
plot_confusion_matrix(cfm, classes=['Non Churn','Churn'],
                      title='Random Forest with max depth of 4')
tn, fp, fn, tp = cfm.ravel()

Screenshot that shows a notebook display of a confusion matrix for random forest with a maximum depth of four.

Erstellen Sie eine Konfusionsmatix für den Random-Forest-Klassifizierer mit einer maximalen Tiefe von acht und mit sechs Features:

cfm = confusion_matrix(y_test, y_pred=ypred_rfc2_sm)
plot_confusion_matrix(cfm, classes=['Non Churn','Churn'],
                      title='Random Forest with max depth of 8')
tn, fp, fn, tp = cfm.ravel()

Screenshot that shows a notebook display of a confusion matrix for random forest with a maximum depth of eight.

Erstellen Sie eine Konfusionsmatrix für LightGBM:

cfm = confusion_matrix(y_test, y_pred=ypred_lgbm1_sm)
plot_confusion_matrix(cfm, classes=['Non Churn','Churn'],
                      title='LightGBM')
tn, fp, fn, tp = cfm.ravel()

Screenshot that shows a notebook display of a confusion matrix for LightGBM.

Speichern von Ergebnissen für Power BI

Speichern Sie den Deltaframe im Lakehouse, um die Modellvorhersageergebnisse in eine Power BI-Visualisierung zu übertragen.

df_pred = X_test.copy()
df_pred['y_test'] = y_test
df_pred['ypred_rfc1_sm'] = ypred_rfc1_sm
df_pred['ypred_rfc2_sm'] =ypred_rfc2_sm
df_pred['ypred_lgbm1_sm'] = ypred_lgbm1_sm
table_name = "df_pred_results"
sparkDF=spark.createDataFrame(df_pred)
sparkDF.write.mode("overwrite").format("delta").option("overwriteSchema", "true").save(f"Tables/{table_name}")
print(f"Spark DataFrame saved to delta table: {table_name}")

Schritt 6: Zugreifen auf Visualisierungen in Power BI

Greifen Sie in Power BI auf Ihre gespeicherte Tabelle zu:

  1. Wählen Sie links OneLake Data Hub aus
  2. Wählen Sie das Lakehouse aus, das Sie diesem Notebook hinzugefügt haben
  3. Wählen Sie im Abschnitt Dieses Lakehouse öffnen die Option Öffnen aus
  4. Wählen Sie im Menüband Neues semantisches Modell aus. Wählen Sie df_pred_results und dann Weiter aus, um ein neues semantisches Power BI-Modell zu erstellen, das mit den Vorhersagedaten verknüpft ist
  5. Wählen Sie bei den Tools oben auf der Seite des Semantikmodells die Option Neuer Bericht aus, um die Power BI-Dokumenterstellungsseite zu öffnen

Der folgende Screenshot zeigt einige Beispiele für Visualisierungen. Im Datenbereich werden die Delta-Tabellen und die Spalten angezeigt, die aus einer Tabelle auszuwählen sind. Nach Auswahl der entsprechenden Kategorie- (x) und Wertachse (y) können Sie die Filter und Funktionen auswählen, z. B. Summe oder Mittelwert der Tabellenspalte.

Hinweis

In diesem Screenshot beschreibt das dargestellte Beispiel die Analyse der gespeicherten Vorhersageergebnisse in Power BI:

Screenshot that shows a Power BI dashboard example.

Für einen echten Kundenabwanderungsfall braucht der Benutzer jedoch möglicherweise einen genaueren Satz von Anforderungen für die zu erstellenden Visualisierungen ausgehend von seinem Fachwissen und den vom Unternehmen und vom Business Analytics-Team standardmäßig verwendeten Metriken.

Der Power BI-Bericht zeigt, dass Kunden, die mehr als zwei der Bankprodukte verwenden, eine höhere Abwanderungsrate aufweisen. Allerdings hatten nur wenige Kunden mehr als zwei Produkte. (Siehe Plot im Bereich links unten.) Die Bank sollte weitere Daten sammeln, sollte aber auch andere Features untersuchen, die mit weiteren Produkten korrelieren.

Bei Bankkunden in Deutschland ist im Vergleich zu Kunden in Frankreich und Spanien eine höhere Abwanderungsrate zu verzeichnen. (Siehe Plot im Bereich rechts unten). Basierend auf den Berichtsergebnissen könnte eine Untersuchung der Faktoren, die Kunden zur Abwanderung veranlassen, hilfreich sein.

Es gibt mehr Kunden im mittleren Alter (zwischen 25 und 45). Kunden zwischen 45 und 60 neigen stärker zur Abwanderung.

Bei Kunden mit geringer Kreditwürdigkeit ist die Wahrscheinlichkeit der Abwanderung zu anderen Finanzinstituten schließlich am größten. Die Bank sollte nach Möglichkeiten suchen, die Kunden mit geringer Kreditwürdigkeit und niedrigen Kontosalden darin zu bestärken, bei der Bank zu bleiben.

# Determine the entire runtime
print(f"Full run cost {int(time.time() - ts)} seconds.")