¿Te suena haber escuchado más de una vez algo sobre el K-Means o el clustering ? Normal. Se trata de uno de los algoritmos de Machine Learning no supervisados más utilizados por los Data Scientists y que además es muy fácil tanto de usar como de interpretar.
En este post voy a hacer que entiendas qué es el clustering y que sepas aplicar correctamente el K-Means.
Qué es el Clustering
El clustering es de las herramientas más utilizadas en Machine Learning durante el EDA para ver segmentaciones de los datos y tener una intuición de cómo están estructurados los datos.
Esta técnica no supervisada se basa en identificar grupos en los datos de tal manera que todos los datos del grupo (clúster) son datos con características similares mientras que los datos de los otros grupos son diferentes.
Algoritmo K Means
El objetivo de K-Means es claro: agrupar observaciones similares para descubrir patrones que a simple vista se desconocen. Para conseguirlo, el algoritmo busca un número fijo (k) de clústers en el dataset.
Regla del codo
Este número k es un hiperparámetro del algoritmo. Representa el número de centroides (centro del clúster) que queremos encontrar en el dataset. Para saber qué k tenemos que coger utilizamos el método del codo o regla del codo que explico durante el caso práctico.
El algoritmo intenta minimizar la distancia entre las observaciones que pertenecen a un clúster y su centroide. Es decir, el objetivo del K-Means es minimizar la suma de las distancias entre los puntos y el centroide al que pertenecen.
Funcionamiento paso a paso del algoritmo K-Means
Suponiendo que tenemos los datos de la imagen de abajo, los pasos de ejecución del algoritmo son los siguientes:

- Elección del número de clústers k
El primer paso siempre es elegir en cuantas agrupaciones queremos segmentar los datos.
- Inicializar las coordenadas de los centroides
Los centroides se inicializan en coordenadas aleatorias. Suponiendo que tenemos k=2, iniciamos dos centroides, uno rojo y otro verde, en puntos aleatorios de los datos.
- Asignamos cada punto a un clúster
Se calcula la distancia de cada punto a cada centroide, y se agrupa con aquel centroide más próximo.
- Se recalculan los centroides de los clústers
Una vez tenemos todos los puntos asignados a un clúster, se recalculan los centroides de manera que vuelven a ser los centros de cada clúster.
- Se repiten los pasos 3 y 4 hasta que se llega al criterio de parada.
El proceso de asignar cada punto a un clúster y calcular los centros se repite hasta que se cumple el criterio de parada estipulado.
Criterio de parada para K Means Clustering
Existen tres criterios para terminar el algoritmo:
- Los centroides dejan de cambiar. Es decir, después de múltiples iteraciones, los centroides de cada clúster no cambian. Por lo que se asume que el algoritmo ha convergido.
- Los puntos dejan de cambiar de clúster. Parecido al anterior, pero esta vez no nos fijamos en los centroides, si no en los puntos que pertenecen a cada clúster. Cuando se observa que no hay un intercambio de clústers se asume que el modelo está entrenado.
- Límite de iteraciones. Podemos fijar un número máximo de iteraciones que queremos que nuestro algoritmo ejecute antes de pararlo. Cuando llega a ese número, se asume que el modelo no va a mejorar drásticamente y se para el entrenamiento.
Caso Práctico – Algoritmo K-Means en Python
Para demostrar el potencial del algoritmo, vamos a realizar segmentación de clientes de un centro comercial utilizando K-Means. Los datos que vamos a utilizar los podemos encontrar en Kaggle.
Lo primero de todo, como siempre, es importar las librerias que vamos a necesitar para el ejemplo:
# Importamos las librerias necesarias import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import plotly as py import plotly.io as pio import plotly.express as px from sklearn.cluster import KMeans from sklearn import preprocessing from yellowbrick.cluster import KElbowVisualizer import warnings warnings.filterwarnings("ignore") py.offline.init_notebook_mode(connected = True) pio.renderers.default='browser'
Vamos a ver qué tenemos…
df = pd.read_csv('/content/Mall_Customers.csv') print('Dimensiones del df:', df.shape) #____________________________________________________________ # Vamos a sacar informacion sobre los tipos y nulos del df df.drop_duplicates(inplace = True) tab_info=pd.DataFrame(df.dtypes).T.rename(index={0:'tipo de la columna'}) tab_info=tab_info.append(pd.DataFrame(df.isnull().sum()).T.rename(index={0:'campos nulos (cant)'})) tab_info=tab_info.append(pd.DataFrame(df.isnull().sum()/df.shape[0]*100).T. rename(index={0:'campos nulos (%)'})) display(tab_info) #__________________ # display(df[:5])

Como hemos dicho antes, K-Means encuentra clústers basándose en la distancia, por lo que es importante que no tengamos variables categóricas. En nuestro caso, Gender es una de ellas. Vamos a pasarla a binaria en el que ‘Hombre’ vale 0 y ‘Mujer’ 1. Vamos a ver la distribución de las demás variables también:
df['Gender'] = pd.get_dummies(df['Gender']).values[:,0] plt.style.use('fivethirtyeight') plt.figure(1 , figsize = (15 , 6)) n = 0 for x in ['Age' , 'Annual Income (k$)' , 'Spending Score (1-100)']: n += 1 plt.subplot(1 , 3 , n) plt.subplots_adjust(hspace =0.5 , wspace = 0.5) sns.distplot(df[x] , bins = 20) plt.title('Distplot of {}'.format(x))


Tenemos CustomerID, que es una variable identificadora. Como esta variable no va a aportarnos nada a la hora de clusterizar nos la cargamos. El siguiente paso será normalizar las variables para que todas estén en la misma escala y no afecte a la hora de calcular la distancia entre puntos:
X = df.copy() X.drop(labels=['CustomerID'], axis=1, inplace=True) X1 = preprocessing.normalize(X)
Empezamos con el algoritmo
Elección de k con la regla del codo
Ahora viene la chicha del post. Vamos a elegir el número de clústers idóneos para nuestro problema. Para ello, vamos a realizar varias ejecuciones con una k diferente (desde 1 clúster hasta 12) y representaremos en un gráfico la distancia media de cada punto hasta su centroide y el tiempo de entrenamiento necesario.
La idea es que a medida que vamos aumentando la cantidad de centroides, la distancia media de los puntos al centroide irá disminuyendo cada vez menos. La norma mnemotécnica es la norma del codo puesto que la gráfica es una curva y el número de clústers óptimo será el ‘codo’ del brazo.
La librería yellowbrick tiene un método rápido para visualizar esto.
model = KMeans() visualizer = KElbowVisualizer(model, k=(1,12)) visualizer.fit(X1) # Entrenamos con los datos visualizer.show() # Renderizamos la imagen

En nuestro caso, cualquier número de cl?sters entre 4 y 6 nos valdría. Este es un punto donde entra el criterio experto para tomar la decisión de cual coger. Yo me voy a fiar de yellowbrick y me quedo con k=4.
Ahora ya solo nos queda entrenar K-Means con k=4 y ver los resultados.
algorithm = KMeans(n_clusters = 5 ,init='k-means++', n_init = 10 ,max_iter=300, tol=0.0001, random_state= 111 , algorithm='elkan') algorithm.fit(X1) labels = algorithm.labels_ centroids = algorithm.cluster_centers_ df['label'] = labels
Visualización
Para la visualización yo he optado por usar plotly. Se trata de una librería de visualización que permite crear gráficos interactivos. Podeis utilizar también bokeh, como os enseño en este post.
fig = px.scatter_3d(df, x='Age', y='Spending Score (1-100)', z='Annual Income (k$)', color='label') fig.show() fig.write_html("/content/file.html")
En la imagen anterior podemos ver claramente los 4 clústers, aunque vemos que los clústers 2 y 4 son parecidos en el centro de la figura, vamos a realizar un PCA para poder mostrar las 3 componentes principales a ver si es verdad que son diferentes. (Por cierto, aquí tienes explicado el PCA).
from sklearn.decomposition import PCA pca = PCA(n_components=3) # Entrenamos el PCA con nuestros datos, y lo aplicamos a los datos principalComponents = pca.fit_transform(X1) principalDf = pd.DataFrame(data = principalComponents , columns = ['component 1', 'component 2', 'component 3']) principalDf['label'] = df['label'] fig = px.scatter_3d(principalDf, x='component 1', y='component 2', z='component 3', color='label') fig.show()
Ahora podemos ver como los clústers están sin mezclar, por lo que, como hemos dicho al principio del post, el K-Means ayuda a descubrir patrones ocultos en los datos.
Desventajas del K-Means
Ya hemos visto la potencia que tiene este algoritmo. Por lo sencillo que es de aplicar y la valiosa información sobre nuestros datos que nos aporta. Como no es oro todo lo que reluce, tengo que comentaros también las desventajas que ofrece:
- Tenemos que elegir k nosotros mismos. Es muy posible que nosotros cometamos un error, o que sea imposible escoger una k óptima.
- Es sensible a outliers. Los casos extremos hacen que el clúster se vea afectado. Aunque esto puede ser algo positivo a la hora de detectar anomalías.
- Es un algoritmo que sufre de la maldición de la dimensionalidad.
Conclusión
El clústering es una técnica muy popular para problemas sin etiqueta y también para tareas de EDA. El K-Means es el rey de esta técnica por su sencillez tanto de entender como de aplicar. Se basa en agrupar los datos según la distancia entre ellos. Aunque como todo en esta vida tiene peros.
¿Quieres aprender ML desde lo básico? Te dejo 2 post para que te inicies en este mundo.
Agradezco tu interes y sin duda a tu persona por compartir tu conocimiento, que por cierto resulta valioso