Esercitazione: Creare, valutare e assegnare un punteggio a un modello di previsione dell’abbandono

Questa esercitazione presenta un esempio end-to-end di un flusso di lavoro di data science Synapse in Microsoft Fabric. Lo scenario crea un modello per prevedere se i clienti di una banca abbandonano. Il tasso di abbandono, o tasso di attrito, rappresenta il tasso a cui i clienti di una banca terminano il loro rapporto con la banca.

Questa esercitazione comprende i seguenti passaggi:

  • Installare librerie personalizzate
  • Caricare i dati
  • Comprendere ed elaborare i dati tramite l'analisi esplorativa dei dati e mostrare l'uso della funzionalità Data Wrangler di Fabric
  • Usare scikit-learn e LightGBM per eseguire il training di modelli di apprendimento automatico e tenere traccia degli esperimenti con le funzionalità di registrazione automatica di Fabric e MLflow
  • Valutare e salvare il modello di apprendimento automatico finale
  • Visualizzare le prestazioni del modello con le visualizzazioni di Power BI

Prerequisiti

Seguire la procedura in un notebook

È possibile scegliere una di queste opzioni per seguire la procedura in un notebook:

  • Aprire ed eseguire il notebook predefinito nell'esperienza Data Science
  • Caricare il notebook da GitHub nell'esperienza Data Science

Aprire il notebook predefinito

Il notebook di abbandono dei clienti di esempio accompagna questa esercitazione.

Per aprire il notebook di esempio predefinito dell'esercitazione nell'esperienza Synapse Data Science:

  1. Passare alla home page di Synapse Data Science.

  2. Selezionare Usa un esempio.

  3. Selezionare l’esempio corrispondente:

    • Dalla scheda predefinita Flussi di lavoro end-to-end (Python), se l'esempio è relativo a un'esercitazione su Python.
    • Dalla scheda Flussi di lavoro end-to-end (R), se l'esempio è relativo a un'esercitazione su R.
    • Dalla scheda Esercitazioni rapide, se l'esempio è relativo a un'esercitazione rapida.
  4. Collegare un lakehouse al notebook prima di iniziare a eseguire il codice.

Importare il notebook da GitHub

Il notebook AIsample - Bank Customer Churn.ipynb accompagna questa esercitazione.

Per aprire il notebook di accompagnamento per questa esercitazione, seguire le istruzioni riportate in Preparare il sistema per le esercitazioni di data science per importare il notebook nell'area di lavoro.

Se si preferisce copiare e incollare il codice da questa pagina, è possibile creare un nuovo notebook.

Assicurarsi di collegare un lakehouse al notebook prima di iniziare a eseguire il codice.

Passaggio 1: installare librerie personalizzate

Per lo sviluppo di modelli di apprendimento automatico o l'analisi dei dati ad hoc, potrebbe essere necessario installare rapidamente una libreria personalizzata per la sessione di Apache Spark. Sono disponibili due opzioni per installare le librerie.

  • Usare le funzionalità di installazione inline (%pip o %conda) del notebook per installare una libreria solo nel notebook corrente.
  • In alternativa, è possibile creare un ambiente Fabric, installare librerie da origini pubbliche o caricarvi librerie personalizzate e quindi l'amministratore dell'area di lavoro può collegare l'ambiente come predefinito per l'area di lavoro. Tutte le librerie nell'ambiente diventano quindi disponibili per l'uso in qualsiasi notebook e definizione del processo Spark nell'area di lavoro. Per altre informazioni sugli ambienti, vedere creare, configurare e usare un ambiente in Microsoft Fabric.

Per questa esercitazione, usare %pip install per installare la libreria imblearn nel notebook.

Nota

Il kernel PySpark viene riavviato dopo l'esecuzione di %pip install. Installare le librerie necessarie prima di eseguire qualsiasi altra cella.

# Use pip to install libraries
%pip install imblearn

Passaggio 2: caricare i dati

Il set di dati in churn.csv contiene lo stato di abbandono di 10.000 clienti, insieme a 14 attributi che includono:

  • Punteggio sul credito
  • Posizione geografica (Germania, Francia, Spagna)
  • Sesso (maschio, femmina)
  • Età
  • Anzianità (numero di anni in cui la persona è stata cliente in quella banca)
  • Saldo del conto
  • Stipendio stimato
  • Numero di prodotti acquistati da un cliente tramite la banca
  • Stato della carta di credito (se un cliente ha o meno una carta di credito)
  • Stato membro attivo (se la persona è un cliente della banca attivo o meno)

