Guía definitiva de agrupamiento jerárquico con Python y Scikit-Learn PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

Guía definitiva de agrupamiento jerárquico con Python y Scikit-Learn

Introducción

En esta guía, nos centraremos en implementar la Algoritmo de agrupamiento jerárquico con Scikit-Learn para resolver un problema de marketing.

Después de leer la guía, comprenderá:

  • Cuándo aplicar el agrupamiento jerárquico
  • Cómo visualizar el conjunto de datos para comprender si es apto para el agrupamiento
  • Cómo preprocesar características y diseñar nuevas características basadas en el conjunto de datos
  • Cómo reducir la dimensionalidad del conjunto de datos usando PCA
  • Cómo usar y leer un dendograma para separar grupos
  • ¿Cuáles son los diferentes métodos de vinculación y métricas de distancia que se aplican a los dendrogramas y algoritmos de agrupamiento?
  • ¿Qué son las estrategias de agrupamiento aglomerativo y divisivo y cómo funcionan?
  • Cómo implementar el Clustering Jerárquico Aglomerativo con Scikit-Learn
  • Cuáles son los problemas más frecuentes al trabajar con algoritmos de clustering y cómo solucionarlos

Nota: Puede descargar el cuaderno que contiene todo el código en esta guía esta página.

Motivación

Imagine un escenario en el que forma parte de un equipo de ciencia de datos que interactúa con el departamento de marketing. El departamento de marketing ha estado recopilando datos de compras de los clientes durante un tiempo y quieren comprender, en función de los datos recopilados, si hay similitudes entre clientes. Esas similitudes dividen a los clientes en grupos y tener grupos de clientes ayuda en la orientación de campañas, promociones, conversiones y en la construcción de mejores relaciones con los clientes.

¿Hay alguna manera de ayudar a determinar qué clientes son similares? ¿Cuántos de ellos pertenecen al mismo grupo? ¿Y cuántos grupos diferentes hay?

Una forma de responder a estas preguntas es mediante el uso de un clustering algoritmo, como K-Means, DBSCAN, agrupamiento jerárquico, etc. En términos generales, los algoritmos de agrupamiento encuentran similitudes entre los puntos de datos y los agrupan.

En este caso, nuestros datos de marketing son bastante pequeños. Tenemos información de sólo 200 clientes. Teniendo en cuenta el equipo de marketing, es importante que podamos explicarles claramente cómo se tomaron las decisiones en función de la cantidad de clústeres y, por lo tanto, explicarles cómo funciona realmente el algoritmo.

Dado que nuestros datos son pequeños y la explicabilidad es un factor importante, podemos aprovechar Agrupación jerárquica para resolver este problema. Este proceso también se conoce como Análisis de agrupamiento jerárquico (HCA).

Una de las ventajas de HCA es que es interpretable y funciona bien en conjuntos de datos pequeños.

Otra cosa a tener en cuenta en este escenario es que HCA es un sin supervisión algoritmo. Al agrupar datos, no tendremos forma de verificar que estamos identificando correctamente que un usuario pertenece a un grupo específico (no conocemos los grupos). No hay etiquetas con las que comparar nuestros resultados. Si identificamos los grupos correctamente, el departamento de marketing lo confirmará más tarde en el día a día (medido por métricas como el ROI, las tasas de conversión, etc.).

Ahora que hemos entendido el problema que estamos tratando de resolver y cómo resolverlo, ¡podemos comenzar a echar un vistazo a nuestros datos!

Breve análisis exploratorio de datos

Nota: Puede descargar el conjunto de datos utilizado en esta guía esta página.

Después de descargar el conjunto de datos, observe que es un CSV (valores separados por comas) archivo llamado shopping-data.csv. Para facilitar la exploración y manipulación de los datos, los cargaremos en un DataFrame usando pandas:

import pandas as pd


path_to_file = 'home/projects/datasets/shopping-data.csv'
customer_data = pd.read_csv(path_to_file)

Marketing dijo que había recopilado 200 registros de clientes. Podemos verificar si los datos descargados están completos con 200 filas usando el shape atributo. Nos dirá cuántas filas y columnas tenemos, respectivamente:

customer_data.shape

Esto resulta en:

(200, 5)

¡Excelente! Nuestros datos están completos con 200 filas (registros de clientes) y también tenemos 5 columnas (caracteristicas). Para ver qué características ha recopilado el departamento de marketing de los clientes, podemos ver los nombres de las columnas con el columns atributo. Para hacer eso, ejecute:

customer_data.columns

El script anterior devuelve:

Index(['CustomerID', 'Genre', 'Age', 'Annual Income (k$)',
       'Spending Score (1-100)'],
      dtype='object')

Aquí vemos que el marketing ha generado un CustomerID, reunió la Genre, Age, Annual Income (en miles de dólares), y un Spending Score yendo de 1 a 100 para cada uno de los 200 clientes. Cuando se les pidió una aclaración, dijeron que los valores en el Spending Score columna significa con qué frecuencia una persona gasta dinero en un centro comercial en una escala del 1 al 100. En otras palabras, si un cliente tiene una puntuación de 0, esta persona nunca gasta dinero, y si la puntuación es 100, acabamos de detectar el mayor gastador.

Echemos un vistazo rápido a la distribución de este puntaje para inspeccionar los hábitos de gasto de los usuarios en nuestro conjunto de datos. Ahí es donde los pandas hist() El método entra para ayudar:

