En cualquier tipo de negocio, más allá de generar un exhaustivo etiquetado de los datos, es esencial agruparlos y clasificarlos según determinadas características. Estos patrones son esenciales para entender el comportamiento de nuestros datos, siendo especialmente útil en ámbitos como el Marketing Digital. Es en este campo en concreto donde este tipo de técnicas son utilizadas de manera recurrente para poder llevar a cabo acciones tan importantes como: audiencias, segmentos, targets, etc. Para ello existen decenas de implementaciones que dependerán siempre de las necesidades o del tipo de análisis a llevar a cabo.

En este artículo me centraré en desarrollar en Python únicamente algunas de las más conocidas dentro de los modelos de aprendizaje no-supervisados (unsupervised learning), concretamente las referidas a algoritmos de Clustering. Pero antes de comenzar con la implementación paso a paso, debo recordar que lo que a continuación se muestra es una pequeñísima muestra de lo que aparecerá de manera mucho más detallada y con más ejemplos prácticos reales en mi nuevo libro en 2024 sobre Analítica avanzada de los principales KPIs de negocio con Python.

 

Clustering en Python

 

A lo largo de la siguiente implementación se alternarán partes de código Python con explicaciones teóricas como si de un notebook al uso se tratara. Empecemos entonces con el desarrollo paso a paso …

     1.   Para poder generar a continuación las diferentes técnicas de clusterización, es necesario tener un conjunto de datos de ejemplo. En este caso se han extraido del dataset tipo ‘Iris color’, el cual tiene datos sobre la anchura y la longitud del sépalo y el pétalo de 3 especies de la flor Iris. Aunque ésto es irrelevante para entender la verdadera importancia de la clusterización en las estrategias y las acciones de un negocio.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_iris

ir = load_iris()
df = pd.DataFrame
    data= np.c_[ir['data'], ir['target']],
    columns= ir['feature_names'] + ['target']
    )
df.rename(columns={'sepal width (cm)':'X1','petal width (cm)':'X2','target':'Y'}, inplace=True)
df = df[['X1','X2','Y']]

sns.scatterplot(x = 'X1', y = 'X2', data = df, hue = 'Y')
plt.show()
Dataset con datos de ejemplo

Visualización de dataset con datos de ejemplo.

     2.   Lo siguiente y generalmente recomendable es normalizar los datos. Aunque en realidad, no en todos los casos es necesario. En este caso se ha realizado a través del z-score (z = (x – u) / s). Por otro lado, el método fit_transform() se utiliza para ajustar adecuar los datos a los modelos. Esto ahorra tiempo evitando llamadas a fit() y a transform() por separado. En es te caso y puesto que se trata de una implementación simplificada se han añadido las variables descriptivas (features) X1 y X2, las cuales equivaldrían a transcribirlo como fit_transform(X) siendo X el conjunto de entrenamiento (train) de éstas. Además, en el subconjunto de datos de ejemplo finalmente seleccionado se ha mantenido la etiqueta target (Y) correspondiente a las agrupaciones de especies manualmente identificadas (ver imagen previa). La clase Y se ha añadido simplemente como punto de control entre lo descrito en el dataset utilizado y los resultados mostrados a continuación para cada una de las clasterizaciones propuestas. A continuación y hasta el final del desarrollo se detallará cada uno de los algoritmos.

from sklearn.preprocessing import StandardScaler
X = StandardScaler().fit_transform(df[['X1','X2']])

     3.   KMEANS. Su objetivo principal es agrupar un conjunto de datos en K clústeres, donde éste es un número predefinido por el usuario. El algoritmo se basa esencialmente en la selección aleatoria de centroides en torno a los cuales se determina la agrupación basándose en la distancia entre puntos.

from sklearn.cluster import KMeans 
kmeans = KMeans(n_clusters = 3, random_state = 12)
kmeans.fit(X)
df['KmeansLabels'] = kmeans.predict(X)

     4.   KMEDOIDS. Simlar a k-means pero en vez de centroides, utiliza los puntos de datos reales del conjunto de datos. Éstos se denominan medoides y son los puntos con menor distancia media a todos los demás del clúster.

from sklearn_extra.cluster import KMedoids
kmedo = KMedoids(n_clusters = 3, random_state = 12)
kmedo.fit(X)
df['KMedoidLabels'] = kmedo.predict(X)

     5.   GAUSSIAN MIXTURE MODEL. Se asume que los datos en cada clúster siguen una distribución gaussiana (distribución normal). A diferencia de los dos anteriores, que asignan puntos de datos a un único clúster, GMM permite la asignación probabilística de puntos de datos a múltiples clústeres.

from sklearn.mixture import GaussianMixture
gmm = GaussianMixture(n_components = 3, random_state = 12)
gmm.fit(X) 
df['GmmLabels'] = gmm.predict(X)

     6.   AGGLOMERATIVE HIERARCHICAL. Agrupamiento jerárquico que gradualmente fusiona los clústeres más cercanos hasta un cierto nivel de profundidad predefinido. 