Il set di dati include anche le colonne numero di riga, ID cliente e cognome del cliente. I valori in queste colonne non devono influenzare la decisione di un cliente di lasciare la banca.

Un evento di chiusura del conto bancario del cliente definisce l’abbandono per il cliente. La colonna del set di dati Exited si riferisce all'abbandono del cliente. Dato che questi attributi hanno poco contesto, non sono necessarie informazioni di base sul set di dati. Si vuole comprendere come questi attributi contribuiscono allo stato Exited.

Su questi 10.000 clienti, solo 2037 clienti (circa il 20%) ha lasciato la banca. A causa del rapporto di squilibrio tra classi, è consigliabile generare dati sintetici. L'accuratezza della matrice di confusione potrebbe non avere rilevanza per la classificazione sbilanciata. È possibile misurare l'accuratezza usando l'area sotto la curva di richiamo di precisione (AUPRC).

  • Questa tabella mostra un’anteprima dei dati churn.csv:
CustomerID Cognome CreditScore Geografia Genere Età Anzianità Saldo NumOfProducts HasCrCard IsActiveMember EstimatedSalary Usciti
15634602 Hargrave 619 Francia Femmina 42 2 0.00 1 1 1 101348,88 1
15647311 Hill 608 Spagna Femmina 41 1 83807,86 1 0 1 112542,58 0

Scaricare il set di dati e caricarlo nel lakehouse

Definire questi parametri, in modo da poter usare questo notebook con set di dati diversi:

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

Questo codice scarica una versione disponibile pubblicamente del set di dati, quindi la archivia in un lakehouse di Fabric:

Importante

Aggiungere un lakehouse al notebook prima di eseguirlo. In caso contrario, verrà generato un errore.

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.")

Avviare la registrazione del tempo necessario per eseguire il notebook:

# Record the notebook running time
import time

ts = time.time()

Leggere i dati non elaborati dal lakehouse

Questo codice legge i dati non elaborati dalla sezione Files e aggiunge altre colonne per parti di data diverse. La creazione della tabella delta partizionata usa queste informazioni.

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

Creare un DataFrame Pandas da un set di dati

Questo codice converte il dataframe Spark in un dataframe Pandas, per semplificare l'elaborazione e la visualizzazione:

df = df.toPandas()

Passaggio 3: eseguire l'analisi esplorativa dei dati

Visualizzazione di dati non elaborati

Esplorare i dati non elaborati con display, calcolare alcune statistiche di base e mostrare le visualizzazioni del grafico. È prima necessario importare le librerie necessarie per la visualizzazione dei dati, ad esempio seaborn. Seaborn è una libreria di visualizzazioni dei dati Python che offre un'interfaccia di livello generale per creare oggetti visivi su DataFrame e matrici.

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)

Usare Data Wrangler per eseguire la pulizia iniziale dei dati

Avviare Data Wrangler direttamente dal notebook per esplorare e trasformare i dataframe Pandas. Nella scheda Dati della barra multifunzione del notebook usare il prompt a discesa Data Wrangler per esplorare i DataFrame Pandas attivati disponibili per la modifica. Selezionare il DataFrame da aprire in Data Wrangler.

Nota

Data Wrangler non può essere aperto mentre il kernel del notebook è occupato. L'esecuzione della cella deve terminare prima di avviare Data Wrangler. Altre informazioni su Data Wrangler.

Screenshot che mostra dove accedere a Data Wrangler.

Dopo l'avvio di Data Wrangler, viene generata una panoramica descrittiva del pannello dati, come illustrato nelle immagini seguenti. La panoramica include informazioni sulla dimensione del DataFrame, sugli eventuali valori mancanti e così via. È possibile usare Data Wrangler per generare lo script per eliminare le righe con valori mancanti, le righe duplicate e le colonne con nomi specifici. È quindi possibile copiare lo script in una cella. La cella successiva mostra lo script copiato.

Screenshot che mostra il menu Data Wrangler.

Screenshot che mostra i dati mancanti 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())

Determinazione degli attributi

Questo codice determina gli attributi categorici, numerici e di destinazione:

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

Visualizzare il riepilogo in cinque numeri

Usare i box plot per visualizzare il riepilogo in cinque numeri

  • il punteggio minimo
  • primo quartile
  • mediana
  • terzo quartile
  • punteggio massimo

per gli attributi numerici.

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 che mostra una visualizzazione del notebook del box plot per gli attributi numerici.

Visualizzare la distribuzione dei clienti usciti e non usciti

Visualizzare la distribuzione dei clienti usciti rispetto ai clienti non usciti, tra gli attributi categorici:

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 che mostra una visualizzazione del notebook della distribuzione dei clienti usciti rispetto ai clienti non usciti.

