latentSource

Clustering de segmentos de clientes

Aprende cómo el clustering de K-Means revela patrones ocultos en el comportamiento de los usuarios para impulsar estrategias de negocio dirigidas.

·5 min read
Compartir
Clustering de segmentos de clientes

Clustering de segmentos de clientes

Tienes una base de datos de 100,000 clientes. El equipo de marketing quiere campañas personalizadas. Una estrategia por cliente es imposible. Una estrategia para todos es un desperdicio. El punto medio es la segmentación: agrupar a los clientes en clusters que compartan comportamientos y luego adaptar tu enfoque a cada grupo.

Aquí es donde el unsupervised learning demuestra su valor. No necesitas etiquetas. El algoritmo encuentra la estructura por sí solo.

Por qué usar aprendizaje no supervisado

Los enfoques supervisados requieren que alguien defina los segmentos de antemano: "alto valor", "en riesgo", "nuevo". Eso introduce sesgos humanos y pasa por alto patrones que nadie pensó en buscar. El clustering permite que los datos hablen. Podrías encontrar un segmento que compra raramente pero gasta mucho por pedido, o un grupo que interactúa a diario pero nunca convierte. Las etiquetas predefinidas nunca mostrarían ninguno de esos casos.

K-Means: la herramienta principal

K-Means es el algoritmo al que recurro primero. Es rápido, la matemática es intuitiva y funciona bien cuando tus clusters son aproximadamente esféricos y de tamaño similar.

El ciclo es corto:

  1. Elegir K centroides iniciales (aleatorios o vía K-means++)
  2. Asignar cada punto a su centroide más cercano
  3. Recomputar cada centroide como la media de sus puntos asignados
  4. Repetir 2 y 3 hasta que nada cambie

Aquí puedes verlo funcionando con datos reales. Presiona play; esta es una ejecución real de K-Means, iniciada deliberadamente con una mala inicialización (los cuatro centroides agrupados en una esquina) para que puedas observar cómo la reasignación hace su trabajo:

Invalid viz:anim block: expected JSON like {"name":"my_frames","height":360}.

Algoritmo de Lloyd en 150 puntos. Las cruces son los centroides; cada iteración los mueve a la media de sus puntos asignados y vuelve a colorear cada punto según su centroide más cercano. Nota qué tan rápido converge: 27 puntos cambian de cluster en la primera pasada, luego 11, 6, 2, y esencialmente termina en la iteración 5. La inercia (distancia total al cuadrado de los centroides) cae de 6,108 a 856 y se estabiliza. Esa estabilización es exactamente lo que busca el método del codo (elbow method) a continuación.

import pandas as pd import numpy as np from sklearn.cluster import KMeans from sklearn.preprocessing import StandardScaler # Load and prepare customer data df = pd.read_csv('customers.csv') features = df[['recency', 'frequency', 'monetary', 'avg_session_duration', 'support_tickets', 'days_since_signup']] # Scaling is critical - K-Means uses Euclidean distance scaler = StandardScaler() X = scaler.fit_transform(features) # Fit K-Means kmeans = KMeans(n_clusters=5, init='k-means++', n_init=10, random_state=42) df['cluster'] = kmeans.fit_predict(X)

Un detalle que no puedes omitir: K-Means utiliza la distancia euclidiana, por lo que cada característica (feature) debe estar en la misma escala. Una columna "monetary" en dólares (rango de 0 a 10,000) aplastará a una columna "frequency" (rango de 0 a 50) a menos que estandarices primero. StandardScaler centra cada característica en cero con varianza unitaria, que es lo que necesitas.

Eligiendo K: método del codo y silhouette scores

Elegir K es la parte más difícil de K-Means. Dos métodos te ayudarán a lograrlo.

El método del codo (elbow method) grafica la suma de cuadrados dentro del cluster (inercia) frente a K. A medida que K crece, la inercia disminuye. El "codo" es el punto donde la caída se suaviza y añadir más clusters deja de valer la pena.

import matplotlib.pyplot as plt inertias = [] K_range = range(2, 11) for k in K_range: km = KMeans(n_clusters=k, init='k-means++', n_init=10, random_state=42) km.fit(X) inertias.append(km.inertia_) plt.plot(K_range, inertias, 'bo-') plt.xlabel('Number of Clusters (K)') plt.ylabel('Inertia') plt.title('Elbow Method') plt.show()

El codo suele ser ambiguo con datos reales. Cuando sea así, recurre al silhouette score. Para cada punto, el coeficiente de silueta compara qué tan similar es a su propio cluster frente al cluster vecino más cercano. Las puntuaciones van de -1 (cluster incorrecto) a 1 (bien ubicado). Promedia todos los puntos y obtendrás un número para comparar diferentes valores de K.

from sklearn.metrics import silhouette_score for k in K_range: km = KMeans(n_clusters=k, init='k-means++', n_init=10, random_state=42) labels = km.fit_predict(X) score = silhouette_score(X, labels) print(f"K={{k}}: Silhouette Score = {{score:.3f}}")

