Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
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
- Descripción y procesamiento de los datos a través del análisis de datos exploratorios
- Uso de scikit-learn y LightGBM para entrenar modelos de aprendizaje automático
- Evaluación y guardado del modelo de aprendizaje automático final
- Mostrar el rendimiento del modelo con visualizaciones de Power BI
Prerrequisitos
Obtenga una suscripción a Microsoft Fabric. También puede registrarse para obtener una evaluación gratuita de Microsoft Fabric.
Inicie sesión en Microsoft Fabric.
Use el conmutador de experiencia en la parte inferior izquierda de la página principal para cambiar a Fabric.
- Si es necesario, cree un almacén de lago de datos de Microsoft Fabric como se describe en Creación de un almacén de lago de datos en Microsoft Fabric.
Sigue el desarrollo en un cuaderno
Puede elegir una de estas opciones para seguir en un cuaderno:
- Abra y ejecute el cuaderno integrado en la experiencia de ciencia de datos de Synapse.
- Cargue el cuaderno desde GitHub en la experiencia de ciencia de datos de Synapse.
Abra el cuaderno integrado.
Customer Churn (abandono de clientes) es el cuaderno de ejemplo que acompaña a este tutorial.
Para abrir el cuaderno de ejemplo de este tutorial, siga las instrucciones de Preparar el sistema para tutoriales de ciencia de datos.
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 - R Bank Customer Churn.ipynb es el cuaderno que acompaña a este tutorial.
Para abrir el cuaderno complementario de este tutorial, siga las instrucciones de Preparación del sistema para los tutoriales de ciencia de datos a fin de importar el cuaderno a su área de trabajo.
Si prefiere copiar y pegar el código de esta página, puede crear un cuaderno nuevo.
Asegúrese de adjuntar un almacén de lago de datos al cuaderno antes de empezar a ejecutar código.
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.
- Use recursos de instalación en línea, por ejemplo,
install.packages
ydevtools::install_version
, para instalar 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.
En este tutorial, use install.packages()
para instalar las bibliotecas de imbalance
y randomForest
. Establezca quiet
en TRUE
para que la salida sea más concisa:
# Install imbalance for SMOTE
install.packages("imbalance", quiet = TRUE)
# Install the random forest algorithm
install.packages("randomForest", quiet=TRUE)
Paso 2: Cargar los datos
El conjunto de datos de churn.csv contiene el estado de abandono 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 los 10.000 clientes, solo 2037 clientes (alrededor de 20%) dejaron el banco. Debido al desequilibrio de clases, recomendamos generar datos sintéticos.
En esta tabla se muestra un ejemplo de vista previa de los datos de churn.csv
:
ID de Cliente | Apellido | Puntuación de crédito | Geografía | Género | Edad | Tenencia | Equilibrio | NumOfProducts | HasCrCard | EsMiembroActivo | SalarioEstimado | Cerrado |
---|---|---|---|---|---|---|---|---|---|---|---|---|
15634602 | Hargrave | 619 | Francia | Mujer | 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
Importante
Agregue un almacén de lago de datos al cuaderno antes de ejecutarlo. Si no lo hace, se producirá un error.
Este código descarga una versión disponible públicamente del conjunto de datos y, a continuación, almacena esos datos en una instancia de Fabric Lakehouse:
library(fs)
library(httr)
remote_url <- "https://sdkstorerta.blob.core.windows.net/churnblob"
file_list <- c("churn.csv")
download_path <- "/lakehouse/default/Files/churn/raw"
if (!dir_exists("/lakehouse/default")) {
stop("Default lakehouse not found, please add a lakehouse and restart the session.")
}
dir_create(download_path, recurse= TRUE)
for (fname in file_list) {
if (!file_exists(paste0(download_path, "/", fname))) {
r <- GET(paste0(remote_url, "/", fname), timeout(30))
writeBin(content(r, "raw"), paste0(download_path, "/", fname))
}
}
print("Downloaded demo data files into lakehouse.")
Inicie la grabación del tiempo necesario para ejecutar este cuaderno:
# Record the notebook running time
ts <- as.numeric(Sys.time())
Lectura de datos sin procesar desde el almacén de lago de datos
Este código lee datos sin procesar de la sección Archivos del lago de datos:
fname <- "churn.csv"
download_path <- "/lakehouse/default/Files/churn/raw"
rdf <- readr::read_csv(paste0(download_path, "/", fname))
Paso 3: Realizar análisis de datos exploratorios
Mostrar datos sin procesar
Use los comandos head()
o str()
para realizar una exploración preliminar de los datos sin procesar:
head(rdf)
Realizar la limpieza inicial de datos
Debe convertir el dataframe de R en un dataframe de Spark. Estas operaciones en spark DataFrame limpian el conjunto de datos sin procesar:
- Eliminar las filas que tienen datos faltantes en todas las columnas
- Quite las filas duplicadas en las columnas
RowNumber
yCustomerId
- Quite las columnas
RowNumber
,CustomerId
ySurname
# Transform the R DataFrame to a Spark DataFrame
df <- as.DataFrame(rdf)
clean_data <- function(df) {
sdf <- df %>%
# Drop rows that have missing data across all columns
na.omit() %>%
# Drop duplicate rows in columns: 'RowNumber', 'CustomerId'
dropDuplicates(c("RowNumber", "CustomerId")) %>%
# Drop columns: 'RowNumber', 'CustomerId', 'Surname'
SparkR::select("CreditScore", "Geography", "Gender", "Age", "Tenure", "Balance", "NumOfProducts", "HasCrCard", "IsActiveMember", "EstimatedSalary", "Exited")
return(sdf)
}
df_clean <- clean_data(df)
Explore el DataFrame de Spark con el comando display
:
display(df_clean)
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)
# Obtain the distinct values for each column
exprs = lapply(names(df_clean), function(x) alias(countDistinct(df_clean[[x]]), x))
# Use do.call to splice the aggregation expressions to aggregate function
distinct_value_number <- SparkR::collect(do.call(agg, c(x = df_clean, exprs)))
# Determine the categorical attributes
categorical_variables <- names(df_clean)[sapply(names(df_clean), function(col) col %in% c("0") || distinct_value_number[[col]] <= 5 && !(col %in% c(dependent_variable_name)))]
print(categorical_variables)
# Determine the numerical attributes
numeric_variables <- names(df_clean)[sapply(names(df_clean), function(col) coltypes(SparkR::select(df_clean, col)) == "numeric" && distinct_value_number[[col]] > 5)]
print(numeric_variables)
Para facilitar el procesamiento y la visualización, convierta el dataframe de Spark limpio en un dataframe de R:
# Transform the Spark DataFrame to an R DataFrame
rdf_clean <- SparkR::collect(df_clean)
Mostrar el resumen de cinco números
Use gráficos de cuadros para mostrar el resumen de cinco números (puntuación mínima, primer cuartil, mediana, tercer cuartil, puntuación máxima) para los atributos numéricos:
# Set the overall layout of the graphics window
par(mfrow = c(2, 1),
mar = c(2, 1, 2, 1)) # Margin size
for(item in numeric_variables[1:2]){
# Create a box plot
boxplot(rdf_clean[, item],
main = item,
col = "darkgreen",
cex.main = 1.5, # Title size
cex.lab = 1.3, # Axis label size
cex.axis = 1.2,
horizontal = TRUE) # Axis size
}
# Set the overall layout of the graphics window
par(mfrow = c(3, 1),
mar = c(2, 1, 2, 1)) # Margin size
for(item in numeric_variables[3:5]){
# Create a box plot
boxplot(rdf_clean[, item],
main = item,
col = "darkgreen",
cex.main = 1.5, # Title size
cex.lab = 1.3, # Axis label size
cex.axis = 1.2,
horizontal = TRUE) # Axis size
}
Mostrar la distribución de clientes que se han dado de baja y clientes que no se han dado de baja
Mostrar la distribución de clientes que se han dado de baja frente a clientes que permanecen, según los atributos categóricos.
attr_list <- c('Geography', 'Gender', 'HasCrCard', 'IsActiveMember', 'NumOfProducts', 'Tenure')
par(mfrow = c(2, 1),
mar = c(2, 1, 2, 1)) # Margin size
for (item in attr_list[1:2]) {
counts <- table(rdf_clean$Exited, rdf_clean[,item])
barplot(counts, main=item, col=c("darkblue","yellow"),
cex.main = 1.5, # Title size
cex.axis = 1.2,
legend = rownames(counts), beside=TRUE)
}
par(mfrow = c(2, 1),
mar = c(2, 2, 2, 1)) # Margin size
for (item in attr_list[3:4]) {
counts <- table(rdf_clean$Exited, rdf_clean[,item])
barplot(counts, main=item, col=c("darkblue","yellow"),
cex.main = 1.5, # Title size
cex.axis = 1.2,
legend = rownames(counts), beside=TRUE)
}
par(mfrow = c(2, 1),
mar = c(2, 1, 2, 1)) # Margin size
for (item in attr_list[5:6]) {
counts <- table(rdf_clean$Exited, rdf_clean[,item])
barplot(counts, main=item, col=c("darkblue","yellow"),
cex.main = 1.5, # Title size
cex.axis = 1.2,
legend = rownames(counts), beside=TRUE)
}
Mostrar la distribución de atributos numéricos
Use un histograma para mostrar la distribución de frecuencia de los atributos numéricos:
# Set the overall layout of the graphics window
par(mfrow = c(2, 1),
mar = c(2, 4, 2, 4) + 0.1) # Margin size
# Create a histogram
for (item in numeric_variables[1:2]) {
hist(rdf_clean[, item],
main = item,
col = "darkgreen",
xlab = item,
cex.main = 1.5, # Title size
cex.axis = 1.2,
breaks = 20) # Number of bins
}
# Set the overall layout of the graphics window
par(mfrow = c(3, 1),
mar = c(2, 4, 2, 4) + 0.1) # Margin size
# Create a histogram
for (item in numeric_variables[3:5]) {
hist(rdf_clean[, item],
main = item,
col = "darkgreen",
xlab = item,
cex.main = 1.5, # Title size
cex.axis = 1.2,
breaks = 20) # Number of bins
}
Realizar ingeniería de funciones
Esta ingeniería de características genera nuevos atributos basados en atributos actuales:
rdf_clean$NewTenure <- rdf_clean$Tenure / rdf_clean$Age
rdf_clean$NewCreditsScore <- as.numeric(cut(rdf_clean$CreditScore, breaks=quantile(rdf_clean$CreditScore, probs=seq(0, 1, by=1/6)), include.lowest=TRUE, labels=c(1, 2, 3, 4, 5, 6)))
rdf_clean$NewAgeScore <- as.numeric(cut(rdf_clean$Age, breaks=quantile(rdf_clean$Age, probs=seq(0, 1, by=1/8)), include.lowest=TRUE, labels=c(1, 2, 3, 4, 5, 6, 7, 8)))
rdf_clean$NewBalanceScore <- as.numeric(cut(rank(rdf_clean$Balance), breaks=quantile(rank(rdf_clean$Balance, ties.method = "first"), probs=seq(0, 1, by=1/5)), include.lowest=TRUE, labels=c(1, 2, 3, 4, 5)))
rdf_clean$NewEstSalaryScore <- as.numeric(cut(rdf_clean$EstimatedSalary, breaks=quantile(rdf_clean$EstimatedSalary, probs=seq(0, 1, by=1/10)), include.lowest=TRUE, labels=c(1:10)))
Realización de una codificación activa
Use la codificación one-hot para convertir los atributos categóricos en atributos numéricos, para introducirlos en el modelo de aprendizaje automático:
rdf_clean <- cbind(rdf_clean, model.matrix(~Geography+Gender-1, data=rdf_clean))
rdf_clean <- subset(rdf_clean, select = - c(Geography, Gender))
Creación de una tabla delta para generar el informe de Power BI
table_name <- "rdf_clean"
# Create a Spark DataFrame from an R DataFrame
sparkDF <- as.DataFrame(rdf_clean)
write.df(sparkDF, paste0("Tables/", table_name), source = "delta", mode = "overwrite")
cat(paste0("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
- 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 del modelo
Con los datos implementados, ahora puede definir el modelo. Aplicar modelos de Bosque aleatorio y LightGBM. Use randomForest y LightGBM para implementar los modelos con algunas líneas de código.
Cargue la tabla delta desde el lago de datos. Puede usar otras tablas delta teniendo en cuenta el almacén de lago como origen.
SEED <- 12345
rdf_clean <- read.df("Tables/rdf_clean", source = "delta")
df_clean <- as.data.frame(rdf_clean)
Importar randomForest y LightGBM:
library(randomForest)
library(lightgbm)
Prepare los conjuntos de datos de entrenamiento y prueba:
set.seed(SEED)
y <- factor(df_clean$Exited)
X <- df_clean[, !(colnames(df_clean) %in% c("Exited"))]
split <- base::sample(c(TRUE, FALSE), nrow(df_clean), replace = TRUE, prob = c(0.8, 0.2))
X_train <- X[split,]
X_test <- X[!split,]
y_train <- y[split]
y_test <- y[!split]
train_df <- cbind(X_train, y_train)
Aplicación de SMOTE al conjunto de datos de entrenamiento
La clasificación desequilibrada tiene un problema, ya que tiene demasiado pocos ejemplos de la clase minoritaria para que un modelo aprenda eficazmente el límite de decisión. Para controlar esto, la técnica de sobremuestreo de minorías sintéticas (SMOTE) es el enfoque más utilizado para sintetizar nuevas muestras para la clase minoría. 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 desequilibrada original para obtener una aproximación válida del rendimiento del modelo en los datos originales. Este experimento representa la situación en producción.
En primer lugar, muestre la distribución de clases en el conjunto de datos para saber qué clase es la clase minoría. La relación entre la clase minoría y la clase mayoritaria se define como imbalance Ratio
en la biblioteca imbalance
.
original_ratio <- imbalance::imbalanceRatio(train_df, classAttr = "y_train")
message(sprintf("Original imbalance ratio is %.2f%% as {Size of minority class}/{Size of majority class}.", original_ratio * 100))
message(sprintf("Positive class(Exited) takes %.2f%% of the dataset.", round(sum(train_df$y_train == 1)/nrow(train_df) * 100, 2)))
message(sprintf("Negative class(Non-Exited) takes %.2f%% of the dataset.", round(sum(train_df$y_train == 0)/nrow(train_df) * 100, 2)))
En el conjunto de datos de entrenamiento:
Positive class(Exited)
hace referencia a la clase minoría, que toma 20,34% del conjunto de datos.Negative class(Non-Exited)
hace referencia a la clase de mayoría, que toma 79,66% del conjunto de datos.
La celda siguiente vuelve a escribir la función oversample de la biblioteca de imbalance
, para generar un conjunto de datos equilibrado:
binary_oversample <- function(train_df, X_train, y_train, class_Attr = "Class"){
negative_num <- sum(y_train == 0) # Compute the number of the negative class
positive_num <- sum(y_train == 1) # Compute the number of the positive class
difference_num <- abs(negative_num - positive_num) # Compute the difference between the negative and positive classes
originalShape <- imbalance:::datasetStructure(train_df, class_Attr) # Get the original dataset schema
new_samples <- smotefamily::SMOTE(X_train, y_train, dup_size = ceiling(max(negative_num, positive_num)/min(negative_num, positive_num))) # Use SMOTE to oversample
new_samples <- new_samples$syn_data # Get the synthetic data
new_samples <- new_samples[base::sample(1:nrow(new_samples), size = difference_num), ] # Sample and shuffle the synthetic data
new_samples <- new_samples[, -ncol(new_samples)] # Remove the class column
new_samples <- imbalance:::normalizeNewSamples(originalShape, new_samples) # Normalize the synthetic data
new_train_df <- rbind(train_df, new_samples) # Concatenate original and synthetic data by row
new_train_df <- new_train_df[base::sample(nrow(new_train_df)), ] # Shuffle the training dataset
new_train_df
}
Para obtener más información sobre SMOTE, vea los recursos Paquete imbalance
y Trabajo con conjuntos de datos desequilibrados en el sitio web de CRAN.
Sobremuestreo del conjunto de datos de entrenamiento
Use la función oversample recién definida para realizar el sobremuestreo en el conjunto de datos de entrenamiento:
library(dplyr)
new_train_df <- binary_oversample(train_df, X_train, y_train, class_Attr="y_train")
smote_ratio <- imbalance::imbalanceRatio(new_train_df, classAttr = "y_train")
message(sprintf("Imbalance ratio after using smote is %.2f%%\n", smote_ratio * 100))
Entrenamiento del modelo
Use un bosque aleatorio para entrenar el modelo, con cuatro características:
set.seed(1)
rfc1_sm <- randomForest(y_train ~ ., data = new_train_df, ntree = 500, mtry = 4, nodesize = 3)
y_pred <- predict(rfc1_sm, X_test, type = "response")
cr_rfc1_sm <- caret::confusionMatrix(y_pred, y_test)
cm_rfc1_sm <- table(y_pred, y_test)
roc_auc_rfc1_sm <- pROC::auc(pROC::roc(as.numeric(y_test), as.numeric(y_pred)))
print(paste0("The auc is ", roc_auc_rfc1_sm))
Use un bosque aleatorio para entrenar el modelo, con seis características:
rfc2_sm <- randomForest(y_train ~ ., data = new_train_df, ntree = 500, mtry = 6, nodesize = 3)
y_pred <- predict(rfc2_sm, X_test, type = "response")
cr_rfc2_sm <- caret::confusionMatrix(y_pred, y_test)
cm_rfc2_sm <- table(y_pred, y_test)
roc_auc_rfc2_sm <- pROC::auc(pROC::roc(as.numeric(y_test), as.numeric(y_pred)))
print(paste0("The auc is ", roc_auc_rfc2_sm))
Entrenamiento del modelo con LightGBM:
set.seed(42)
X_train <- new_train_df[, !(colnames(new_train_df) %in% c("y_train"))]
y_train <- as.numeric(as.character(new_train_df$y_train))
y_test <- as.numeric(as.character(y_test))
lgbm_sm_model <- lgb.train(list(objective = "binary", learning_rate = 0.1, max_delta_step = 2, nrounds = 100, max_depth = 10, eval_metric = "logloss"), lgb.Dataset(as.matrix(X_train), label = as.vector(y_train)), valids = list(test = lgb.Dataset(as.matrix(X_test), label = as.vector(as.numeric(y_test)))))
y_pred <- as.numeric(predict(lgbm_sm_model, as.matrix(X_test)) > 0.5)
accuracy <- mean(y_pred == as.vector(y_test))
cr_lgbm_sm <- caret::confusionMatrix(as.factor(y_pred), as.factor(as.vector(y_test)))
cm_lgbm_sm <- table(y_pred, as.vector(y_test))
roc_auc_lgbm_sm <- pROC::auc(pROC::roc(as.vector(y_test), y_pred))
print(paste0("The auc is ", roc_auc_lgbm_sm))
Paso 5: Evaluación y guardado del modelo de aprendizaje automático final
Evalúe el rendimiento de los modelos guardados en el conjunto de datos de prueba:
ypred_rfc1_sm <- predict(rfc1_sm, X_test, type = "response")
ypred_rfc2_sm <- predict(rfc2_sm, X_test, type = "response")
ypred_lgbm1_sm <- as.numeric(predict(lgbm_sm_model, as.matrix(X_test)) > 0.5)
Mostrar verdaderos/falsos positivos/negativos con una matriz de confusión. Desarrolle un script para trazar la matriz de confusión para evaluar la precisión de la clasificación:
plot_confusion_matrix <- function(cm, classes, normalize=FALSE, title='Confusion matrix', cmap=heat.colors(10)) {
if (normalize) {
cm <- cm / rowSums(cm)
}
op <- par(mar = c(6,6,3,1))
image(1:nrow(cm), 1:ncol(cm), t(cm[nrow(cm):1,]), col = cmap, xaxt = 'n', yaxt = 'n', main = title, xlab = "Prediction", ylab = "Reference")
axis(1, at = 1:nrow(cm), labels = classes, las = 2)
axis(2, at = 1:ncol(cm), labels = rev(classes))
for (i in seq_len(nrow(cm))) {
for (j in seq_len(ncol(cm))) {
text(i, ncol(cm) - j + 1, cm[j,i], cex = 0.8)
}
}
par(op)
}
Cree una matriz de confusión para el clasificador de bosque aleatorio, con cuatro características:
cfm <- table(y_test, ypred_rfc1_sm)
plot_confusion_matrix(cfm, classes=c('Non Churn','Churn'), title='Random Forest with features of 4')
tn <- cfm[1,1]
fp <- cfm[1,2]
fn <- cfm[2,1]
tp <- cfm[2,2]
Cree una matriz de confusión para el clasificador de bosque aleatorio, con seis características:
cfm <- table(y_test, ypred_rfc2_sm)
plot_confusion_matrix(cfm, classes=c('Non Churn','Churn'), title='Random Forest with features of 6')
tn <- cfm[1,1]
fp <- cfm[1,2]
fn <- cfm[2,1]
tp <- cfm[2,2]
Cree una matriz de confusión para LightGBM:
cfm <- table(y_test, ypred_lgbm1_sm)
plot_confusion_matrix(cfm, classes=c('Non Churn','Churn'), title='LightGBM')
tn <- cfm[1,1]
fp <- cfm[1,2]
fn <- cfm[2,1]
tp <- cfm[2,2]
Guardar resultados para Power BI
Guarde el marco delta en lakehouse para mover los resultados de predicción del modelo a una visualización de Power BI:
df_pred <- X_test
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 <- as.DataFrame(df_pred)
write.df(sparkDF, paste0("Tables/", table_name), source = "delta", mode = "overwrite", overwriteSchema = "true")
cat(paste0("Spark DataFrame saved to delta table: ", table_name))
Paso 6: Acceso a visualizaciones en Power BI
Acceda a la tabla guardada en Power BI:
- A la izquierda, seleccione centro de datos de OneLake
- Seleccione el almacén de lago de datos que agregó a este cuaderno
- En la sección Abrir este almacén de lago de datos, seleccione Abrir
- En la cinta de opciones, seleccione Nuevo modelo semántico. Seleccione
df_pred_results
y, a continuación, seleccione Continuar para crear un nuevo modelo semántico de Power BI vinculado a las predicciones. - En las herramientas de la parte superior de la página del conjunto de datos, seleccione Nuevo informe 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ías (x) y el eje de valores (y) adecuados, puede elegir los filtros y las funciones. Por ejemplo, puede elegir una suma o media de la columna de tabla.
Nota
La captura de pantalla es un ejemplo ilustrado que muestra el análisis de los resultados de la predicción guardada en Power BI. Para un caso de uso real sobre la deserción de clientes, los usuarios de la plataforma podrían necesitar una idea más completa sobre las visualizaciones que se deben crear, basándose tanto en la experiencia en la materia como en lo que la organización y el equipo de análisis empresarial de la empresa han estandarizado como métricas.
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 investigar otras características que se correlacionan con más productos.
Los clientes bancarios en 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
cat(paste0("Full run cost ", as.integer(Sys.time() - ts), " seconds.\n"))