Análisis de Segmentación de Clientes Usando K-Means: Una Guía Práctica

Oriol Gilabert López
11 min readFeb 2, 2024

--

Switch Language: EN

Descubre cómo el algoritmo K-means transforma el caos de un conjuntos de datos en clusters claros y significativos, revelando patrones ocultos con una simplicidad sorprendente

Photo by Happy Lee on Unsplash

En cuando a la segmentación de clientes, esta es una técnica esencial para las empresas que buscan entender mejor a sus clientes y optimizar sus estrategias de marketing y ventas. En este post, vamos a explorar cómo podemos utilizar el algoritmo K-Means para segmentar clientes utilizando Python. Para ello, usaremos un conjunto de datos de un centro comercial para demostrar este proceso.

1. Dataset “Mall Customers”

El conjunto de datos “Mall Customers” es un conjunto de datos comúnmente utilizado para ejercicios y proyectos de Machine Learning, especialmente en el contexto del clustering y la segmentación de clientes.
El conjunto de datos “Mall Customers” incluye las siguientes características:

  1. Customer ID: Un identificador único para cada cliente.
  2. Gender: El género del cliente: Male, Female
  3. Age: La edad del cliente.
  4. Annual income (K$): El ingreso anual aproximado del cliente, expresado en miles de dólares.
  5. Spending Score (1-100): El scoring asignado por el centro comercial en función del comportamiento del cliente y la naturaleza del gasto. Este puntaje o scoring esta en el rango de 1 a 100.
import pandas as pd
dataset = pd.read_csv("Mall_Customers.csv")
Tabla 1: Output de Mall_Customers.csv.

Aquí, nos centraremos en Annual income (K$)y Spending Score (1-100).Para ello, seleccionamos dichas columnas del dataset y las convertimos en un ndarray de NumPy, luego, asociamos este resultado a X, siendo esta la famosa matriz de características.

import numpy as np
X = dataset.iloc[:, [3, 4]].values
Output 1: Resultado de la matriz de características X (ndarray).

Al visualizar estas dos variables en un gráfico de dispersión, obtenemos una primera impresión de la distribución de los clientes:

plt.figure(figsize=(8, 5))
plt.scatter(X[:, 0], X[:, 1], color='blue', marker='o')
plt.title('Scatter Plot')
plt.xlabel('Annual Income (k$) ')
plt.ylabel('Spending Score (1-100)')
plt.grid(True)
plt.show()
Gráfico 1: Scatter-plot de la matriz de características X que muestra la relación entre las variables Annual Income (k$) y Spending Score (1–100).

Al observar el primer gráfico de dispersión, como científicos de datos, nos deberían surgir, como mínimo, esta pregunta:

¿Existen patrones o agrupaciones naturales?
Para abordar este pregunta, necesitamos identificar si los clientes se agrupan por características comunes, como ingresos y puntuaciones de gasto. Esto nos permitirá comprender la naturaleza específica de los diferentes clústers dentro del conjunto de datos.

Si uno finalmente quiere organizar los datos de manera sistemática en grupos homogéneos, es es este contexto donde surge la necesidad de usar algoritmos clusterización.

2. Clusterización

Un algoritmo de clustering es un método utilizado en análisis de datos para agrupar un conjunto de objetos en diferentes grupos o “clusters”, de modo que los objetos en el mismo grupo son más similares entre sí que con los de otros grupos.

Estos algoritmos son especialmente útiles cuando no tenemos datos etiquetados, es decir, cuando los datos no vienen con categorías o clasificaciones predefinidas. En lugar de clasificar los datos en categorías conocidas, un algoritmo de clustering explorará los datos para encontrar estructuras o patrones naturales y creará grupos basados en estas similitudes descubiertas.

Algunos de estos algoritmos son:

  1. K-Means: Divide los datos en grupos, asegurando que los puntos en un grupo sean similares entre sí.
  2. DBSCAN: Forma grupos basados en áreas densas de puntos, ignorando los puntos aislados o raros.
  3. Clustering Jerárquico: Crea grupos dentro de grupos, como una estructura de árbol, ya sea combinando puntos gradualmente o dividiéndolos.

En el caso de K-means, este es un algoritmo tremendamente útil para los negocios, gracias a su capacidad de interpretar fácilmente los datos y proporcionar información práctica y relevante. Este método ayuda a las empresas a identificar tendencias ocultas en los datos de clientes, a afinar sus estrategias de marketing y ventas, y a tomar decisiones más informadas y precisas. En pocas palabras, K-means transforma datos complejos en conclusiones claras y valiosas que pueden impulsar el éxito de un negocio.

Elegimos el algoritmo K-means para este ejemplo por su simplicidad y eficacia, lo que lo se convierte en una excelente opción para quienes se inician en el mundo de los algoritmos de clustering.

3. Profundizando en K-means

Antes de comenzar con el algoritmo de K-means, necesitamos decidir la cantidad de grupos (K) que queremos identificar. Esta decisión puede crearnos un dolor de cabeza terrible ya que, en muchos casos, no sabemos de antemano cuántos grupos serán los más adecuados para describir nuestros datos.

Por ejemplo, en el caso anterior podemos definir K =1 (un grupo, lo que no tiene especial sentido), K = 2, K= 3, hasta un K=n, que por ejemplo será 6. Si aplicamos el algoritmo para cada una de las Ks nos da el siguiente resultado:

Gráfico 2: Resultado de iterar K-means 6 veces en la matriz de características X

Pero, ¿Cuál es el número de clústers perfecto? Os lo avanzo, es cuando K=5.

El método del codo (Elbow method) y otras técnicas son utilizadas para estimar el número de clústers (K) en el algoritmo K-means. Estas técnicas, especialmente el método del codo, analizan cómo la variabilidad dentro de los clusters, medida como WCSS (Within-Cluster Sum of Squares), cambia a medida que aumenta el número de clusters. El objetivo es encontrar un balance donde un incremento en el número de clusters no resulta en una mejora significativa de la variabilidad (WCSS).

Para más información sobre que es el WCSS y como se calcula, os animo a ver mi post en Medium: Entendiendo el Within Cluster Sum of Squares (WCSS).

Una vez que se ha elegido un valor para K, el siguiente paso es inicializar los centroides en el espacio de características. Los centroides son los puntos centrales de cada cluster y pueden ser inicializados de forma aleatoria o mediante métodos más sofisticados como K-means++, que selecciona los centroides de manera estratégica para mejorar la eficiencia del algoritmo. (para seleccionar K, también se puede usar K-means++)

El algoritmo K-means funciona iterativamente. Primero, asigna cada punto de datos al cluster cuyo centroide es el más cercano. Luego, recalcula los centroides de cada cluster en función de los puntos asignados a ellos. Este proceso se repite hasta que la asignación de los puntos a los clusters ya no cambia significativamente, lo que indica que el algoritmo ha convergido a una solución.

En otras palabras, estos son los pasos a seguir:

  1. Estimación del número de clusters (K): Debemos elegir el número de K de clústers con cualquier método válido
  2. Inicialización de los centroides: Debemos poner al azar los K centroides en el espacio de características.
    Nota: No tiene porque ser puntos de nuestro dataset original. En el Gráfico 2, vemos que muchos centroides no coinciden con ningún punto de nuestro dataset.
  3. Asignación de Puntos a Clusters: K-means asigna cada punto del dataset al centroide mas cercano. Aquí tendremos la primer conformación de los K-clusters
  4. Recálculo de los Centroides: Aquí se calculará y asignará el nuevo centroide de cada clúster. Es decir, dados ya los grupos que forman un cluster, calculamos su centroide o baricentro, por lo que los baricentros iniciales queda recalculados en este paso
  5. Iteración hasta Convergencia: Debe repetirse los pasos de asignación y recálculo hasta que la asignación de puntos a los clusters se estabilice y no cambie significativamente.

Veámoslo paso a paso.

4. End-to-end algoritmo K-means

Procedamos a ejecutar el algoritmo paso a paso, detallando y comprendiendo cada una de sus fases

4.1 Método Elbow: Escogiendo numero óptimo K clústers

Para identificar el número óptimo de clusters (K), esencial en nuestro análisis pero inicialmente desconocido, debemos comenzar estimando un valor inicial apropiado para K. Este proceso implica considerar cuidadosamente el contexto específico del negocio y establecer un rango viable para K, basado en nuestra comprensión del dominio y los objetivos del análisis. Para este propósito, definiremos un valor mínimo y un valor máximo para K. Por ejemplo, podríamos determinar que el límite superior para K sea 10, lo que nos proporciona un marco de referencia inicial para explorar la estructura de agrupación más efectiva dentro de los datos.

Para ello, vamos a:

  1. Ejecutar el algoritmo 10 veces: cuando K=1, K=2, … K=10
  2. Calcularemos la suma de los cuadrados de cada clusters (WCSS)
  3. Visualizaremos en un grafico cuando sucede ese cambio de tendencia mediante la gráfica del codo

