Introducción al clustering (I): algoritmo k-means

Nov 9, 2021 | Machine Learning | 0 Comentarios

¿Qué es el aprendizaje no supervisado?

En el machine learning, las técnicas de aprendizaje no supervisado nos permiten descubrir estructuras ocultas en los datos. A diferencia del aprendizaje supervisado, en este caso no trabajamos con datos etiquetados para entrenar los modelos, ya que el objetivo no es predecir la clase de salida.

De esta manera, al no contar con datos etiquetados, sólo podemos descubrir los patrones que se producen de forma natural en el conjunto de datos.

Una de las principales técnicas del aprendizaje no supervisado es el clustering. El objetivo del clustering consiste en encontrar grupos de instancias (llamados clusters) que están relacionadas entre sí.

Esta técnica tiene innumerables aplicaciones como la detección de outliers, la segmentación de clientes o los sistemas de recomendación.

Hay diferentes tipos de algoritmos de clustering y cada uno de ellos elige los clusters de manera distinta. En este artículo nos centraremos en el popular algoritmo k-means, el cual busca instancias centradas en un punto determinado, llamado centroide. Después de explicar su funcionamiento, lo aplicaremos en Python a un conjunto de datos y visualizaremos los resultados obtenidos.

 

Funcionamiento del algoritmo k-means

El algoritmo k-means es un método de clustering muy utilizado que coge cada punto de nuestro dataset e intenta asignarle un grupo o clúster de manera iterativa. El objetivo es asignar cada punto a un grupo en base a la similitud de sus características.

De esta manera, los pasos que sigue el algoritmo k-means para encontrar los grupos en función de nuestros datos son los siguientes:

  1. Se eligen de manera aleatoria las coordenadas de los k centroides iniciales del conjunto de datos. Los centroides son los puntos que marcan el centro de cada agrupación
  2. Una vez se han inicializado los centroides, se agrupan cada punto con el centroide más cercano. Para ello se utiliza una medida de distancia como la distancia euclídea.
  3. Se actualizan los centroides cambiando su posición al centro de las muestras que le fueron asignadas.
  4. Se repiten los pasos 2 y 3 hasta que se cumpla un cierto criterio de parada establecido por el usuario. Estos criterios de parada pueden ser:
  • Las asignaciones de clústeres no cambian o se alcanza un umbral de tolerancia definido.
  • Se alcanza un número máximo de iteraciones.

Para saber que agrupamiento es mejor y poder recalcular los centroides iterativamente, deberemos utilizar una función que nos permita calcular la distancia entre dos puntos x e y. La función de distancia que normalmente se utiliza en clustering es la distancia euclídea al cuadrado:

eucl1

donde m es el número de dimensiones de nuestros datos.

Cuando se utiliza la distancia euclídea, la idea del algoritmo consiste en elegir los centroides que minimicen la suma de errores al cuadrado (SSE):

euc3

donde k es el número de grupos y μ(j) es el centroide del cluster j.

Veamos ahora como aplicarlo a nuestros datos!

 

Aplicando el k-means a nuestro conjunto de datos

Una vez hemos aprendido el funcionamiento de este algoritmo, veamos cómo aplicarlo a nuestro conjunto de datos. Aunque k-means puede aplicarse a datos de mayor dimensión, en este tutorial vamos a utilizar datos bidimensionales para poder visualizarlos de manera sencilla.

En primer lugar, cargamos en conjunto de datos y lo convertimos en un Dataframe de Pandas:

 

In [1]:
import pandas as pd

# Cargamos el conjunto de datos
df = pd.read_csv ('data/data.csv')

# Mostramos las primeras observaciones
df.head()
Out[1]:
xy
068183
1436
278186
369194
47154

A continuación, mostramos una gráfica de dispersión con todos los puntos para buscar agrupaciones entre los datos:

 

In [2]:
import matplotlib.pyplot as plt

# Mostramos un diagrama de dispersión
df.plot.scatter(x='x', y='y', c='DarkGreen')
plt.show()

grafica_cl1

Como podemos ver en la anterior gráfica, hay 5 grupos bastante bien diferenciados, por lo que elegiremos 5 clústers.

Es recomendable estandarizar o normalizar los datos antes de aplicarles el algoritmo k-means en el caso de que no tengan la misma escala. En este caso utilizamos la clase MinMaxScaler de de scikit-learn que normaliza todos los datos entre unos límites definidos, por defecto entre 0 y 1.

In [3]:
from sklearn.preprocessing import MinMaxScaler

# Normalizamos los datos
min_max_scaler = MinMaxScaler() 
df = min_max_scaler.fit_transform(df)
df = pd.DataFrame(df) # Convertimos a Dataframe

Veamos el resultado después de transformar las variables:

In [4]:
# Mostramos los datos escalados
df.head(5)
Out[15]:
01
00.5555560.786364
10.0085470.118182
20.6410260.800000
30.5641030.836364
40.0341880.654545
Ahora, es hora de aplicar el algoritmo k-means a nuestros datos. Para ello simplemente utilizaremos la clase KMeans de la librería scikit-learn pasándole como argumento los siguientes parámetros:

  • n_clusters: el número de clusters y de centroides a generar. En este caso utilizaremos 5.
  • n_init: método de inicialización. Para este ejemplo utilizamos la opción “random”, que se encarga de elegir n_clusters observaciones (filas) al azar de los datos para los centroides iniciales.
  • max_iter: número máximo de iteraciones del algoritmo k-means para una sola ejecución.
  • random_state determina la generación de números aleatorios para la inicialización del centroide.

Por supuesto, hay más parámetros para tener en cuenta y que podéis consultar en la documentación de scikit-learn, pero en este tutorial solo utilizaremos los anteriores descritos.

En el siguiente código mostramos como aplicar k-means a nuestro dataset:

In [5]:
from sklearn.cluster import KMeans

# Aplicamos k-means a nuestro dataset
km = KMeans(n_clusters=5, init='random', 
            max_iter=200, random_state=0)
y_km = km.fit_predict(df)

Así de fácil. Ahora veamos como podemos visualizar los resultados obtenidos.

 

Visualizando los grupos

Una vez ya tenemos el cluster asignado a cada observación, vamos a visualizarlos junto con la localización de los centroides. Para ello, utilizamos el siguiente código:

In [6]:
# Gráfico con los puntos y su cluster y los centroides
plt.figure(figsize=(8,8))
plt.scatter(df[y_km == 0][0], df[y_km == 0][1], 
            s=50, c='green', marker='o', 
            edgecolor='black', label='cluster 1')
plt.scatter(df[y_km == 1][0], df[y_km == 1][1],  
            s=50, c='orange', marker='s', 
            edgecolor='black', label='cluster 2')
plt.scatter(df[y_km == 2][0], df[y_km == 2][1], 
            s=50, c='lightblue', marker='v', 
            edgecolor='black', label='cluster 3')
plt.scatter(df[y_km == 3][0], df[y_km == 3][1], 
            s=50, c='purple', marker='d', 
            edgecolor='black', label='cluster 4')
plt.scatter(df[y_km == 4][0], df[y_km == 4][1], 
            s=50, c='brown', marker='p', 
            edgecolor='black', label='cluster 5')
plt.scatter(km.cluster_centers_[:, 0], 
            km.cluster_centers_[:, 1], s=200, 
            marker='*', c='red', 
            edgecolor='black', label='centroides')
plt.legend(loc="best")
plt.grid()
plt.show()

imaclu2

En el gráfico anterior podemos ver los puntos coloreados según el cluster al que pertenecen.

Como hemos visto, en este algoritmo de clustering es necesario especificar el número de clusters que queremos a priorio. Este es el mayor inconveniente de este método, ya que si elegimos un número de clusters inadecuado puede afectar negativamente a su rendimiento

Hay varios métodos para elegir el número óptimo de clústers a utilizar en el algoritmo. Una de las técnicas que se utiliza comúnmente es la gráfica elbow.

 

En este tutorial, hemos explicado el funcionamiento del algoritmo de clustering k-means y como se aplica a un conjunto de datos en Python. En futuras publicaciones mostraremos como obtener el número óptimo de clusters y otros métodos de agrupamiento, como, por ejemplo, el jerárquico.

Por último, recordar que todo el código utilizado en este tutorial se puede descargar desde nuestro repositorio de Github.

También te puede interesar:

Diferencias entre inferencia y predicción

Entiende las diferencias entre inferencia y predicción, dos conceptos de la estadística y el machine learning que pueden resultar confusos.

Libros recomendados para adentrarse en el machine learning

Lista de cinco libros recomendables para principiantes que quieran aprender machine learning y ciencia de datos.

Introducción al topic modeling con Gensim (I): fundamentos y preprocesamiento de textos

En esta publicación entenderéis los fundamentos del topic modeling (modelo LDA) y se mostrará como realizar el preprocesamento necesario a los textos: tokenización, eliminación de stopwords, etc.

Introducción al topic modeling con Gensim (II): asignación de tópicos

En esta publicación aprenderás como entrenar un modelo LDA con noticias periodísticas para la asignación de tópicos, usando para ello la librería Gensim de Python.

Introducción al topic modeling con Gensim (III): similitud de textos

En este post mostramos como utilizar la técnica de topic modeling para obtener la similitud entre textos teniendo en cuenta la semántica

Sentiment analysis en críticas de películas mediante regresión logística

El sentimiento de análisis es una técnica que nos permite identificar la opinión emocional que hay detrás de un textol. En este artículo mostramos como construir un modelo de predicción capaz de distinguir entre críticas positivas y negativas. Estas críticas han sido descargadas previamente de la web de filmaffinity.

AutoML: creación de un modelo de análisis de sentimiento con Google Cloud AutoML

Descubre en que consiste el AutoML, que nos permite automatizar varias partes del proceso de Machine Learning y aprende a utilizar Google Cloud AutoML para realizar una tarea de sentiment analysis y construir un clasificador capaz de identificar si una crítica de película es positiva o negativa.