Compartir vía


Tutorial: Creación, evaluación y puntuación de un modelo de predicción de deserción

En este tutorial se presenta un ejemplo completo de un flujo de trabajo de ciencia de datos de Synapse en Microsoft Fabric. El escenario crea un modelo para predecir si los clientes bancarios abandonan o no. La tasa de renovación, o la tasa de atrición, implica la tasa a la que los clientes bancarios terminan su negocio con el banco.

En este tutorial se describen estos pasos:

  • Instalación de bibliotecas personalizadas
  • Carga de los datos
  • Comprender y procesar los datos a través del análisis de datos exploratorios y mostrar el uso de la característica Fabric Data Wrangler
  • Uso de scikit-learn y LightGBM para entrenar modelos de aprendizaje automático y realizar un seguimiento de los experimentos con las características de registro automático de MLflow y Fabric
  • Evaluación y guardado del modelo de aprendizaje automático final
  • Mostrar el rendimiento del modelo con visualizaciones de Power BI

Prerrequisitos

Seguimiento en un cuaderno

Puede elegir una de estas opciones para tomar notas en un cuaderno:

  • Abra y ejecute el cuaderno integrado.
  • Cargue el cuaderno desde GitHub.

Abra el cuaderno integrado.

Customer Churn (abandono de clientes) es el cuaderno de ejemplo que acompaña a este tutorial.

  1. Para abrir el cuaderno de ejemplo de este tutorial, siga las instrucciones de Preparar el sistema para tutoriales de ciencia de datos.

  2. Asegúrese de adjuntar un almacén de lago de datos al cuaderno antes de empezar a ejecutar el código.

Importación del cuaderno desde GitHub

AIsample - Bank Customer Churn.ipynb es el cuaderno que acompaña a este tutorial.

Paso 1: Instalación de bibliotecas personalizadas

Para el desarrollo de modelos de Machine Learning o el análisis de datos ad hoc, es posible que tenga que instalar rápidamente una biblioteca personalizada para la sesión de Apache Spark. Tiene dos opciones para instalar bibliotecas.

  • Usa las capacidades de instalación en línea (%pip o %conda) de tu cuaderno para instalar una biblioteca, solo en el cuaderno actual.
  • Como alternativa, puede crear un entorno de Fabric, instalar bibliotecas desde orígenes públicos o cargar bibliotecas personalizadas en él y, a continuación, el administrador del área de trabajo puede asociar el entorno como valor predeterminado para el área de trabajo. Todas las bibliotecas del entorno estarán disponibles para su uso en los cuadernos y las definiciones de trabajo de Spark en el área de trabajo. Para obtener más información sobre los entornos, consulte crear, configurar y usar un entorno en Microsoft Fabric.

Para este tutorial, use %pip install para instalar la biblioteca imblearn en el notebook.

Nota

El kernel de PySpark se reinicia después de que se ejecute %pip install. Instale las bibliotecas necesarias antes de ejecutar cualquier otra celda.

# Use pip to install libraries
%pip install imblearn

Paso 2: Cargar los datos

El conjunto de datos de churn.csv contiene el estado de cancelación de 10 000 clientes, junto con 14 atributos que incluyen:

  • Puntuación de crédito
  • Ubicación geográfica (Alemania, Francia, España)
  • Género (masculino, femenino)
  • Edad
  • Antigüedad (número de años que la persona era cliente en ese banco)
  • Saldo de la cuenta
  • Salario estimado
  • Número de productos que un cliente compró a través del banco
  • Estado de la tarjeta de crédito (si un cliente tiene o no una tarjeta de crédito)
  • Estado de miembro activo (independientemente de si la persona es un cliente bancario activo)

El conjunto de datos también incluye columnas de número de fila, identificador de cliente y apellidos del cliente. Los valores de estas columnas no deben influir en la decisión de un cliente de abandonar el banco.

Un evento de cierre de cuenta bancaria de un cliente define la pérdida de ese cliente. El conjunto de datos Exited columna hace referencia al abandono del cliente. Dado que tenemos poco contexto sobre estos atributos, no necesitamos información general sobre el conjunto de datos. Queremos comprender cómo contribuyen estos atributos al estado Exited.