Veamos el código:

from sklearn.cluster import KMeans

wcss = []
n_clu = 10

for i in range(1, n_clu+1):

kmeans = KMeans(n_clusters = i,
init = "k-means++",
max_iter = 300,
n_init = 10,
random_state = 42)

kmeans.fit(X)

wcss.append(kmeans.inertia_)

Como podéis ver, debemos iterar sobre K donde, para cada iteración debemos :

  1. Instanciar el algoritmo K-Means con n_clusters usando el método Kmeans() de sklearn.
  2. Ajustar el algoritmo K-Means al dataset X con el método .fit()
  3. Calcular el WCSS con el método .inertia_

Las configuraciones del algoritmo K-Means par cada iteración es la siguientes:

  • n_clusters = i: Este parámetro define el número de clústeres a crear y es dinámico en cada iteración del for.
  • init = "k-means++": Este método de inicialización de centroides mejora la convergencia del algoritmo. A diferencia de una selección aleatoria, k-means++ coloca los centroides de manera más estratégica, lo que generalmente conduce a resultados más eficientes y efectivos.
  • max_iter = 300: Este es el número máximo de iteraciones para una sola ejecución del algoritmo. Un valor de 300, que es el predeterminado, limita la cantidad de veces que el algoritmo actualizará los centroides, evitando así ciclos infinitos o prolongados sin una mejora significativa la asignación de los clústeres.
  • n_init = 10: También es un valor predeterminado e indica el número de veces que el algoritmo se ejecutará con diferentes semillas de centroides. Esto es útil para obtener un resultado más robusto, ya que el algoritmo puede ofrecer diferentes soluciones en función de la inicialización de los centroides.
  • random_state = 42: Es la semilla que nos asegurará reproducibilidad.

Una vez ejecutado el código, procedemos a listar los valors de wcss:

Output 2: Valores de WCSS para los diferentes números de clústeres

Como podemos ver en el la lista, los valores de WCSS tienden a disminuir progresivamente a medida que aumenta el número de clústeres. Esta disminución es típicamente rápida al principio y se ralentiza a medida que se alcanza el número óptimo de clústeres. Como con la lista anterior es difícil decir qué K es la correcta, vamos a graficar estos datos:

plt.plot(range(1,11), wcss, marker='o')
plt.title("Gráfico de Elbow")
plt.xlabel("Número de Clústers")
plt.ylabel("WCSS(k)")
plt.grid(True)
plt.show()
Gráfico 3: Método del codo o de Elbow. Representación de los WCSS según el numero de clusters K

En este caso, podríamos decir que la elección de K = 5, como el número clústeres óptimo para nuestro dataset, sugiere que esta cantidad proporciona un buen equilibrio entre la eficiencia del algoritmo y la precisión en la agrupación de los datos.

Al seleccionar 5 clústeres, se logra una significativa reducción de la métrica WCSS en comparación con K=1,2,3 y 4, lo que indica que los datos están siendo agrupados de manera más coherente y compacta.

Al mismo tiempo, aumentar el número de clústeres más allá de 5 solo proporciona mejoras marginales en la reducción de WCSS. Esto implica que añadir más clústeres no contribuye significativamente a una mejor separación de los datos, y podría incluso llevar a una segmentación excesiva, donde la ganancia en precisión no compensa el aumento en la complejidad del modelo.

4.2 Implementación del algoritmo K-Means

Teniendo ya el K-óptimo, lo que vamos hacer es organizar nuestro dataset X en 5 grupos o clústeres distintos.

La idea, es volver a ejecutar el método K-means con K=5 para que el algoritmo encuentre las mejores 5 agrupaciones basándonos en las características de los datos.

Por lo que ahora:

  1. Instanciamos el algoritmo K-Means con n_clusters = 5
  2. Ajustamos del modelo la predicción con el metodo.fit_predict() , con el cual pretendemos ajustar el modelo K-means al conjunto de datos X y realiza una predicción para cada muestra en X. Este método realiza dos operaciones:
    - fit: Ajusta el modelo K-means a los datos, encontrando los centroides de los clústeres.
    - predict: Asigna cada muestra en X a uno de los 5 clústeres identificados.
kmeans = KMeans(n_clusters = 5, 
init="k-means++",
max_iter = 100,
n_init = 10,
random_state = 42)