from sklearn.cluster import AgglomerativeClustering
aglc = AgglomerativeClustering(n_clusters = 3, linkage = 'single')
df['AggLabels'] = aglc.fit_predict(X)

     7.   DBSCAN. Density-Based Spatial Clustering of Applications with Noise en sus siglas en inglés se basa en la densidad de cada punto, en lugar de asumir que los clústeres tienen formas específicas. Esencialmente trata de definir a través del parámetro ε si dos puntos pueden considerarse vecinos y por lo tanto parte de un clúster y del parámetro minPts si una zona es suficientemente densa. En el siguiente código, además de generar las agrupaciones correspondientes, se muestran (a través de las dos últimas líneas del código) los índices de cada clúster y sus puntos asociados. Resaltar el índice -1 mostrado, el cual hace referencia a una zona con muy baja densidad de datos. O dicho de otra manera, señala una etiqueta como ruidosa (noisy).

from sklearn.cluster import DBSCAN
dbs = DBSCAN(eps=0.3,min_samples=4)
df['DBSLabels'] = dbs.fit_predict(X)

df['dbs_labels']=dbs.labels_
df['dbs_labels'].value_counts()

     8.   AFFINITY PROPAGATION. Como ocurre con DBSCAN, no es necesario definir previamente el número de clústeres ya que el propio algoritmo es capaz de encontrarlos automáticamente y asigna los puntos a cada uno de ellos. Su funcionamiento se basa esencialmente en la crecaión de una matriz de similitud que mide la afinidad entre todos los pares de puntos, bien a través de alguna distancia o bien a través de alguna medida de similitud entre features.

from sklearn.cluster import AffinityPropagation
afp = AffinityPropagation(damping=0.9)
afp.fit(X)
df['AffinityProp'] = afp.predict(X)

Además de estos seis algoritmos de Clustering, existen muchos más igualmente útiles. La necesidad de usar cada uno de ellos dependenderá de la tipología del proyecto. Algunos otros habitualmente usados son: BIRCH (Balanced Iterative Reducing and Clustering using Hierarchies), OPTICS (Ordering Points To Identify the Clustering Structure), etc.

Además, se debe tener en cuenta que todos ellos pueden ser fácilmente combinados y comparados entre sí (ensemble methods) con la intención de obtener el mejor resultado posible. En este escenario será muy importante tener en cuenta los recursos de rendimiento y de tiempo disponibles (ingeniería de datos).

Tras estas apreciaciones y para finalizar este desarrollo en Python, solo queda generar la visualización final a través de Matplotliby Seaborn …

fig, axs = plt.subplots(nrows=2,ncols=3,figsize=(12, 12))

sns.scatterplot(x = 'X1', y = 'X2', data = df, hue = 'KmeansLabels', ax=axs[0,0])
sns.scatterplot(x = 'X1', y = 'X2', data = df, hue = 'KMedoidLabels', ax=axs[0,1])
sns.scatterplot(x = 'X1', y = 'X2', data = df, hue = 'GmmLabels', ax=axs[0,2])
sns.scatterplot(x = 'X1', y = 'X2', data = df, hue = 'AggLabels', ax=axs[1,0])
sns.scatterplot(x = 'X1', y = 'X2', data = df, hue = 'DBSLabels', ax=axs[1,1])
sns.scatterplot(x = 'X1', y = 'X2', data = df, hue = 'AffinityProp', ax=axs[1,2])
Algoritmos de Clustering más utilizados

Algoritmos de Clustering más conocidos.

Antes de comenzar con las conclusiones debo detallar que en este artículo no se han tratado las metodologías habituales para especificar el número de clústeres más óptimo para cada tipo de algoritmo previamente mostrado (elbow method, silhouette score, BIC or AIC, etc.). Son muchas las alternativas y todas ellas requieren de un estudio pormenorizado.

 

Conclusiones

 

Como se puede ver en la última imagen la ciencia de datos, en este caso a través de modelos machine learning, no depende únicamente de la validación de lo datos o la generación de resultados. Es mucho más, es esencial entender los datos para plasmar y obtener exactamente lo que se requiere desde el punto de visto del negocio. A simple vista se podría decir que los modelos más certeros y cercanos a la realidad son en primera instancia el GMM seguido del AffinityPropagation. Sin embargo, esta suposición requiere de un estudio mucho más profundo involucrando un mayor número de datos.

En este tipo de circunstancias será esencial entender cómo todo ésto puede aplicarse al flujo y a la lógica interna de cada compañía. Por eso es primordial tener en cuenta e involucrar a otros equipos con larga experiencia (además del dpto. de Analítica) en la generación de estrategias y acciones, como puede ser el dpto. de Marketing (por lo general uno de los principales beneficiados de este tipo de análisis).

El análisis de datos no solo se refiere a la extracción de éstos, también y mucho más importante, a su adecuación a los casos de uso de cada empresa. Las experiencias previas y el conocimiento de los clientes es esencial para poder analizar datos con seguridad. 

Por último, solo queda recordar antes de despedirme que si quieres seguir aprendiendo sobre este tipo de implementaciones de Analítica avanzada o saber más en torno al Marketing Digital, te invito a que visites el resto de artículos de mi Blog. ¡Te espero en el siguiente artículo!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *