Análisis de Personalidad del Cliente con Machine Learning
Análisis de Personalidad del Cliente con K-Means y PCA
Este proyecto nació como parte de un reto para aplicar Machine Learning en un caso real de negocio. La idea fue simple: entender mejor a los clientes para que las estrategias de marketing sean más inteligentes, efectivas y personalizadas. Para lograrlo, utilicé algoritmos de aprendizaje no supervisado como PCA y K-Means para descubrir patrones ocultos en los datos.
¿Por qué hacer esto? Porque no tiene sentido gastar dinero en campañas generales si no sabes a quién le estás hablando. Con este tipo de análisis, una empresa puede enfocarse en los grupos de clientes que realmente tienen mayor probabilidad de comprar cierto producto o responder a una promoción.
Metodología aplicada
- Escalamiento de datos para mejorar el rendimiento del modelo.
- Reducción de dimensionalidad con PCA para visualizar y simplificar los datos.
- Agrupación de clientes usando K-Means para formar segmentos con características similares.
- Análisis de cada clúster para entender sus preferencias, hábitos de compra y comportamiento digital.
¿Qué tipo de datos usamos?
Los datos incluían atributos personales (edad, estado civil, educación), hábitos de compra (gastos en vino, carne, frutas, dulces), participación en campañas promocionales, historial de compras en web y tiendas físicas, e incluso si el cliente se había quejado recientemente.
- Demográficos: Edad, ingresos, hijos y adolescentes en el hogar.
- Consumo: Gastos en vino, carne, frutas, dulces, pescado y productos de oro.
- Promociones: Campañas aceptadas, número de compras con descuentos.
- Comportamiento digital: Compras online, visitas web mensuales.
- Relación con la marca: Tiempo desde la última compra, si ha presentado quejas.
Transformar datos en decisiones de negocio más inteligentes.
— Propósito del proyecto
1# Import the necessary libraries
2
3import numpy as np
4import pandas as pd
5import matplotlib.pyplot as plt
6from matplotlib.colors import ListedColormap # allows you to create a color palette from a list of colors.
7import seaborn as sns
8from matplotlib import colors
9sns.set(style = 'whitegrid')
10
11# Import the neccesary libraries for building model
12from sklearn.preprocessing import OneHotEncoder, LabelEncoder # These are used for converting categorical data into numerical data.
13from sklearn.decomposition import PCA # PCA is used for dimensionality reduction in data.
14from sklearn.cluster import KMeans # KMeans is a clustering algorithm used to group data into k clusters.
15from sklearn.preprocessing import StandardScaler, MinMaxScaler # These are used for scaling features in data preprocessing.
16from sklearn.metrics import silhouette_score
17from yellowbrick.cluster import SilhouetteVisualizer
18from sklearn.cluster import AgglomerativeClustering
19from matplotlib.colors import ListedColormap
20from sklearn import metrics
21import warnings
22import sys
23if not sys.warnoptions:
24 warnings.simplefilter("ignore")
25np.random.seed(42)
26
27# scipy
28from scipy.stats import pointbiserialr # This function is used to calculate the Point Biserial correlation.
29
30# Method Elbow
31from yellowbrick.cluster import KElbowVisualizer # This class is used for visualizing the "elbow" method to select the optimal number of clusters in KMeans clustering.
32from sklearn.exceptions import ConvergenceWarning
Análisis Exploratorio de Datos (EDA)
Visualización de la variable categórica: Education
1# Look the categorical variables like as Education and Marital_status, for better understanding
2education_categories = df['Education'].value_counts()
3print(education_categories)
1Graduation 1127
2PhD 486
3Master 370
42n Cycle 203
5Basic 54
6Name: Education, dtype: int64
Visualización de la variable categórica: Marital_Status
1# Look the categorical variables like as Education and Marital_status, for better understanding
2education_categories = df['Marital_Status'].value_counts()
3print(education_categories)
1Married 864
2Together 580
3Single 480
4Divorced 232
5Widow 77
6Alone 3
7Absurd 2
8YOLO 2
9Name: Marital_Status, dtype: int64
¿Qué observé?
El dataset cuenta con 2240 muestras y 29 características. Se identificaron cuatro áreas principales: Personas, Productos, Promociones y Lugares. Existen varias variables que no aportan información relevante, como Complain, Z_CostContact, Z_Revenue e ID. Algunas variables pueden ser transformadas en una sola, por ejemplo, el número de hijos en el hogar y la aceptación de campañas. En la variable Estado Civil (Marital_Status) se recomienda simplificar en dos categorías para mejorar el rendimiento. No hay valores duplicados, aunque sí 24 valores faltantes en Ingresos (Income).
Limpieza de datos y nuevas características
Para preparar los datos es necesario eliminar los valores faltantes, convertir la variable Dt_customer a número de meses, eliminar columnas irrelevantes y unificar variables como la aceptación de campañas. Además, se transformará el número de hijos en el hogar a una sola variable y el Estado Civil se simplificará a dos categorías: soltero o casado. Todo esto tiene como objetivo reducir la dimensionalidad y optimizar el análisis.
Visualización y análisis de datos
1# We create a pairplot analyzing the continuous variables and relating them to a discrete variable
2To_Plot = ["Income", "Recency", "Total_children", "Age", "Total_Mn", 'Prents']
3print("Reletive Plot Of Some Selected Features: A Data Subset")
4sns.pairplot(df[To_Plot], hue='Prents', palette=(['#682F2F', '#F3AB60']))
He creado un gráfico de pares (pairplot) que analiza las variables continuas en relación con una variable discreta: si los individuos son padres o no. En este análisis, observamos la presencia de valores atípicos (outliers) en las variables de edad y de ingresos, lo que indica la necesidad de una nueva fase de limpieza de datos. Por otro lado, en cuanto a la correlación, confirmamos la ausencia de multicolinealidad.
5. PCA - Principal Component Analysis
1# Assign model
2pca = PCA(n_components=0.5)
1# Train model
2pca.fit(dt_scaler)
1# New data PCA_Scales
2dt_scaler_pca = pca.transform(dt_scaler)
1# Now, we analyze the variance of data_scaler_pca
2var = pca.explained_variance_ratio_
3
4# Show the variance of all features
5print(len(var))
6print(var)
1# We show the best option to reduce the dimensionality, for this we plot the variance with which we will explore the best amount of characteristics that explain the variance of the data.
2cum_var = np.cumsum(np.round(var, decimals = 4) * 100) # np.cumsum is the cumulative sum
3# Show results
4for i, acumulado in enumerate(cum_var, start=1):
5 print(f"{i} componente: {acumulado:.2f}%")
6
7plt.figure(figsize=(10, 6))
8plt.plot(cum_var, 'r-x', marker='X')
9plt.xlabel('Número de Componentes')
10plt.ylabel('Varianza Acumulada (%)')
11plt.title('Varianza Acumulada vs. Número de Componentes')
12plt.grid(True)
13plt.show()
1# Elbow Method to determine the number of clusters to be formed
2Elbow_method = KElbowVisualizer(KMeans(), k = 10)
3Elbow_method.fit(dt_scaler_pca)
4Elbow_method.show()
1# Ahora vamos hallar el numero de K más efectivo para el modelo, usaremos el coeficiente de la silueta
2silhoutte_score = []
3K = range(2, 15)
4for i in K:
5 km = KMeans(n_clusters = i)
6 km = km.fit(dt_scaler_pca)
7 y = km.fit_predict(dt_scaler_pca)
8 silhoutte_score.append(silhouette_score(dt_scaler_pca, y))
9
10plt.plot(K, silhoutte_score, 'bx-')
11plt.title('Efective clusters')
12plt.xlabel('No. of Clusters')
13plt.ylabel('Silhoutte Score')
14plt.show()
15
16print('Podemos observar que efectivamente el número más apropiado para el modelo es de 4 Clusters')
17print('El número que vamos a escoger es el que está asociado con el coeficiente de silueta más alto')
Evaluación del modelo
1from sklearn.datasets import make_blobs
2from sklearn.cluster import KMeans
3from sklearn.metrics import silhouette_samples, silhouette_score
4import matplotlib.pyplot as plt
5import matplotlib.cm as cm
6import numpy as np
7
8range_n_clusters = [2,3,4,5]
9
10for n_clusters in range_n_clusters:
11 fig, (ax1, ax2) = plt.subplots(1, 2)
12 fig.set_size_inches(18, 7)
13 ax1.set_xlim([-0.1, 1])
14 ax1.set_ylim([0, len(dt_scaler_pca) + (n_clusters + 1) * 10])
15
16 clustererO = AgglomerativeClustering(n_clusters=n_clusters, affinity='euclidean', linkage='ward')
17 cluster_labels = clustererO.fit_predict(dt_scaler_pca)
18 silhouette_avg = silhouette_score(dt_scaler_pca, cluster_labels)
19 print("For n_clusters =", n_clusters, "The average silhouette_score is :", silhouette_avg)
20
21 sample_silhouette_values = silhouette_samples(dt_scaler_pca, cluster_labels)
22
23 y_lower = 10
24 for i in range(n_clusters):
25 ith_cluster_silhouette_values = sample_silhouette_values[cluster_labels == i]
26 ith_cluster_silhouette_values.sort()
27 size_cluster_i = ith_cluster_silhouette_values.shape[0]
28 y_upper = y_lower + size_cluster_i
29 color = cm.nipy_spectral(float(i) / n_clusters)
30 ax1.fill_betweenx(np.arange(y_lower, y_upper), 0, ith_cluster_silhouette_values, facecolor=color, edgecolor=color, alpha=0.7)
31 ax1.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))
32 y_lower = y_upper + 10
33
34 ax1.set_title("The silhouette plot for the various clusters.")
35 ax1.set_xlabel("The silhouette coefficient values")
36 ax1.set_ylabel("Cluster label")
37 ax1.axvline(x=silhouette_avg, color="red", linestyle="--")
38 ax1.set_yticks([])
39 ax1.set_xticks([-0.1, 0, 0.2, 0.4, 0.6, 0.8, 1])
40
41 colors = cm.nipy_spectral(cluster_labels.astype(float) / n_clusters)
42 sns.scatterplot(data = df, x = 'Total_Mn', y = 'Income', hue = 'Clusters', palette=["#682F2F", "#F3AB60", "#58A4B0", "yellow"])
43
44plt.show()
1# Plotting the clusters
2sns.scatterplot(data = df, x = 'Total_Mn', y = 'Income', hue = 'Clusters', palette=["#682F2F", "#F3AB60", "#58A4B0", "yellow"])
Comentarios
Cargando comentarios...