Este proyecto desarrolla una solución basada en machine learning para predecir el abandono de clientes (churn) en una entidad bancaria, proporcionando a la compañía una herramienta clave para la toma de decisiones estratégicas basadas en datos.
El análisis comienza con la evaluación de diferentes modelos supervisados en R (regresión logística, árbol de decisión y random forest), seleccionando la alternativa más precisa para identificar clientes en riesgo de abandono. Los resultados se integran en Power BI para facilitar su visualización y monitorización por parte de los equipos directivos.
Además, el uso de técnicas de interpretabilidad avanzada en Python mediante valores SHAP permite comprender el peso de cada variable en la predicción individual, aportando información valiosa para diseñar campañas de retención personalizadas y estrategias de marketing segmentado. Este enfoque integral mejora la capacidad de la organización para anticipar comportamientos críticos de sus clientes y optimizar sus acciones de fidelización.
Se comparan distintos modelos de aprendizaje supervisado utilizadondo R.
Se probaron tres modelos: Regresión Logística, Árbol de Decisión y Random Forest, evaluando su precisión y capacidad predictiva.
El modelo elegido finalmente fue Random Forest, que ofreció mejores resultados.
El resultado de este modelo se exportó a un CSV (predicciones_rf.csv
) para su análisis posterior en Power BI.
library(readr) churn <- read_csv("churn.csv") View(churn) datos <- churn # Análisis descriptivo de los datos summary(datos) str(datos) # Cuántos y qué % de clientes se van del banco table(datos$Exited) prop.table(table(datos$Exited)) # Categóricas datos$Gender <- as.factor(datos$Gender) datos$Geography <- as.factor(datos$Geography) datos$Exited <- as.factor(datos$Exited) # Split 80/20 library("caTools") division <- sample.split(datos$Exited, SplitRatio = 0.8) entrenamiento <- subset(datos, division==TRUE) test <- subset(datos, division==FALSE) prop.table(table(datos$Exited)) prop.table(table(entrenamiento$Exited)) prop.table(table(test$Exited)) # Regresión Logística reg_logistica <- glm(Exited ~ Age + Gender + Geography + CreditScore + Balance + NumOfProducts + IsActiveMember, data = entrenamiento, family = "binomial") summary(reg_logistica) prediccionmodelo <- predict(reg_logistica, newdata = test, type = "response") prediccionmodelocod <- ifelse(prediccionmodelo > 0.5, 1, 0) library(caret) confusionMatrix(as.factor(prediccionmodelocod), as.factor(test$Exited)) # Árbol de decisión library(rpart) library(rpart.plot) modelo_arbol <- rpart(Exited ~ Age + Gender + Geography + CreditScore + Balance + NumOfProducts + IsActiveMember, data = entrenamiento, method = "class") summary(modelo_arbol) rpart.plot(modelo_arbol) prediccionarbol <- predict(modelo_arbol, newdata = test, type = "class") confusionMatrix(as.factor(test$Exited), as.factor(prediccionarbol)) # Random Forest library(randomForest) set.seed(123) modelo_rf <- randomForest(Exited ~ Age + Gender + Geography + CreditScore + Balance + NumOfProducts + IsActiveMember, data = entrenamiento, ntree = 500, mtry = 3, importance = TRUE) print(modelo_rf) prediccion_rf <- predict(modelo_rf, newdata = test) confusionMatrix(as.factor(prediccion_rf), as.factor(test$Exited)) varImpPlot(modelo_rf) # Exportar resultados para Power BI datos$Predicted_Exited <- predict(modelo_rf, newdata = datos) write.csv(datos, "predicciones_rf.csv", row.names = FALSE)
En este bloque se muestra el código principal en Python utilizado para entrenar el modelo de Random Forest, analizar la importancia de las variables y aplicar técnicas de interpretabilidad mediante SHAP values. Este análisis permite comprender tanto el funcionamiento interno del modelo como el impacto de cada variable en la predicción individual de cada cliente.
# Instalación de librerías (en Google Colab) !pip install shap import numpy as np import pandas as pd from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn import metrics import shap # Cargar los datos data = pd.read_csv("churn.csv") train, test = train_test_split(data, test_size=0.3, random_state=0, stratify=data['Exited']) # Eliminación de columnas innecesarias train = train.drop(['RowNumber', 'Surname', 'CustomerId'], axis=1) test = test.drop(['RowNumber', 'Surname', 'CustomerId'], axis=1) # Conversión de variables categóricas train_processed = pd.get_dummies(train) test_processed = pd.get_dummies(test) # Rellenar valores nulos train_processed = train_processed.fillna(train_processed.mean(numeric_only=True)) test_processed = test_processed.fillna(test_processed.mean(numeric_only=True)) test_processed = test_processed[train_processed.columns] # Crear matrices de entrenamiento y test X_train = train_processed.drop(['Exited'], axis=1) Y_train = train_processed['Exited'] X_test = test_processed.drop(['Exited'], axis=1) Y_test = test_processed['Exited'] # Entrenar modelo Random Forest random_forest = RandomForestClassifier(n_estimators=100) random_forest.fit(X_train, Y_train) random_forest_preds = random_forest.predict(X_test) print('The accuracy of the Random Forests model is :', metrics.accuracy_score(random_forest_preds, Y_test)) # Interpretabilidad con SHAP explainer = shap.TreeExplainer(random_forest) # Ejemplo de predicción e interpretación choosen_instance = X_test.loc[2739] shap_values = explainer.shap_values(choosen_instance) shap.initjs() shap.force_plot(explainer.expected_value[1], shap_values[1], choosen_instance)