customer_data['Spending Score (1-100)'].hist()

img

Al observar el histograma, vemos que más de 35 clientes tienen puntajes entre 40 y 60, entonces menos de 25 tienen puntajes entre 70 y 80. Así que la mayoría de nuestros clientes son gastadores equilibrados, seguido por los consumidores de gasto moderado a alto. También podemos ver que hay una línea después 0, a la izquierda de la distribución, y otra línea antes de la 100, a la derecha de la distribución. Estos espacios en blanco probablemente significan que la distribución no contiene personas que no gastan, lo que tendría una puntuación de 0, y que tampoco hay grandes gastadores con una puntuación de 100.

Para verificar si eso es cierto, podemos mirar los valores mínimo y máximo de la distribución. Esos valores se pueden encontrar fácilmente como parte de las estadísticas descriptivas, por lo que podemos usar el describe() método para obtener una comprensión de otras distribuciones de valores numéricos:


customer_data.describe().transpose()

Esto nos dará una tabla desde donde podemos leer las distribuciones de otros valores de nuestro conjunto de datos:

 						count 	mean 	std 		min 	25% 	50% 	75% 	max
CustomerID 				200.0 	100.50 	57.879185 	1.0 	50.75 	100.5 	150.25 	200.0
Age 					200.0 	38.85 	13.969007 	18.0 	28.75 	36.0 	49.00 	70.0
Annual Income (k$) 		200.0 	60.56 	26.264721 	15.0 	41.50 	61.5 	78.00 	137.0
Spending Score (1-100) 	200.0 	50.20 	25.823522 	1.0 	34.75 	50.0 	73.00 	99.0

Nuestra hipótesis se confirma. los min valor de la Spending Score is 1 y el maximo es 99. entonces no tenemos 0 or 100 gastadores de puntuación. Entonces echemos un vistazo a las otras columnas de la transpuesta describe mesa. Al mirar el mean y std columnas, podemos ver que para Age las mean is 38.85 y del std es de aproximadamente 13.97. Lo mismo sucede para Annual Income, Con un mean of 60.56 y std 26.26, Y para Spending Score con un mean of 50 y std of 25.82. Para todas las características, el mean está lejos de la desviación estándar, lo que indica nuestros datos tienen una alta variabilidad.

Para comprender mejor cómo varían nuestros datos, representemos gráficamente Annual Income distribución:

customer_data['Annual Income (k$)'].hist()

Lo cual nos dará:

img

Observe en el histograma que la mayoría de nuestros datos, más de 35 clientes, se concentran cerca del número 60, en nuestro mean, en el eje horizontal. Pero, ¿qué sucede a medida que avanzamos hacia los extremos de la distribución? Yendo hacia la izquierda, de la media de $60.560, el siguiente valor que encontraremos es de $34.300 – la media ($60.560) menos la variación estándar ($26.260). Si nos alejamos más a la izquierda de nuestra distribución de datos, se aplica una regla similar, restamos la variación estándar ($26.260) del valor actual ($34.300). Por lo tanto, encontraremos un valor de $8.040. Observe cómo nuestros datos pasaron rápidamente de $ 60k a $ 8k. Está “saltando” $26.260 cada vez, variando mucho, y es por eso que tenemos una variabilidad tan alta.

img

La variabilidad y el tamaño de los datos son importantes en el análisis de agrupamiento porque las mediciones de distancia de la mayoría de los algoritmos de agrupamiento son sensibles a las magnitudes de los datos. La diferencia de tamaño puede cambiar los resultados de la agrupación al hacer que un punto parezca más cercano o más distante de otro de lo que realmente es, distorsionando la agrupación real de datos.

Hasta ahora, hemos visto la forma de nuestros datos, algunas de sus distribuciones y estadísticas descriptivas. Con Pandas, también podemos enumerar nuestros tipos de datos y ver si todas nuestras 200 filas están llenas o tienen algunos null valores:

customer_data.info()

Esto resulta en:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 200 entries, 0 to 199
Data columns (total 5 columns):
 #   Column                  Non-Null Count  Dtype 
---  ------                  --------------  ----- 
 0   CustomerID              200 non-null    int64 
 1   Genre                   200 non-null    object
 2   Age                     200 non-null    int64 
 3   Annual Income (k$)      200 non-null    int64 
 4   Spending Score (1-100)  200 non-null    int64 
dtypes: int64(4), object(1)
memory usage: 7.9+ KB

Aquí podemos ver que no hay null valores en los datos y que solo tenemos una columna categórica: Genre. En esta etapa, es importante que tengamos en cuenta qué características parecen interesantes para agregar al modelo de agrupamiento. Si queremos agregar la columna Género a nuestro modelo, necesitaremos transformar sus valores de categórico a numérico.

Veamos como Genre se llena echando un vistazo rápido a los primeros 5 valores de nuestros datos:

customer_data.head() 

Esto resulta en:

    CustomerID 	Genre 	Age 	Annual Income (k$) 	Spending Score (1-100)
0 	1 			Male 	19 		15 					39
1 	2 			Male 	21 		15 					81
2 	3 			Female 	20 		16 					6
3 	4 			Female 	23 		16 					77
4 	5 			Female 	31 		17 					40

Parece que solo tiene Female y Male categorías. Podemos estar seguros de eso al echar un vistazo a sus valores únicos con unique:

customer_data['Genre'].unique()

Esto confirma nuestra suposición:

array(['Male', 'Female'], dtype=object)

Hasta ahora, sabemos que solo tenemos dos géneros, si planeamos usar esta función en nuestro modelo, Male podría transformarse en 0 y Female a 1. También es importante comprobar la proporción entre géneros, para ver si están equilibrados. Podemos hacer eso con el value_counts() método y su argumento normalize=True para mostrar el porcentaje entre Male y Female:

customer_data['Genre'].value_counts(normalize=True)

Esto produce:

Female    0.56
Male      0.44
Name: Genre, dtype: float64

Tenemos un 56 % de mujeres en el conjunto de datos y un 44 % de hombres. La diferencia entre ellos es solo del 16%, y nuestros datos no son 50/50 pero son lo suficientemente equilibrado para no causar ningún problema. Si los resultados fueron 70/30, 60/40, entonces podría haber sido necesario recopilar más datos o emplear algún tipo de técnica de aumento de datos para equilibrar esa proporción.

Hasta ahora, todas las características pero Age, han sido explorados brevemente. en que preocupaciones Age, suele ser interesante dividirlo en bins para poder segmentar a los clientes en función de sus grupos de edad. Si hacemos eso, necesitaríamos transformar las categorías de edad en un número antes de agregarlas a nuestro modelo. De esa forma, en lugar de usar la categoría 15-20 años, contaríamos cuántos clientes hay en el 15-20 categoría, y ese sería un número en una nueva columna llamada 15-20.

Consejo: En esta guía, presentamos solo un breve análisis exploratorio de datos. Pero puedes ir más allá y debes ir más allá. Puede ver si hay diferencias de ingresos y diferencias de puntuación según el género y la edad. Esto no solo enriquece el análisis, sino que conduce a mejores resultados del modelo. Para profundizar en el análisis exploratorio de datos, consulte el Capítulo EDA en el “Predicción práctica del precio de la vivienda: aprendizaje automático en Python" Proyecto Guiado.

Después de conjeturar sobre lo que se podría hacer con ambos categóricos -o categóricos por ser- Genre y Age columnas, apliquemos lo comentado.

Codificación de variables e ingeniería de funciones

Comencemos dividiendo el Age en grupos que varían en 10, de modo que tenemos 20-30, 30-40, 40-50, etc. Dado que nuestro cliente más joven tiene 15 años, podemos comenzar a los 15 y terminar a los 70, que es la edad del cliente de mayor edad en los datos. Comenzando en 15 y terminando en 70, tendríamos intervalos de 15-20, 20-30, 30-40, 40-50, 50-60 y 60-70.

para agrupar o papelera Age valores en estos intervalos, podemos usar los Pandas cut() método para cortarlos en contenedores y luego asignar los contenedores a un nuevo Age Groups columna:

intervals = [15, 20, 30, 40, 50, 60, 70]
col = customer_data['Age']
customer_data['Age Groups'] = pd.cut(x=col, bins=intervals)


customer_data['Age Groups'] 

Esto resulta en:

0      (15, 20]
1      (20, 30]
2      (15, 20]
3      (20, 30]
4      (30, 40]
         ...   
195    (30, 40]
196    (40, 50]
197    (30, 40]
198    (30, 40]
199    (20, 30]
Name: Age Groups, Length: 200, dtype: category
Categories (6, interval[int64, right]): [(15, 20] < (20, 30] < (30, 40] < (40, 50] < (50, 60] < (60, 70]]

Tenga en cuenta que al mirar los valores de la columna, también hay una línea que especifica que tenemos 6 categorías y muestra todos los intervalos de datos agrupados. De esta manera, hemos categorizado nuestros datos previamente numéricos y creado una nueva Age Groups .

¿Y cuántos clientes tenemos en cada categoría? Podemos saberlo rápidamente agrupando la columna y contando los valores con groupby() y count():

customer_data.groupby('Age Groups')['Age Groups'].count()

Esto resulta en:

Age Groups
(15, 20]    17
(20, 30]    45
(30, 40]    60
(40, 50]    38
(50, 60]    23
(60, 70]    17
Name: Age Groups, dtype: int64

Es fácil detectar que la mayoría de los clientes tienen entre 30 y 40 años, seguidos por los clientes entre 20 y 30 y luego los clientes entre 40 y 50. Esta también es una buena información para el departamento de Marketing.

Por el momento, tenemos dos variables categóricas, Age y Genre, que necesitamos transformar en números para poder usar en nuestro modelo. Hay muchas formas diferentes de hacer esa transformación: usaremos los Pandas get_dummies() método que crea una nueva columna para cada intervalo y género y luego llena sus valores con 0 y 1; este tipo de operación se llama codificación one-hot. Veamos cómo se ve:


customer_data_oh = pd.get_dummies(customer_data)

customer_data_oh 

Esto nos dará una vista previa de la tabla resultante:

img

Con la salida, es fácil ver que la columna Genre se dividió en columnas - Genre_Female y Genre_Male. Cuando el cliente es mujer, Genre_Female es igual a 1, y cuando el cliente es hombre, es igual 0.

También el Age Groups columna se dividió en 6 columnas, una para cada intervalo, como Age Groups_(15, 20], Age Groups_(20, 30], y así. De la misma forma como Genre, cuando el cliente tenga 18 años, el Age Groups_(15, 20] Valor es 1 y el valor de todas las demás columnas es 0.

El competitiva de la codificación one-hot es la simplicidad en la representación de los valores de la columna, es sencillo entender lo que está sucediendo, mientras que el desventaja es que ahora hemos creado 8 columnas adicionales, para resumir con las columnas que ya teníamos.

advertencia: si tiene un conjunto de datos en el que la cantidad de columnas codificadas en caliente excede la cantidad de filas, es mejor emplear otro método de codificación para evitar problemas de dimensionalidad de los datos.

La codificación one-hot también agrega ceros a nuestros datos, haciéndolos más escasos, lo que puede ser un problema para algunos algoritmos que son sensibles a la escasez de datos.

Para nuestras necesidades de agrupamiento, la codificación one-hot parece funcionar. Pero podemos graficar los datos para ver si realmente hay grupos distintos para agrupar.

Trazado básico y reducción de dimensionalidad

Nuestro conjunto de datos tiene 11 columnas, y hay algunas formas en las que podemos visualizar esos datos. El primero es trazarlo en 10 dimensiones (buena suerte con eso). Diez porque el Customer_ID la columna no está siendo considerada. La segunda es trazando nuestras características numéricas iniciales, y la tercera es transformando nuestras 10 características en 2, por lo tanto, realizando una reducción de dimensionalidad.

Trazar cada par de datos

Dado que trazar 10 dimensiones es un poco imposible, optaremos por el segundo enfoque: trazaremos nuestras características iniciales. Podemos elegir dos de ellos para nuestro análisis de agrupamiento. Una forma en que podemos ver todos nuestros pares de datos combinados es con un Seaborn pairplot():

import seaborn as sns


customer_data = customer_data.drop('CustomerID', axis=1)

sns.pairplot(customer_data)

Que muestra:

img

De un vistazo, podemos detectar los diagramas de dispersión que parecen tener grupos de datos. Uno que parece interesante es el diagrama de dispersión que combina Annual Income y Spending Score. Observe que no hay una separación clara entre otros diagramas de dispersión de variables. A lo sumo, tal vez podamos decir que hay dos concentraciones distintas de puntos en el Spending Score vs Age gráfico de dispersión.

Ambos diagramas de dispersión consisten en Annual Income y Spending Score son esencialmente los mismos. Podemos verlo dos veces porque se intercambiaron los ejes x e y. Al echar un vistazo a cualquiera de ellos, podemos ver lo que parecen ser cinco grupos diferentes. Grafiquemos solo esas dos características con un Seaborn scatterplot() para echar un vistazo más de cerca:

sns.scatterplot(x=customer_data['Annual Income (k$)'],
                y=customer_data['Spending Score (1-100)'])

img

Al mirar más de cerca, definitivamente podemos distinguir 5 grupos diferentes de datos. Parece que nuestros clientes pueden agruparse en función de cuánto ganan en un año y cuánto gastan. Este es otro punto relevante en nuestro análisis. Es importante que solo estemos tomando en cuenta dos características para agrupar a nuestros clientes. Cualquier otra información que tengamos sobre ellos no entra en la ecuación. Esto le da sentido al análisis: si sabemos cuánto gana y gasta un cliente, podemos encontrar fácilmente las similitudes que necesitamos.

img

¡Eso es genial! Hasta ahora, ya tenemos dos variables para construir nuestro modelo. Además de lo que esto representa, también hace que el modelo sea más simple, parsimonioso y más explicable.

Consulte nuestra guía práctica y práctica para aprender Git, con las mejores prácticas, los estándares aceptados por la industria y la hoja de trucos incluida. Deja de buscar en Google los comandos de Git y, de hecho, aprenden ella!

Nota: La ciencia de datos generalmente favorece enfoques tan simples como sea posible. No solo porque es más fácil de explicar para el negocio, sino también porque es más directo: con 2 funciones y un modelo explicable, queda claro qué está haciendo el modelo y cómo funciona.

Trazado de datos después de usar PCA

Parece que nuestro segundo enfoque es probablemente el mejor, pero también echemos un vistazo a nuestro tercer enfoque. Puede ser útil cuando no podemos graficar los datos porque tienen demasiadas dimensiones, o cuando no hay concentraciones de datos o separación clara en grupos. Cuando ocurren esas situaciones, se recomienda intentar reducir las dimensiones de los datos con un método llamado Análisis de componentes principales (PCA).

Nota: La mayoría de las personas usan PCA para reducir la dimensionalidad antes de la visualización. Existen otros métodos que ayudan en la visualización de datos antes de la agrupación, como Clustering espacial basado en la densidad de aplicaciones con ruido (DBSCAN) y Mapas autoorganizados (SOM) agrupamiento Ambos son algoritmos de agrupamiento, pero también se pueden usar para la visualización de datos. Dado que el análisis de agrupamiento no tiene un estándar de oro, es importante comparar diferentes visualizaciones y diferentes algoritmos.

PCA reducirá las dimensiones de nuestros datos mientras intenta preservar la mayor cantidad de información posible. Primero, tengamos una idea de cómo funciona PCA, y luego podemos elegir a cuántas dimensiones de datos reduciremos nuestros datos.

Para cada par de características, PCA ve si los valores mayores de una variable se corresponden con los valores mayores de la otra variable, y hace lo mismo con los valores menores. Entonces, esencialmente calcula cuánto varían los valores de las características entre sí; lo llamamos su covarianza. Esos resultados luego se organizan en una matriz, obteniendo un Matriz de covarianza.

Después de obtener la matriz de covarianza, PCA intenta encontrar una combinación lineal de características que la explique mejor: ajusta los modelos lineales hasta que identifica el que explica la máximas cantidad de variación.

Note: PCA es una transformación lineal y la linealidad es sensible a la escala de los datos. Por lo tanto, PCA funciona mejor cuando todos los valores de los datos están en la misma escala. Esto se puede hacer restando la columna personalizado de sus valores y dividiendo el resultado por su desviación estándar. Eso es llamado estandarización de datos. ¡Antes de usar PCA, asegúrese de que los datos estén escalados! Si no está seguro de cómo hacerlo, lea nuestro “Características de escalado de datos con Scikit-Learn para aprendizaje automático en Python”!

Con la mejor línea (combinación lineal) encontrada, PCA obtiene las direcciones de sus ejes, llamadas vectores propios, y sus coeficientes lineales, el valores propios. La combinación de los vectores propios y los valores propios, o las direcciones de los ejes y los coeficientes, son los Componentes principales de PCA. Y ahí es cuando podemos elegir nuestro número de dimensiones en función de la varianza explicada de cada característica, entendiendo qué componentes principales queremos conservar o descartar en función de cuánta varianza explican.

Después de obtener los componentes principales, PCA usa los vectores propios para formar un vector de características que reorienta los datos de los ejes originales a los representados por los componentes principales; así es como se reducen las dimensiones de los datos.

Nota: Un detalle importante a tener en cuenta aquí es que, debido a su naturaleza lineal, PCA concentrará la mayor parte de la varianza explicada en los primeros componentes principales. Entonces, al observar la varianza explicada, por lo general nuestros primeros dos componentes serán suficientes. Pero eso puede ser engañoso en algunos casos, así que trate de seguir comparando diferentes gráficos y algoritmos al agrupar para ver si tienen resultados similares.

Antes de aplicar PCA, debemos elegir entre los Age columna o la Age Groups columnas en nuestros datos codificados previamente en caliente. Dado que ambas columnas representan la misma información, introducirla dos veces afecta la varianza de nuestros datos. Si el Age Groups se elige la columna, simplemente elimine la Age columna usando los pandas drop() método y reasignarlo al customer_data_oh variable:

customer_data_oh = customer_data_oh.drop(['Age'], axis=1)
customer_data_oh.shape 

Ahora nuestros datos tienen 10 columnas, lo que significa que podemos obtener un componente principal por columna y elegir cuántos de ellos usaremos midiendo cuánto la introducción de una nueva dimensión explica más la varianza de nuestros datos.

Hagámoslo con Scikit-Learn PCA. Calcularemos la varianza explicada de cada dimensión, dada por explained_variance_ratio_ , y luego mire su suma acumulada con cumsum() :

from sklearn.decomposition import PCA

pca = PCA(n_components=10)
pca.fit_transform(customer_data_oh)
pca.explained_variance_ratio_.cumsum()

Nuestras variaciones acumuladas explicadas son:

array([0.509337  , 0.99909504, 0.99946364, 0.99965506, 0.99977937,
       0.99986848, 0.99993716, 1.        , 1.        , 1.        ])

Podemos ver que la primera dimensión explica el 50% de los datos, y cuando se combinan con la segunda dimensión, explican el 99% por ciento. Esto significa que las 2 primeras dimensiones ya explican el 99% de nuestros datos. Entonces podemos aplicar un PCA con 2 componentes, obtener nuestros componentes principales y graficarlos:

from sklearn.decomposition import PCA

pca = PCA(n_components=2)
pcs = pca.fit_transform(customer_data_oh)

pc1_values = pcs[:,0]
pc2_values = pcs[:,1]
sns.scatterplot(x=pc1_values, y=pc2_values)

img

La gráfica de datos después de PCA es muy similar a la gráfica que usa solo dos columnas de datos sin PCA. Observe que los puntos que forman grupos están más cerca y un poco más concentrados después del PCA que antes.

img

Visualización de la estructura jerárquica con dendogramas

Hasta ahora, hemos explorado los datos, las columnas categóricas codificadas en caliente, decidido qué columnas eran aptas para el agrupamiento y reducido la dimensionalidad de los datos. Los gráficos indican que tenemos 5 conglomerados en nuestros datos, pero también hay otra forma de visualizar las relaciones entre nuestros puntos y ayudar a determinar la cantidad de conglomerados: creando un dendrograma (comúnmente mal escrito como dendograma). dendro significa árbol en latín.

El dendrograma es el resultado de la vinculación de puntos en un conjunto de datos. Es una representación visual del proceso de agrupación jerárquica. ¿Y cómo funciona el proceso de agrupamiento jerárquico? Bueno… depende, probablemente una respuesta que ya hayas escuchado mucho en Data Science.

Comprender la agrupación jerárquica

Cuando el Algoritmo de agrupamiento jerárquico (HCA) comienza a vincular los puntos y encontrar grupos, primero puede dividir los puntos en 2 grupos grandes y luego dividir cada uno de esos dos grupos en 2 grupos más pequeños, teniendo 4 grupos en total, que es el divisivo y de arriba hacia abajo enfoque.

Alternativamente, puede hacer lo contrario: puede mirar todos los puntos de datos, encontrar 2 puntos que estén más cerca entre sí, vincularlos y luego encontrar otros puntos que sean los más cercanos a esos puntos vinculados y seguir construyendo los 2 grupos. desde el de abajo hacia arriba. Cuál es el aglomerante enfoque que desarrollaremos.

Pasos para realizar el agrupamiento jerárquico aglomerativo

Para que el enfoque aglomerativo sea aún más claro, hay pasos del Agrupación jerárquica aglomerativa (AHC) algoritmo:

  1. Al principio, trate cada punto de datos como un grupo. Por lo tanto, la cantidad de grupos al principio será K, mientras que K es un número entero que representa la cantidad de puntos de datos.
  2. Forme un grupo uniendo los dos puntos de datos más cercanos que dan como resultado grupos K-1.
  3. Forme más grupos uniendo los dos grupos más cercanos que dan como resultado grupos K-2.
  4. Repita los tres pasos anteriores hasta que se forme un grupo grande.

Note: Para simplificar, estamos diciendo "dos puntos de datos más cercanos" en los pasos 2 y 3. Pero hay más formas de vincular puntos, como veremos en un momento.

Si invierte los pasos del algoritmo ACH, pasando de 4 a 1, esos serían los pasos a *Agrupación jerárquica divisiva (DHC)*.

Tenga en cuenta que las HCA pueden ser divisivas y de arriba hacia abajo, o aglomerativas y de abajo hacia arriba. El enfoque de DHC de arriba hacia abajo funciona mejor cuando tiene menos clústeres, pero más grandes, por lo tanto, es más costoso desde el punto de vista computacional. Por otro lado, el enfoque de AHC de abajo hacia arriba es adecuado cuando tiene muchos clústeres más pequeños. Es computacionalmente más simple, más utilizado y más disponible.

Nota: Ya sea de arriba hacia abajo o de abajo hacia arriba, la representación del dendrograma del proceso de agrupamiento siempre comenzará con una división en dos y terminará con cada punto individual discriminado, una vez que su estructura subyacente sea la de un árbol binario.

Tracemos nuestro dendrograma de datos de clientes para visualizar las relaciones jerárquicas de los datos. Esta vez usaremos el scipy biblioteca para crear el dendrograma para nuestro conjunto de datos:

import scipy.cluster.hierarchy as shc
import matplotlib.pyplot as plt

plt.figure(figsize=(10, 7))
plt.title("Customers Dendrogram")


selected_data = customer_data_oh.iloc[:, 1:3]
clusters = shc.linkage(selected_data, 
            method='ward', 
            metric="euclidean")
shc.dendrogram(Z=clusters)
plt.show()

La salida del script se ve así:

img

En el script anterior, generamos los grupos y subgrupos con nuestros puntos, definimos cómo se vincularían nuestros puntos (aplicando el ward método) y cómo medir la distancia entre puntos (usando el euclidean métrico).

Con el gráfico del dendrograma, se pueden visualizar los procesos descritos de DHC y AHC. Para visualizar el enfoque de arriba hacia abajo, comience desde la parte superior del dendrograma y baje, y haga lo contrario, comenzando hacia abajo y moviéndose hacia arriba para visualizar el enfoque de abajo hacia arriba.

Métodos de vinculación

Hay muchos otros métodos de vinculación, al comprender más sobre cómo funcionan, podrá elegir el adecuado para sus necesidades. Además de eso, cada uno de ellos dará resultados diferentes cuando se apliquen. No hay una regla fija en el análisis de conglomerados, si es posible, estudie la naturaleza del problema para ver cuál se adapta mejor, pruebe diferentes métodos e inspeccione los resultados.

Algunos de los métodos de vinculación son:

  • Enlace único: también conocido como Vecino más cercano (NN). La distancia entre clústeres se define por la distancia entre sus miembros más cercanos.

img

  • enlace completo: también conocido como Vecino más lejano (FN), Algoritmo del punto más lejanoo Algoritmo Voor Hees. La distancia entre grupos se define por la distancia entre sus miembros más lejanos. Este método es computacionalmente costoso.

img

  • Vinculación promedio: también conocido como UPGMA (Método de grupos de pares no ponderados con media aritmética). El porcentaje del número de puntos de cada clúster se calcula con respecto al número de puntos de los dos clústeres si estuvieran fusionados.

img

  • vinculación ponderada: también conocido como WPGMA (Método de grupos de pares ponderados con media aritmética). Los puntos individuales de los dos grupos contribuyen a la distancia agregada entre un grupo más pequeño y uno más grande.
  • Enlace centroide: también conocido como UPGMC (Método de grupo de pares no ponderados usando centroides). Se calcula un punto definido por la media de todos los puntos (centroide) para cada grupo y la distancia entre grupos es la distancia entre sus respectivos centroides.

img

  • enlace de barrio: También conocido como MISSQ (Incremento mínimo de suma de cuadrados). Especifica la distancia entre dos grupos, calcula el error de la suma de los cuadrados (ESS) y elige sucesivamente los siguientes grupos en función del ESS más pequeño. El método de Ward busca minimizar el aumento de ESS en cada paso. Por lo tanto, minimizar el error.

img

Métricas de distancia

