Análisis de clústeres de K-means

La agrupación es un amplio conjunto de técnicas para encontrar subgrupos de observaciones dentro de un conjunto de datos. Cuando agrupamos observaciones, queremos que las observaciones en el mismo grupo sean similares y que las observaciones en diferentes grupos sean diferentes. Debido a que no hay una variable de respuesta, este es un método no supervisado, lo que implica que busca encontrar relaciones entre el n observaciones sin ser entrenado por una variable de respuesta. La agrupación nos permite identificar qué observaciones son similares y, potencialmente, categorizarlas en ellas. K-means clustering es el método de clustering más simple y más utilizado para dividir un dataset en un conjunto de k grupos.

  1. Requerimientos de Replicaión Para replicar el análisis se deben cargar los siguientes paquetes.
library(tidyverse) #Datos 
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
## ✔ ggplot2 3.3.6     ✔ purrr   0.3.4
## ✔ tibble  3.1.7     ✔ dplyr   1.0.9
## ✔ tidyr   1.2.0     ✔ stringr 1.4.0
## ✔ readr   2.1.2     ✔ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
library (cluster)  #Algoritmo clustering
library(factoextra) #visualización
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
  1. Preparación de datos Para realizar un análisis de clúster en R, generalmente, los datos deben prepararse de la siguiente manera:

  2. Las filas son observaciones (individuos) y las columnas son variables

  3. Cualquier valor que falte en los datos debe eliminarse o estimarse.

  4. Los datos deben estandarizarse (es decir, escalarse) para que las variables sean comparables. Recordemos que, la estandarización consiste en transformar las variables de tal manera que tengan media cero y desviación estándar uno.

Aquí, usaremos el conjunto de datos R incorporado, que contiene estadísticas de arrestos por cada 100,000 residentes por asalto, asesinato y violación en cada uno de los 50 estados de los Estados Unidos en 1973. Incluye también el porcentaje de la población que vive en áreas urbanas. USArrests.

df <- USArrests

Como no queremos que el algoritmo de clustering dependa de una unidad variable arbitraria, comenzamos escalando/estandarizando los datos usando la función R: scale.

df <- scale(df)
head(df)
##                Murder   Assault   UrbanPop         Rape
## Alabama    1.24256408 0.7828393 -0.5209066 -0.003416473
## Alaska     0.50786248 1.1068225 -1.2117642  2.484202941
## Arizona    0.07163341 1.4788032  0.9989801  1.042878388
## Arkansas   0.23234938 0.2308680 -1.0735927 -0.184916602
## California 0.27826823 1.2628144  1.7589234  2.067820292
## Colorado   0.02571456 0.3988593  0.8608085  1.864967207
  1. Medidas de distancia de agrupamiento

La clasificación de las observaciones en grupos requiere algunos métodos para calcular la distancia o la (des)similitud entre cada par de observaciones. El resultado de este cálculo se conoce como una matriz de disimilitud o distancia. Existen muchos métodos para calcular esta información de distancia; la elección de las medidas de distancia es un paso crítico en la agrupación. Define cómo se calcula la similitud de dos elementos (x, y) e influirá en la forma de los cúmulos.

La elección de las medidas de distancia es un paso crítico en la agrupación. Define cómo se calcula la similitud de dos elementos (x, y) e influirá en la forma de los cúmulos. Los métodos clásicos para las medidas de distancia son las distancias euclidianas y de Manhattan, que se definen de la siguiente manera:

Distancia euclidiana: \[d_{euc}(x,y) = \sqrt{\sum^n_{i=1}(x_i - y_i)^2} \tag{1}\]

Ditancia de Manhattan: \[ d_{man}(x,y) = \sum^n_{i=1}|(x_i - y_i)| \tag{2}\] Donde, x e y son dos vectores de longitud n.

Existen otras medidas de disimilitud, como las distancias basadas en la correlación, que se utilizan ampliamente para los análisis de datos de expresión génica. La distancia basada en la correlación se define restando el coeficiente de correlación de 1. Se pueden utilizar diferentes tipos de métodos de correlación, tales como:

Distancia de correlación de Pearson: \[d_{cor}(x, y) = 1 - \frac{\sum^n_{i=1}(x_i-\bar x)(y_i - \bar y)}{\sqrt{\sum^n_{i=1}(x_i-\bar x)^2\sum^n_{i=1}(y_i - \bar y)^2}} \tag{3}\] Distancia de correlación de Spearman:

El método de correlación spearman calcula la correlación entre el rango de x y el rango de las variables y. \[ d_{spear}(x, y) = 1 - \frac{\sum^n_{i=1}(x^\prime_i-\bar x^\prime)(y^\prime_i - \bar y^\prime)}{\sqrt{\sum^n_{i=1}(x^\prime_i-\bar x^\prime)^2\sum^n_{i=1}(y^\prime_i - \bar y^\prime)^2}} \tag{4} \] \[Donde x^\prime_Yo = rannk(x_Yo), y^\prime_Yo = rannk(y_Yo) \] Distancia de correlación de Kendall:

El método de correlación de Kendall mide la correspondencia entre la clasificación de las variables x e y. El número total de posibles emparejamientos de x con y observaciones es n(n − 1)/2, donde n es el tamaño de x e y. Comience ordenando los pares por los valores x. Si x e y están correlacionados, entonces tendrían los mismos órdenes de rango relativo. Ahora, para cada uno yYo contar el número de yj menor que Yo (pares concordantes (c)) y el número de yj mayor a Yo (pares discordantes (d)).

La distancia de correlación de Kendall se define de la siguiente manera:

\[d_{kend}(x,y) = 1 - \frac{n_c - n_d}{\frac{1}{2}n(n - 1)} \tag{5}\] La elección de las medidas de distancia es muy importante, ya que tiene una fuerte influencia en los resultados de agrupación. Para el software de agrupación en clústeres más común, la medida de distancia predeterminada es la distancia euclidiana. Sin embargo, dependiendo del tipo de datos y las preguntas de investigación, se pueden preferir otras medidas de disimilitud y debe conocer las opciones.

Dentro de R es sencillo calcular y visualizar la matriz de distancias utilizando las funciones y desde el paquete R. Esto comienza a ilustrar qué estados tienen grandes diferencias (rojo) frente a aquellos que parecen ser bastante similares (verde azulado). get_distfviz_distfactoextra. Donde tenemos que:

  1. Para calcular una matriz de distancia entre las filas de una matriz de datos. La distancia por defecto calculada es la euclidiana; sin embargo, también soporta distancias descritas en las ecuaciones 2-5 anteriores más otras. get_dist
  2. para visualizar una matriz de distancias. fviz_dist
distance <- get_dist(df)
fviz_dist(distance, gradient = list(low = "#00AFBB", mid = "white", high = "#FC4E07"))

Agrupación de K-Means K-means clustering es el algoritmo de aprendizaje automático no supervisado más comúnmente utilizado para particionar un conjunto de datos dado en un conjunto de k grupos (es decir, k clusters), donde k representa el número de grupos preespecificados por el analista. Clasifica los objetos en múltiples grupos (es decir, clústeres), de modo que los objetos dentro del mismo clúster son lo más similares posible (es decir, alta similitud intraclase), mientras que los objetos de diferentes grupos son lo más diferentes posible (es decir, baja similitud entre clases). En la agrupación de k-medias, cada clúster está representado por su centro (es decir, centroide) que corresponde a la media de puntos asignados al clúster.

La idea básica La idea básica detrás de la agrupación de k-medias consiste en definir clústeres para que la variación total dentro del clúster (conocida como variación total dentro del clúster) se minimice. Hay varios algoritmos de k-medias disponibles. El algoritmo estándar es el algoritmo de Hartigan-Wong (1979), que define la variación total dentro del clúster como la suma de distancias al cuadrado distancias euclidianas entre los elementos y el centroide correspondiente:

\[W(C_k) = \sum_{x_Yo \in C_k}(x_Yo - \mu_k)^2 \tag{6}\] Dónde: 1. x_Yo es un punto de datos que pertenece al clúster C_k 2. mu:k es el valor medio de los puntos asignados al clúster Ck

Definimos la varianzción total dentro del cluster de la siguiente manera:

\[tot.withiness = \sum^k_{k=1}W(C_k) = \sum^k_{k=1}\sum_{x_i \in C_k}(x_i - \mu_k)^2 \tag{7}\]

La suma total dentro del cuadrado dentro del clúster mide la compacidad (es decir, la bondad) de la agrupación y queremos que sea lo más pequeña posible.

Algoritmo K-means El primer paso cuando se utiliza la agrupación en clústeres de k-medias es indicar el número de clústeres (k) que se generarán en la solución final. El algoritmo comienza seleccionando aleatoriamente k objetos del conjunto de datos para que sirvan como centros iniciales para los clústeres. Los objetos seleccionados también se conocen como medios de clúster o centroides. A continuación, cada uno de los objetos restantes se asigna a su centroide más cercano, donde el más cercano se define utilizando la distancia euclidiana (1) entre el objeto y la media del clúster. Este paso se denomina “paso de asignación de clúster”. Después del paso de asignación, el algoritmo calcula el nuevo valor medio de cada clúster. El término clúster “actualización de centroide” se utiliza para diseñar este paso. Ahora que los centros han sido recalculados, cada observación se revisa nuevamente para ver si podría estar más cerca de un grupo diferente. Todos los objetos se reasignan de nuevo utilizando los medios de clúster actualizados. Los pasos de asignación de clúster y actualización del centroide se repiten iterativamente hasta que las asignaciones de clúster dejan de cambiar (es decir, hasta que se logra la convergencia). Es decir, los clusters formados en la iteración actual son los mismos que los obtenidos en la iteración anterior.

El algoritmo K-means se puede resumir de la siguiente manera:

  1. Especifique el número de clústeres (K) que se crearán (por el analista)

  2. Seleccionar aleatoriamente k objetos del conjunto de datos como centros o medios de clúster iniciales

  3. Asigna cada observación a su centroide más cercano, basado en la distancia euclidiana entre el objeto y el centroide

  4. Para cada uno de los k clústeres, actualice el centroide del clúster calculando los nuevos valores medios de todos los puntos de datos del clúster. El centroide de un cúmulo Kth es un vector de longitud p que contiene las medias de todas las variables para las observaciones en el cúmulo kth; p es el número de variables.

  5. Minimizar iterativamente el total dentro de la suma del cuadrado (7). Es decir, repita los pasos 3 y 4 hasta que las asignaciones de clúster dejen de cambiar o se alcance el número máximo de iteraciones. De forma predeterminada, el software R utiliza 10 como valor predeterminado para el número máximo de iteraciones.

Computación k-significa clustering en R

Podemos calcular k-medias en R con la función. Aquí se agruparán los datos en dos clústeres (). La función también tiene una opción que intenta múltiples configuraciones iniciales e informa sobre la mejor. Por ejemplo, agregar generará 25 configuraciones iniciales. Este enfoque a menudo se recomienda.

k2 <- kmeans(df, centers = 2, nstart = 25) 
str(k2)
## List of 9
##  $ cluster     : Named int [1:50] 1 1 1 2 1 1 2 2 1 1 ...
##   ..- attr(*, "names")= chr [1:50] "Alabama" "Alaska" "Arizona" "Arkansas" ...
##  $ centers     : num [1:2, 1:4] 1.005 -0.67 1.014 -0.676 0.198 ...
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:2] "1" "2"
##   .. ..$ : chr [1:4] "Murder" "Assault" "UrbanPop" "Rape"
##  $ totss       : num 196
##  $ withinss    : num [1:2] 46.7 56.1
##  $ tot.withinss: num 103
##  $ betweenss   : num 93.1
##  $ size        : int [1:2] 20 30
##  $ iter        : int 1
##  $ ifault      : int 0
##  - attr(*, "class")= chr "kmeans"