Visualizzare la distribuzione degli attributi numerici

Usare un istogramma per visualizzare la distribuzione della frequenza degli attributi numerici:

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 che mostra una visualizzazione del notebook degli attributi numerici.

Eseguire l'ingegneria delle funzionalità

Questa ingegneria delle funzionalità genera nuovi attributi in base agli attributi correnti:

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

Usare Data Wrangler per eseguire la codifica one-hot

Con gli stessi passaggi per avviare Data Wrangler, come illustrato in precedenza, usare Data Wrangler per eseguire la codifica one-hot. Questa cella mostra lo script generato copiato per la codifica one-hot:

Screenshot che mostra la codifica one-hot in Data Wrangler.

Screenshot che mostra la selezione di colonne in Data Wrangler.

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

Creare una tabella differenziale per generare il report di Power BI

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}")

Riepilogo delle osservazioni dell'analisi esplorativa dei dati

  • La maggior parte dei clienti proviene dalla Francia. La Spagna ha il tasso di abbandono più basso, rispetto alla Francia e alla Germania.
  • La maggior parte dei clienti ha carte di credito
  • Alcuni clienti superano i 60 anni di età e hanno punteggi di credito inferiori a 400. Tuttavia, non possono essere considerati come outlier
  • Pochissimi clienti hanno più di due prodotti bancari
  • I clienti inattivi hanno un tasso di abbandono più elevato
  • Il sesso e gli anni di anzianità hanno un impatto minimo sulla decisione di un cliente di chiudere un conto bancario

Passaggio 4: eseguire il training e il rilevamento del modello

Con i dati disponibili, è ora possibile definire il modello. Applicare modelli casuali di foresta e LightGBM in questo notebook.

Usare le librerie scikit-learn e LightGBM per implementare i modelli, con alcune righe di codice. Usare inoltre MLfLow e la registrazione automatica di Fabric per tenere traccia degli esperimenti.

Questo esempio di codice carica la tabella differenziale dal lakehouse. È possibile usare altre tabelle delta che, a loro volta, usano il lakehouse come origine.

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

Generare un esperimento per monitorare e registrare i modelli usando MLflow

Questa sezione illustra come generare un esperimento e specifica i parametri del modello e del training, nonché le metriche di assegnazione dei punteggi. Illustra inoltre come eseguire il training dei modelli, registrarli e salvare i modelli sottoposti a training per usarli in un secondo momento.

import mlflow

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

L'assegnazione automatica acquisisce automaticamente sia i valori dei parametri di input che le metriche di output di un modello di apprendimento automatico, in quanto viene eseguito il training del modello. Queste informazioni vengono quindi registrate nell'area di lavoro, da cui le API MLflow o l'esperimento corrispondente nell'area di lavoro possono accedervi e visualizzarle.

Al termine, l'esperimento sarà simile all'immagine seguente:

Screenshot che mostra la pagina dell'esperimento per l'esperimento di abbandono della banca.

Tutti gli esperimenti con i rispettivi nomi vengono registrati ed è possibile tenere traccia dei parametri e delle metriche delle prestazioni. Per altre informazioni sulla registrazione automatica, vedere l'articolo Registrazione automatica in Microsoft Fabric.

Impostare le specifiche dell'esperimento e della registrazione automatica

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

Importare scikit-learn e 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

Preparare i set di dati di training e di test

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)

Applicare SMOTE ai dati di training

La classificazione sbilanciata presenta un problema, poiché contiene troppi esempi della classe di minoranza per un modello per apprendere efficacemente il limite decisionale. Per gestire questo problema, Synthetic Minority Oversampling Technique (SMOTE) è la tecnica più usata per sintetizzare nuovi campioni per la classe di minoranza. Accedere a SMOTE con la libreria imblearn installata nel passaggio 1.

Applicare SMOTE solo al set di dati di training. È necessario lasciare il set di dati di test nella distribuzione originale sbilanciata per ottenere un'approssimazione valida delle prestazioni del modello sui dati originali. Questo esperimento rappresenta la situazione in produzione.

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)

Per altre informazioni, vedere SMOTE e Dal sovracampionamento casuale a SMOTE e ADASYN. Il sito Web con apprendimento sbilanciato ospita queste risorse.

Eseguire il training del modello

Usare la foresta casuale per eseguire il training del modello, con una profondità massima di quattro e con quattro funzionalità:

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

Usare la foresta casuale per eseguire il training del modello, con una profondità massima di otto e con sei funzionalità:

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

Eseguire il training del modello con 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])