Además de la vinculación, también podemos especificar algunas de las métricas de distancia más utilizadas:

  • Euclidiana: también conocido como Pitágoras o en línea recta distancia. Calcula la distancia entre dos puntos en el espacio, midiendo la longitud de un segmento de línea que pasa entre ellos. Utiliza el teorema de Pitágoras y el valor de la distancia es el resultado (C) de la ecuación:

$$
c ^ 2 = a ^ 2 + b ^ 2
$$

  • Manhattan: también llamado Manzana, Taxi distancia. Es la suma de las diferencias absolutas entre las medidas en todas las dimensiones de dos puntos. Si esas dimensiones son dos, es similar a girar a la derecha y luego a la izquierda al caminar una cuadra.

img

  • minkowski: es una generalización de las distancias Euclidiana y Manhattan. Es una forma de calcular distancias en base a las diferencias absolutas al orden de la métrica de Minkowski p. Aunque se define para cualquier p> 0, rara vez se usa para valores distintos de 1, 2 y ∞ (infinito). La distancia de Minkowski es la misma que la distancia de Manhattan cuando p = 1, y lo mismo que la distancia euclidiana cuando p = 2.

$$
Dizquierda(X,Yderecha) = izquierda(suma_{i=1}^n |x_i-y_i|^derecha)^{frac{1}{p}}
$$

img

  • Chebyshev: también conocido como Tablero de ajedrez distancia. Es el caso extremo de la distancia de Minkowski. Cuando usamos infinito como el valor del parámetro pag (pag = ∞), terminamos con una métrica que define la distancia como la máxima diferencia absoluta entre coordenadas.
  • coseno: es la distancia coseno angular entre dos sucesiones de puntos, o vectores. La similitud del coseno es el producto escalar de los vectores dividido por el producto de sus longitudes.
  • jaccard: mide la similitud entre conjuntos finitos de puntos. Se define como el número total de puntos (cardinalidad) en los puntos comunes de cada conjunto (intersección), dividido por el número total de puntos (cardinalidad) del total de puntos de ambos conjuntos (unión).
  • Jensen-Shannon: basado en la divergencia Kullback-Leibler. Considera las distribuciones de probabilidad de los puntos y mide la similitud entre esas distribuciones. Es un método popular de teoría de probabilidad y estadística.

Hemos elegido Sala y Euclidiana para el dendrograma porque son el método y la métrica más utilizados. Suelen dar buenos resultados ya que Ward enlaza puntos basados ​​en minimizar los errores, y Euclidean funciona bien en dimensiones más bajas.

En este ejemplo, estamos trabajando con dos características (columnas) de los datos de marketing y 200 observaciones o filas. Dado que el número de observaciones es mayor que el número de características (200 > 2), estamos trabajando en un espacio de baja dimensión.

Cuando el número de características (F) es mayor que el número de observaciones (N) – mayormente escrito como f >> norte, significa que tenemos un espacio de alta dimensión.

Si tuviéramos que incluir más atributos, por lo que tenemos más de 200 características, la distancia euclidiana podría no funcionar muy bien, ya que tendría dificultades para medir todas las distancias pequeñas en un espacio muy grande que solo se hace más grande. En otras palabras, el enfoque de la distancia euclidiana tiene dificultades para trabajar con los datos. escasez. Este es un tema que se llama la maldición de la dimensionalidad. Los valores de distancia se volverían tan pequeños, como si se "diluyeran" en el espacio más grande, distorsionados hasta convertirse en 0.

Nota: Si alguna vez encuentra un conjunto de datos con f >> pag, probablemente utilizará otras métricas de distancia, como la mahalanobis distancia. Alternativamente, también puede reducir las dimensiones del conjunto de datos, usando Análisis de componentes principales (PCA). Este problema es frecuente, especialmente cuando se agrupan datos de secuenciación biológica.

Ya hemos discutido las métricas, los vínculos y cómo cada uno de ellos puede afectar nuestros resultados. Ahora continuemos con el análisis del dendrograma y veamos cómo nos puede dar una indicación de la cantidad de grupos en nuestro conjunto de datos.

Encontrar un número interesante de conglomerados en un dendrograma es lo mismo que encontrar el espacio horizontal más grande que no tiene líneas verticales (el espacio con las líneas verticales más largas). Esto significa que hay más separación entre los grupos.

Podemos dibujar una línea horizontal que pase por esa distancia más larga:

plt.figure(figsize=(10, 7))
plt.title("Customers Dendogram with line")
clusters = shc.linkage(selected_data, 
            method='ward', 
            metric="euclidean")
shc.dendrogram(clusters)
plt.axhline(y = 125, color = 'r', linestyle = '-')

img

Después de ubicar la línea horizontal, contamos cuántas veces cruzó nuestras líneas verticales; en este ejemplo, 5 veces. Entonces, 5 parece una buena indicación de la cantidad de grupos que tienen la mayor distancia entre ellos.

Note: El dendrograma debe considerarse solo como una referencia cuando se utiliza para elegir el número de conglomerados. Puede alejarse fácilmente de ese número y está completamente influenciado por el tipo de vinculación y las métricas de distancia. Al realizar un análisis de conglomerados en profundidad, se recomienda observar los dendogramas con diferentes vínculos y métricas y observar los resultados generados con las tres primeras líneas en las que los conglomerados tienen la mayor distancia entre ellos.

Implementación de una agrupación jerárquica aglomerativa

Uso de datos originales

Hasta ahora, hemos calculado la cantidad sugerida de grupos para nuestro conjunto de datos que corrobora con nuestro análisis inicial y nuestro análisis PCA. Ahora podemos crear nuestro modelo de agrupamiento jerárquico aglomerativo usando Scikit-Learn AgglomerativeClustering y conoce las etiquetas de los puntos de comercialización con labels_:

from sklearn.cluster import AgglomerativeClustering

clustering_model = AgglomerativeClustering(n_clusters=5, affinity='euclidean', linkage='ward')
clustering_model.fit(selected_data)
clustering_model.labels_

Esto resulta en:

array([4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3,
       4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 1,
       4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 0, 2, 0, 2,
       1, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 2, 1, 2, 0, 2, 0, 2, 0, 2,
       0, 2, 0, 2, 0, 2, 1, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2,
       0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2,
       0, 2])

Hemos investigado mucho para llegar a este punto. ¿Y qué significan estas etiquetas? Aquí, tenemos cada punto de nuestros datos etiquetados como un grupo del 0 al 4:

data_labels = clustering_model.labels_
sns.scatterplot(x='Annual Income (k$)', 
                y='Spending Score (1-100)', 
                data=selected_data, 
                hue=data_labels,
                pallete="rainbow").set_title('Labeled Customer Data')

img

Estos son nuestros datos agrupados finales. Puede ver los puntos de datos codificados por colores en forma de cinco grupos.

Los puntos de datos en la parte inferior derecha (etiqueta: 0, puntos de datos morados) pertenecen a los clientes con salarios altos pero gastos bajos. Estos son los clientes que gastan su dinero con cuidado.

Del mismo modo, los clientes en la parte superior derecha (etiqueta: 2, puntos de datos verdes), son los clientes con salarios altos y gastos elevados. Estos son el tipo de clientes a los que se dirigen las empresas.

Los clientes en el medio (etiqueta: 1, puntos de datos azules) son los que tienen un ingreso promedio y un gasto promedio. El mayor número de clientes pertenecen a esta categoría. Las empresas también pueden dirigirse a estos clientes dado que se encuentran en grandes cantidades.

Los clientes en la parte inferior izquierda (etiqueta: 4, rojo) son los clientes que tienen salarios bajos y gastos bajos, podrían ser atraídos ofreciendo promociones.

Y finalmente, los clientes en la parte superior izquierda (etiqueta: 3, puntos de datos naranjas) son los que tienen ingresos altos y gastos bajos, que son los objetivos ideales del marketing.

Uso del resultado de PCA

Si estuviéramos en un escenario diferente, en el que tuviéramos que reducir la dimensionalidad de los datos. También podríamos trazar fácilmente los resultados de PCA agrupados. Eso se puede hacer creando otro modelo de agrupamiento aglomerativo y obteniendo una etiqueta de datos para cada componente principal:

clustering_model_pca = AgglomerativeClustering(n_clusters=5, affinity='euclidean', linkage='ward')
clustering_model_pca.fit(pcs)

data_labels_pca = clustering_model_pca.labels_

sns.scatterplot(x=pc1_values, 
                y=pc2_values,
                hue=data_labels_pca,
                palette="rainbow").set_title('Labeled Customer Data Reduced with PCA')

img

Observa que ambos resultados son muy similares. La principal diferencia es que el primer resultado con los datos originales es mucho más fácil de explicar. Es evidente que los clientes se pueden dividir en cinco grupos según su puntuación anual de ingresos y gastos. Si bien, en el enfoque de PCA, tomamos en consideración todas nuestras características, tanto como podemos observar la variación explicada por cada una de ellas, este es un concepto más difícil de comprender, especialmente cuando se informa a un departamento de marketing.

Cuanto menos tengamos que transformar nuestros datos, mejor.

Si tiene un conjunto de datos muy grande y complejo en el que debe realizar una reducción de la dimensionalidad antes del agrupamiento, intente analizar las relaciones lineales entre cada una de las características y sus residuos para respaldar el uso de PCA y mejorar la explicabilidad del proceso. Al hacer un modelo lineal por par de características, podrá comprender cómo interactúan las características.

Si el volumen de datos es tan grande, se vuelve imposible trazar los pares de características, seleccione una muestra de sus datos, lo más equilibrada y cercana posible a la distribución normal y realice el análisis en la muestra primero, entiéndala, ajuste y aplicarlo más tarde a todo el conjunto de datos.

Siempre puede elegir diferentes técnicas de visualización de agrupamiento según la naturaleza de sus datos (lineal, no lineal) y combinarlas o probarlas todas si es necesario.

Conclusión

La técnica de agrupamiento puede ser muy útil cuando se trata de datos sin etiquetar. Dado que la mayoría de los datos en el mundo real no están etiquetados y anotar los datos tiene costos más altos, se pueden usar técnicas de agrupación para etiquetar datos no etiquetados.

En esta guía, hemos planteado un problema real de ciencia de datos, ya que las técnicas de agrupación se utilizan en gran medida en el análisis de marketing (y también en el análisis biológico). También explicamos muchos de los pasos de investigación para llegar a un buen modelo de agrupamiento jerárquico y cómo leer dendrogramas y cuestionamos si PCA es un paso necesario. Nuestro principal objetivo es que se cubran algunos de los escollos y diferentes escenarios en los que nos podemos encontrar con la agrupación jerárquica.

¡Feliz agrupamiento!

Sello de tiempo:

Mas de Abuso de pila