La salida de es una lista con varios bits de información. El más importante es: kmeans.

  1. cluster: Vector de enteros (de 1:k) que indica el clúster al que se asigna cada punto.

  2. centers: Una matriz de centros de clúster.

  3. totss: La suma total de cuadrados.

  4. withinss: Vector de suma de cuadrados dentro del clúster, un componente por clúster.

  5. tot.withinss: Suma total de cuadrados dentro del clúster.

  6. betweenss: La suma entre grupos de cuadrados, es decir, “\(totss-tot.withinss\)”.

  7. size: El número de puntos de cada clúster.

Si imprimimos los resultados veremos que nuestras agrupaciones dieron como resultado 2 tamaños de clúster de 30 y 20. Vemos los centros de clúster (medias) para los dos grupos en las cuatro variables (Asesinato, Asalto, UrbanPop, Violación). También obtenemos la asignación de clúster para cada observación (es decir, Alabama se asignó al grupo 2, Arkansas se asignó al grupo 1, etc.).

fviz_cluster(k2, data = df)

Debido a que el número de clústeres (k) debe establecerse antes de iniciar el algoritmo, a menudo es ventajoso usar varios valores diferentes de k y examinar las diferencias en los resultados. Podemos ejecutar el mismo proceso para 3, 4 y 5 clústeres, y los resultados se muestran en la figura:

k3 <- kmeans(df, centers = 3, nstart = 25)
k4 <- kmeans(df, centers = 4, nstart = 25)
k5 <- kmeans(df, centers = 5, nstart = 25)
#Comparando:

p1 <- fviz_cluster(k2, geom = "point", data = df) + ggtitle("k = 2")
p2 <- fviz_cluster(k3, geom = "point",  data = df) + ggtitle("k = 3")
p3 <- fviz_cluster(k4, geom = "point",  data = df) + ggtitle("k = 4")
p4 <- fviz_cluster(k5, geom = "point",  data = df) + ggtitle("k = 5")

library(gridExtra)
## 
## Attaching package: 'gridExtra'
## The following object is masked from 'package:dplyr':
## 
##     combine
grid.arrange(p1, p2, p3, p4, nrow = 2)

Determinación de clústeres óptimos:

Método del codo Recordemos que, la idea básica detrás de los métodos de partición de clústeres, como la agrupación en clústeres k-means, es definir clústeres de tal manera que la variación total dentro del clúster (conocida como variación total dentro del clúster o suma total de cuadrados dentro del clúster) se minimice:

\[minimize\Bigg(\sum^k_{k=1}W(C_k)\Bigg) \tag{8}\] Dónde C_k es el K^th cluster y W (C_k) es la variación dentro del clúster. La suma total dentro del clúster de cuadrados (wss) mide la compacidad del agrupamiento y queremos que sea lo más pequeño posible. Por lo tanto, podemos usar el siguiente algoritmo para definir los clústeres óptimos:

  1. Algoritmo de agrupación en clústeres de cómputo (por ejemplo, agrupación de k-medias) para diferentes valores de k. Por ejemplo, variando k de 1 a 10 clústeres
  2. Para cada k, calcule la suma total dentro del clúster de cuadrado (wss)
  3. Trazar la curva de wss según el número de clusters k.
  4. La ubicación de una curva (rodilla) en la parcela generalmente se considera como un indicador del número apropiado de grupos.

Podemos implementar esto en R con el siguiente código. Los resultados sugieren que 4 es el número óptimo de grupos, ya que parece ser la curva en la rodilla (o codo):

set.seed(123)

#Calculamos la suma total de los cuadrados dentro del clúster:
wss <- function(k) {
  kmeans(df, k, nstart = 10 )$tot.withinss
}
k.values <- 1:15 # Calcular y trazar wss para k = 1 a k = 15

wss_values <- map_dbl(k.values, wss) #Extraemos WSS para 2-15 clusteres:

plot(k.values, wss_values,
       type="b", pch = 19, frame = FALSE, 
       xlab="Numero de cluster K",
       ylab="Suma total de cuadrados")