y_kmeans = kmeans.fit_predict(X)
y_kmeans

Si mostramos las 10 primers perdiciones de clústeres tenemos lo siguiente:

y_kmeans[0:10]
Output 3: Valores de la predicción de los clústeres para las 10 primeras filas del dataset

4.3 Integración de Resultados de Clustering en el Conjunto de Datos

Tras ajustar el modelo K — Means a nuestros datos y asignar cada muestra a un clúster, ahora debemos integrar los resultados en nuestro conjunto de datos original para facilitar un análisis más detallado y poder dar ese valor añadido a negocio.

El siguiente paso, convertimos las etiquetas de clúster, almacenadas en y_kmeans, en una Serie de Pandas. Luego, concatenamos esta serie con nuestro DataFrame dataset y añadiendo las etiquetas de clúster como una nueva columna llamada Cluster Pred.

Este DataFrame ampliado, X_clustered, nos permite examinar no solo las características originales de cada muestra, sino también su asignación a un clúster específico, abriendo un camino hacia un análisis detallado y contextualizado de los grupos identificados.

y_kmeans_series = pd.Series(y_kmeans, name='Cluster Pred')

X_clustered = pd.concat([dataset, y_kmeans_series], axis=1)
X_clustered
Tabla 2: Output con la predicción de los clústeres para el dataset de Mall_Customers.csv.

4.4 Visualización de clústeres y centroides

Tras integrar las asignaciones de clúster (Cluster Pred)en nuestro conjunto de datos, el siguiente paso consiste en visualizar los resultados para obtener una comprensión intuitiva de cómo se distribuyen los clústeres en función de las características seleccionadas.

La correcta elección de un grafico de visualización nos permitirá detectar patrones y tendencias que podrían no ser evidentes solo a través del análisis numérico.

Para ello, utilizamos un gráfico de dispersión para representar cada uno de los cinco clústeres identificados por el algoritmo K-Means. Cabe destacar que esto es posible gracias a que solo estamos analizados dos variables.

plt.scatter(X[y_kmeans == 0, 0], X[y_kmeans == 0, 1], 
s = 100, c = "red", label = "Grupo 1")
plt.scatter(X[y_kmeans == 1, 0], X[y_kmeans == 1, 1],
s = 100, c = "blue", label = "Grupo 2")
plt.scatter(X[y_kmeans == 2, 0], X[y_kmeans == 2, 1], s = 100,
c = "green", label = "Grupo 3")
plt.scatter(X[y_kmeans == 3, 0], X[y_kmeans == 3, 1], s = 100,
c = "cyan", label = "Grupo 4")
plt.scatter(X[y_kmeans == 4, 0], X[y_kmeans == 4, 1], s = 100,
c = "magenta", label = "Grupo 5")
plt.scatter(X[y_kmeans == 5, 0], X[y_kmeans == 5, 1], s = 100,
c = "magenta", label = "Grupo 5")

plt.scatter(kmeans.cluster_centers_[:,0], kmeans.cluster_centers_[:,1],
s = 100, c = "black", label = "centroide", marker = '^')

plt.title('Clúster de clientes Centro Comercial (k = ' + str(n) +')')
plt.xlabel('Annual Income (k$) ')
plt.ylabel('Spending Score (1-100)')
plt.legend()
plt.show()
Gráfico 4: Scatter-plot del dataset con la segmentación del K-means grafico de dispersión de los clústeres

Cada punto en el gráfico corresponde a una muestra en nuestro conjunto de datos X, coloreada de acuerdo con el clúster al que pertenece. Los colores distintos (rojo, azul, verde, cian y magenta) facilitan la diferenciación visual entre los grupos 1, 2, 3, 4 y 5 respectivamente.

Además, trazamos los centroides de cada clúster, representados por marcadores negros en forma de triángulo. Los centroides juegan un papel crucial en el algoritmo K-Means, ya que son el punto central alrededor del cual se agrupan las muestras, y su posición final refleja el centro de masa de cada clúster.

Este gráfico nos permite evaluar de manera efectiva la cohesión y separación entre los clústeres.

Idealmente, buscamos clústeres bien separados y compactos, lo que indica una agrupación clara y significativa dentro del espacio de características seleccionadas: Annual Income (K$) y Spending Score (1-100). La visualización proporciona una confirmación visual de la efectividad de nuestra selección de parámetros para K-Means y del número de clústeres, permitiéndonos avanzar con confianza en nuestro análisis de los segmentos de clientes identificados.

--

--