En la práctica, analizo ambos y luego me pregunto si el resultado es útil operativamente. Puede que K=7 tenga una puntuación ligeramente mejor que K=5, pero si el equipo de marketing no puede ejecutar siete campañas distintas, lanza el modelo con K=5.

Feature engineering: análisis RFM

Las transacciones en bruto no están listas para el clustering. El punto de partida estándar para la segmentación de clientes es el análisis RFM:

  • Recency: días desde la última compra. Mientras menor, mejor.
  • Frequency: número de compras en un periodo. Mayor significa más compromiso.
  • Monetary: gasto total. Tu señal de ingresos.
from datetime import datetime snapshot_date = datetime(2025, 10, 1) rfm = df.groupby('customer_id').agg({{ 'purchase_date': lambda x: (snapshot_date - x.max()).days, # Recency 'order_id': 'nunique', # Frequency 'amount': 'sum' # Monetary }}).rename(columns={{ 'purchase_date': 'recency', 'order_id': 'frequency', 'amount': 'monetary' }})

RFM es un punto de partida, no la meta. Dependiendo del negocio, añadiré el valor promedio del pedido, el número de categorías de productos comprados, la antigüedad del cliente, tickets de soporte, tasa de apertura de correos electrónicos o duración de la sesión. Más características a veces ayudan, pero también disparan la dimensionalidad y añaden ruido. Sé deliberado.

Más allá de K-Means: DBSCAN para clusters no esféricos

K-Means asume que los clusters son convexos y de tamaño similar. Los datos reales de clientes rompen ambos supuestos constantemente. Tendrás un cluster enorme de compradores ocasionales y un cluster diminuto y compacto de usuarios avanzados. K-Means dividirá el grande o absorberá el pequeño.

DBSCAN (Density-Based Spatial Clustering of Applications with Noise) encuentra clusters de forma arbitraria basándose en la densidad de puntos. Toma dos parámetros:

  • eps: radio de la vecindad alrededor de cada punto.
  • min_samples: el número mínimo de puntos necesarios para considerar una región como densa.

Los puntos que no pertenecen a ninguna región densa se etiquetan como ruido, lo cual es realmente útil. No todos los clientes encajan en un segmento, y pretender que lo hacen es como terminas con "buyer personas" que no sirven para nada.

from sklearn.cluster import DBSCAN dbscan = DBSCAN(eps=0.8, min_samples=10) df['cluster'] = dbscan.fit_predict(X) n_clusters = len(set(df['cluster'])) - (1 if -1 in df['cluster'].values else 0) n_noise = (df['cluster'] == -1).sum() print(f"Clusters: {{n_clusters}}, Noise points: {{n_noise}}")

Ajustar eps es la parte difícil. Si es muy pequeño, todo es ruido. Si es muy grande, todo colapsa en un solo cluster. Un gráfico de k-distancia —ordenar la distancia al k-ésimo vecino más cercano para cada punto y buscar el codo— suele situarte en el rango correcto.

Interpretación y acción sobre los clusters

El clustering no es el final del trabajo, es el comienzo de la conversación con los interesados. Para cada cluster, calcula estadísticas resumidas:

summary = df.groupby('cluster')[['recency', 'frequency', 'monetary']].agg(['mean', 'median', 'std']) print(summary)

Luego, dales un nombre. Una segmentación RFM típica de 5 clusters suele verse así:

ClusterRecencyFrequencyMonetaryEtiqueta
0BajaAltaAltaCampeones (Champions)
1BajaBajaBajaClientes nuevos
2AltaAltaAltaLeales en riesgo
3AltaBajaBajaPerdidos
4MediaMediaMediaLeales potenciales

Cada uno requiere una jugada diferente. Los Campeones reciben recompensas de lealtad y acceso anticipado. Los Leales en riesgo reciben campañas de recuperación antes de que abandonen (churn). Los Clientes nuevos entran en flujos de onboarding. Los clientes Perdidos simplemente podrían no valer el costo de re-adquisición; esa también es una respuesta válida.

Errores comunes

Olvidar escalar. El error número uno. Las características sin escalar hacen que la distancia euclidiana no tenga sentido.

Incluir demasiadas características. La maldición de la dimensionalidad hace que las métricas de distancia sean cada vez menos informativas a medida que agregas columnas. Después de 10 o 15 características, ejecuta un PCA antes del clustering.

Tratar los clusters como permanentes. El comportamiento del cliente cambia. Ejecuta el clustering mensual o trimestralmente y observa cómo los clientes migran entre segmentos; esa migración suele ser la señal más útil que tienes.

Ignorar la estabilidad. Ejecuta K-Means varias veces con diferentes semillas aleatorias. Si los clientes saltan entre clusters en cada ejecución, la segmentación no es robusta para ese valor de K.

Conclusión

La segmentación de clientes es uno de los casos más claros donde el aprendizaje no supervisado entrega valor real de negocio. Las piezas técnicas —K-Means, silhouette scores, variables RFM— están bien establecidas. La parte difícil es la capa de traducción: convertir las estadísticas de los clusters en algo que los equipos de marketing, producto y soporte puedan ejecutar. La mejor segmentación es la que cambia la forma en que la organización toma decisiones, no la que tiene el gráfico de silueta más bonito.