Visualizzare l'artefatto dell'esperimento per tenere traccia delle prestazioni del modello

Le esecuzioni dell'esperimento vengono salvate automaticamente nell'artefatto dell'esperimento. È possibile trovare l'artefatto nell'area di lavoro. Un nome di artefatto si basa sul nome usato per impostare l'esperimento. Tutti i modelli sottoposti a training, le esecuzioni, le metriche delle prestazioni e i parametri del modello vengono registrati nella pagina dell'esperimento.

Per visualizzare gli esperimenti:

  1. Nel pannello a sinistra, selezionare l'area di lavoro.
  2. Trovare e selezionare il nome dell'esperimento, in questo caso sample-bank-churn-experiment.

Screenshot che mostra i valori registrati per uno dei modelli.

Passaggio 5: valutare e salvare il modello di apprendimento automatico finale

Aprire l'esperimento salvato dall'area di lavoro per selezionare e salvare il modello migliore:

# 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")

Valutare le prestazioni dei modelli salvati nel set di dati di test

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

Mostrare veri/falsi positivi/negativi usando una matrice di confusione

Per valutare l'accuratezza della classificazione, compilare uno script che traccia la matrice di confusione. È anche possibile tracciare una matrice di confusione usando gli strumenti SynapseML, come illustrato nell'esempio di rilevamento delle frodi.

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

Creare una matrice di confusione per il classificatore di foresta casuale, con una profondità massima di quattro, con quattro funzionalità:

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 che mostra una visualizzazione del notebook di una matrice di confusione per una foresta casuale con una profondità massima di quattro.

Creare una matrice di confusione per il classificatore di foresta casuale con profondità massima di otto, con sei funzionalità:

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 che mostra una visualizzazione del notebook di una matrice di confusione per una foresta casuale con una profondità massima di otto.

Creare una matrice di confusione per 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 che mostra una visualizzazione del notebook di una matrice di confusione per LightGBM.

Salvare i risultati per Power BI

Salvare il frame differenziale nel lakehouse per spostare i risultati della previsione del modello in una visualizzazione di Power BI.

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}")

Passaggio 6: accedere alle visualizzazioni in Power BI

Accedere alla tabella salvata in Power BI:

  1. A sinistra selezionare Hub dati OneLake
  2. Selezionare il lakehouse aggiunto a questo notebook
  3. Nella sezione Apri questo lakehouse selezionare Apri
  4. Nella barra multifunzione selezionare Nuovo modello semantico. Selezionare df_pred_results e quindi Continua per creare un nuovo modello semantico di Power BI collegato alle stime
  5. Selezionare Nuovo report dagli strumenti nella parte superiore della pagina dei modelli semantici per aprire la pagina di creazione di report di Power BI

Lo screenshot seguente mostra alcune visualizzazioni di esempio. Il pannello dati mostra le tabelle e le colonne differenziali da selezionare da una tabella. Dopo aver selezionato l'asse delle categorie (x) e quello del valore (y), è possibile scegliere i filtri e le funzioni, ad esempio somma o media della colonna della tabella.

Nota

In questo screenshot l'esempio illustrato descrive l'analisi dei risultati della stima salvata in Power BI:

Screenshot che mostra un esempio di dashboard di Power BI.

Tuttavia, per un vero caso d'uso di abbandono dei clienti, l'utente potrebbe avere bisogno di un set più completo dei requisiti delle visualizzazioni da creare, in base alle competenze in materia e a ciò che il team di analisi del business e aziendale, nonché l’azienda stessa hanno standardizzato come metriche.

Il report di Power BI mostra che i clienti che usano più di due prodotti bancari hanno un tasso di abbandono più elevato. Tuttavia, pochi clienti avevano più di due prodotti. (Vedere il tracciato nel pannello in basso a sinistra.) La banca dovrebbe raccogliere più dati, ma dovrebbe anche analizzare altre funzionalità correlate a più prodotti.

I clienti della banca in Germania hanno un tasso di abbandono più elevato rispetto ai clienti in Francia e Spagna. (Vedere il tracciato nel pannello in basso a destra). In base ai risultati del report, potrebbe essere utile svolgere un'indagine sui fattori che hanno incoraggiato i clienti all’abbandono.

Ci sono più clienti di mezza età (tra i 25 e i 45 anni). I clienti tra i 45 e i 60 anni tendono a uscire di più.

Infine, i clienti con punteggi di credito più bassi lasciano la banca per altri istituti finanziari. La banca dovrebbe esplorare i modi per incoraggiare i clienti con punteggi di credito e saldi di conto più bassi a rimanere.

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