De esos 10 000 clientes, solo 2037 clientes (aproximadamente 20%) abandonaron el banco. Debido a la relación de desequilibrio de clases, se recomienda generar datos sintéticos. Es posible que la precisión de la matriz de confusión no tenga relevancia para la clasificación desbalanceada. Es posible que deseemos medir la precisión mediante el área bajo la curva de Precision-Recall (AUPRC).

  • En esta tabla se muestra una vista previa de los datos de churn.csv:
ID de Cliente Apellido Calificación crediticia Geografía Género Edad Tenencia Equilibrio NumOfProducts HasCrCard EsMiembroActivo SalarioEstimado Cerrado
15634602 Hargrave 619 Francia Femenino 42 2 0.00 1 1 1 101348.88 1
15647311 Hill 608 España Femenino 41 1 83807.86 1 0 1 112542.58 0

Descarga del conjunto de datos y carga en un almacén de lago de datos

Defina estos parámetros para poder usar este cuaderno con diferentes conjuntos de datos:

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

Este código descarga una versión disponible públicamente del conjunto de datos y, a continuación, almacena ese conjunto de datos en fabric lakehouse:

Importante

Agregue un almacén de lago de datos al cuaderno antes de ejecutarlo. Si no lo hace, se producirá un error.

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

Inicie la grabación del tiempo necesario para ejecutar el cuaderno:

# Record the notebook running time
import time

ts = time.time()

Lectura de datos sin procesar desde el lago de datos

Este código lee datos sin procesar de la sección de Archivos del almacén de lago de datos, y agrega más columnas para diferentes partes de fecha. La creación de la tabla delta con particiones usa esta información.

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

Creación de un dataFrame de Pandas a partir del conjunto de datos

Este código convierte el dataframe de Spark en un dataframe de Pandas para facilitar el procesamiento y la visualización:

df = df.toPandas()

Paso 3: Realizar análisis de datos exploratorios

Mostrar datos sin procesar

Explore los datos sin procesar con display, calcule algunas estadísticas básicas y muestre las vistas del gráfico. Primero debe importar las bibliotecas necesarias para la visualización de datos; por ejemplo, seaborn . Seaborn es una biblioteca de visualización de datos de Python y proporciona una interfaz de alto nivel para crear objetos visuales en tramas de datos y matrices.

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)

Utilice Data Wrangler para realizar la limpieza inicial de datos

Inicie Data Wrangler directamente desde el cuaderno para explorar y transformar cualquier dataframe de Pandas. Seleccione el desplegable de Data Wrangler en la barra de herramientas horizontal para examinar los DataFrames de Pandas activados disponibles para su edición. Seleccione el DataFrame que desea abrir en Data Wrangler.

Nota

El Wrangler de datos no se puede abrir mientras el kernel del cuaderno está ocupado. La ejecución de la celda debe finalizar antes de iniciar Data Wrangler. Más información sobre data Wrangler.

Captura de pantalla que muestra dónde acceder a Data Wrangler.

Una vez que se inicia Data Wrangler, se genera una descripción general descriptiva del panel de datos, como se muestra en las imágenes siguientes. La información general incluye información sobre la dimensión de DataFrame, los valores que faltan, etc. Puede usar Data Wrangler para generar el script para quitar las filas con valores que faltan, las filas duplicadas y las columnas con nombres específicos. A continuación, puede copiar el script en una celda. En la celda siguiente se muestra el script copiado.

Captura de pantalla que muestra el menú Wrangler de datos.

Captura de pantalla que muestra los datos que faltan en 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())

Determinación de atributos

Este código determina los atributos categóricos, numéricos y de destino:

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

Mostrar el resumen de cinco números

Usar diagramas de caja para mostrar el resumen de cinco números

  • la puntuación mínima
  • primer cuartil
  • mediana
  • tercer cuartil
  • puntuación máxima

para los atributos numéricos.

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

Captura de pantalla que muestra una presentación del cuaderno del diagrama de caja para atributos numéricos.

Mostrar la distribución de clientes que han salido y que no han salido

Mostrar la distribución de clientes que han salido frente a clientes que no han salido, según los atributos categóricos.

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)

Captura de pantalla que muestra la pantalla del portátil de la distribución de clientes que se han dado de baja frente a clientes que no se han dado de baja.

Mostrar la distribución de atributos numéricos

Use un histograma para mostrar la distribución de frecuencia de los atributos numéricos:

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

Captura de pantalla que muestra una presentación del cuaderno de atributos numéricos.

Ingeniería de características