Método de silueta promedio En resumen, el enfoque de silueta promedio mide la calidad de un clustering. Es decir, determina qué tan bien se encuentra cada objeto dentro de su clúster. Un ancho de silueta promedio alto indica una buena agrupación. El método de silueta promedio calcula la silueta promedio de las observaciones para diferentes valores de k. El número óptimo de cúmulos k es el que maximiza la silueta media en un rango de valores posibles para k.

Podemos usar la función en el paquete de clúster para componer el ancho promedio de la silueta. El código siguiente calcula este enfoque para 1-15 clústeres. Los resultados muestran que 2 clústeres maximizan los valores de silueta promedio con 4 clústeres que entran como segundo número óptimo de clústeres. silhouette

avg_sil <- function(k) {
  km.res <- kmeans(df, centers = k, nstart = 25)
  ss <- silhouette(km.res$cluster, dist(df))
  mean(ss[, 3])
}
k.values <- 2:15
avg_sil_values <- map_dbl(k.values, avg_sil)
plot(k.values, avg_sil_values,
       type = "b", pch = 19, frame = FALSE, 
       xlab = "Number of clusters K",
       ylab = "Average Silhouettes")

Extracción de resultados Con la mayoría de estos enfoques sugiriendo 4 como el número de grupos óptimos, podemos realizar el análisis final y extraer los resultados utilizando 4 grupos.

set.seed(123)
final <- kmeans(df, 4, nstart = 25)
print(final)
## K-means clustering with 4 clusters of sizes 8, 13, 16, 13
## 
## Cluster means:
##       Murder    Assault   UrbanPop        Rape
## 1  1.4118898  0.8743346 -0.8145211  0.01927104
## 2 -0.9615407 -1.1066010 -0.9301069 -0.96676331
## 3 -0.4894375 -0.3826001  0.5758298 -0.26165379
## 4  0.6950701  1.0394414  0.7226370  1.27693964
## 
## Clustering vector:
##        Alabama         Alaska        Arizona       Arkansas     California 
##              1              4              4              1              4 
##       Colorado    Connecticut       Delaware        Florida        Georgia 
##              4              3              3              4              1 
##         Hawaii          Idaho       Illinois        Indiana           Iowa 
##              3              2              4              3              2 
##         Kansas       Kentucky      Louisiana          Maine       Maryland 
##              3              2              1              2              4 
##  Massachusetts       Michigan      Minnesota    Mississippi       Missouri 
##              3              4              2              1              4 
##        Montana       Nebraska         Nevada  New Hampshire     New Jersey 
##              2              2              4              2              3 
##     New Mexico       New York North Carolina   North Dakota           Ohio 
##              4              4              1              2              3 
##       Oklahoma         Oregon   Pennsylvania   Rhode Island South Carolina 
##              3              3              3              3              1 
##   South Dakota      Tennessee          Texas           Utah        Vermont 
##              2              1              4              3              2 
##       Virginia     Washington  West Virginia      Wisconsin        Wyoming 
##              3              3              2              2              3 
## 
## Within cluster sum of squares by cluster:
## [1]  8.316061 11.952463 16.212213 19.922437
##  (between_SS / total_SS =  71.2 %)
## 
## Available components:
## 
## [1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
## [6] "betweenss"    "size"         "iter"         "ifault"

Y podemos extraer los clústeres y agregar a nuestros datos iniciales para hacer algunas estadísticas descriptivas a nivel de clúster:

USArrests %>%
  mutate(Cluster = final$cluster) %>%
  group_by(Cluster) %>%
  summarise_all("mean")
## # A tibble: 4 × 5
##   Cluster Murder Assault UrbanPop  Rape
##     <int>  <dbl>   <dbl>    <dbl> <dbl>
## 1       1  13.9    244.      53.8  21.4
## 2       2   3.6     78.5     52.1  12.2
## 3       3   5.66   139.      73.9  18.8
## 4       4  10.8    257.      76    33.2
fviz_cluster(final, data = df)

Gracias