Esta ingeniería de características genera nuevos atributos basados en los atributos actuales:

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

Uso de Limpieza y transformación de datos para realizar la codificación de un solo uso

Con los mismos pasos para iniciar Data Wrangler, como se explicó anteriormente, use Data Wrangler para realizar la codificación one-hot. En esta celda se muestra el script generado copiado para la codificación one-hot:

Captura de pantalla que muestra la codificación one-hot en Data Wrangler.

Captura de pantalla que muestra la selección de columnas en Data Wrangler.

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

Creación de una tabla delta para generar el informe de 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}")

Resumen de las observaciones del análisis de datos exploratorios

  • La mayoría de los clientes son de Francia. España tiene la tasa de renovación más baja, en comparación con Francia y Alemania.
  • La mayoría de los clientes tienen tarjetas de crédito
  • Algunos clientes son mayores de 60 años y tienen puntuaciones de crédito por debajo de 400. Sin embargo, no se pueden considerar valores atípicos
  • Muy pocos clientes tienen más de dos productos bancarios
  • Los clientes inactivos tienen una tasa de renovación más alta
  • Los años de género y antigüedad tienen poco impacto en la decisión de un cliente de cerrar una cuenta bancaria

Paso 4: Realizar el entrenamiento y el seguimiento del modelo

Con los datos implementados, ahora puede definir el modelo. Aplique modelos de bosque aleatorio y LightGBM en este cuaderno.

Use las bibliotecas scikit-learn y LightGBM para implementar los modelos, con algunas líneas de código. Además, use el registro automático de MLfLow y Fabric para realizar un seguimiento de los experimentos.

Este ejemplo de código carga la tabla delta desde lakehouse. Puede usar otras tablas delta que usen la instancia del almacén de lago de datos como origen.

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

Generación de un experimento para el seguimiento y registro de los modelos mediante MLflow

En esta sección se muestra cómo generar un experimento y se especifican los parámetros de modelo y entrenamiento y las métricas de puntuación. Además, muestra cómo entrenar los modelos, registrarlos y guardar los modelos entrenados para su uso posterior.

import mlflow

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

El registro automático captura automáticamente los valores de parámetro de entrada y las métricas de salida de un modelo de Machine Learning, ya que ese modelo se entrena. A continuación, esta información se registra en el área de trabajo, donde las API de MLflow o el experimento correspondiente del área de trabajo pueden acceder a ella y visualizarla.

Cuando haya finalizado, el experimento se parece a esta imagen:

Captura de pantalla que muestra la página del experimento de deserción bancaria.

Todos los experimentos con sus respectivos nombres se registran y puede realizar un seguimiento de sus parámetros y métricas de rendimiento. Para obtener más información sobre el registro automático, consulte Registro automático en Microsoft Fabric.

Establecimiento de especificaciones de experimento y registro automático

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

Importación de scikit-learn y 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

Preparación de conjuntos de datos de entrenamiento y prueba

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)

Aplicación de SMOTE a los datos de entrenamiento

La clasificación desequilibrada tiene un problema, ya que tiene muy pocos ejemplos de la clase minoritaria para que un modelo aprenda eficazmente el límite de decisión. Para manejar esto, la técnica de sobremuestreo de minorías sintéticas (SMOTE) es la técnica más usada para sintetizar nuevas muestras para la clase minoritaria. Acceda a SMOTE con la biblioteca imblearn que instaló en el paso 1.

Aplique SMOTE solo al conjunto de datos de entrenamiento. Debe dejar el conjunto de datos de prueba en su distribución original desequilibrada para aproximarse correctamente al rendimiento del modelo en los datos originales. Este experimento representa la situación en producción.

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)

Para obtener más información, consulte SMOTE y De muestreo excesivo aleatorio a SMOTE y ADASYN. El sitio web de imbalanced-learn hospeda estos recursos.

Entrenamiento del modelo

Use Bosque aleatorio para entrenar el modelo, con una profundidad máxima de cuatro y con cuatro características:

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

Use Bosque aleatorio para entrenar el modelo, con una profundidad máxima de ocho y con seis características:

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

Entrenamiento del modelo 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])

Visualización del artefacto del experimento para realizar un seguimiento del rendimiento del modelo

Las ejecuciones del experimento se guardan automáticamente en el artefacto del experimento. Puede encontrar ese artefacto en el área de trabajo. Un nombre de artefacto se basa en el nombre usado para establecer el experimento. Todos los modelos entrenados, sus ejecuciones, métricas de rendimiento y parámetros de modelo se registran en la página del experimento.

Para ver los experimentos:

  1. En el panel izquierdo, seleccione el área de trabajo.
  2. Busque y seleccione el nombre del experimento, en este caso, sample-bank-churn-experiment.

Captura de pantalla que muestra los valores registrados para uno de los modelos.

Paso 5: Evaluación y guardado del modelo de aprendizaje automático final

Abra el experimento guardado del área de trabajo para seleccionar y guardar el mejor modelo:

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

Evaluación del rendimiento de los modelos guardados en el conjunto de datos de prueba

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

Mostrar verdaderos/falsos positivos/negativos mediante una matriz de confusión

Para evaluar la precisión de la clasificación, cree un script que traza la matriz de confusión. También puede trazar una matriz de confusión mediante herramientas de SynapseML, como se muestra en el ejemplo de detección de fraudes de .

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

Cree una matriz de confusión para el clasificador de bosque aleatorio, con una profundidad máxima de cuatro, con cuatro características:

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

Captura de pantalla que muestra una interfaz de cuaderno con una matriz de confusión para un bosque aleatorio con una profundidad máxima de cuatro.

Cree una matriz de confusión para el clasificador de bosque aleatorio con una profundidad máxima de ocho, con seis características:

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

Captura de pantalla que muestra la pantalla de un cuaderno de una matriz de confusión de un bosque aleatorio con una profundidad máxima de ocho.

Cree una matriz de confusión para 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()

Captura de pantalla que muestra una visualización de una matriz de confusión en un cuaderno para LightGBM.

Guardar resultados para Power BI

Guarde el marco delta en el almacén de lago de datos para mover los resultados de predicción del modelo a una visualización de 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}")

Paso 6: Acceso a visualizaciones en Power BI

Acceda a la tabla guardada en Power BI:

  1. A la izquierda, seleccione OneLake.
  2. Seleccione la instancia de almacén de lago de datos que agregó a este cuaderno.
  3. En la sección Abrir este almacén de lago de datos, seleccione Abrir.
  4. En la cinta de opciones, seleccione Nuevo modelo semántico. Seleccione df_pred_resultsy, a continuación, seleccione Confirmar para crear un nuevo modelo semántico de Power BI vinculado a las predicciones.
  5. Abra un nuevo modelo semántico. Puedes encontrarlo en OneLake.
  6. Seleccione Crear nuevo informe en archivo en las herramientas de la parte superior de la página modelos semánticos para abrir la página de creación de informes de Power BI.

En la captura de pantalla siguiente se muestran algunas visualizaciones de ejemplo. El panel de datos muestra las tablas y columnas delta que se van a seleccionar de una tabla. Después de seleccionar el eje de categoría (x) y el eje de valor (y), puede elegir los filtros y las funciones, por ejemplo, la suma o el promedio de la columna de la tabla.

Nota

En esta captura de pantalla, en el ejemplo ilustrado se describe el análisis de los resultados de predicción guardados en Power BI:

Captura de pantalla que muestra un ejemplo de panel de Power BI.

Sin embargo, para un caso de uso real de abandono de clientes, el usuario podría necesitar un conjunto más exhaustivo de requisitos para crear las visualizaciones, basándose en el conocimiento especializado del tema, así como en las métricas que el equipo de análisis empresarial y la empresa han estandarizado.

El informe de Power BI muestra que los clientes que usan más de dos de los productos bancarios tienen una tasa de renovación más alta. Sin embargo, pocos clientes tenían más de dos productos. (Vea el trazado en el panel inferior izquierdo). El banco debe recopilar más datos, pero también debe investigar otras características que se correlacionan con más productos.

Los clientes bancarios de Alemania tienen una tasa de abandono más alta que los clientes de Francia y España. (Vea el trazado en el panel inferior derecho). En función de los resultados del informe, una investigación sobre los factores que animan a los clientes a salir podrían ayudar.

Hay más clientes de mediana edad (entre 25 y 45). Los clientes entre 45 y 60 tienden a salir más.

Por último, los clientes con puntuaciones de crédito más bajas probablemente dejarían el banco para otras instituciones financieras. El banco debe explorar formas de animar a los clientes con puntuaciones de crédito más bajas y saldos de cuentas para mantenerse con el banco.

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