¿Cómo usar las variables binarias y continuas juntas en la agrupación?

27

Necesito usar variables binarias (valores 0 y 1) en k-means. Pero k-means solo funciona con variables continuas. Sé que algunas personas todavía usan estas variables binarias en k-means ignorando el hecho de que k-means solo está diseñado para variables continuas. Esto es inaceptable para mí.

Preguntas:

  1. Entonces, ¿cuál es la forma estadística / matemáticamente correcta de usar variables binarias en k-means / cluster jerárquico?
  2. ¿Cómo implementar la solución en SAS / R?
GeorgeOfTheRF
fuente
1
Tengo curiosidad acerca de la fuente de su información que "K significa que solo está diseñada para variables continuas". ¿Serías capaz de citar una referencia?
whuber
2
jmp.com/support/help/K-Means_Clustering.shtml "La agrupación de K-medias solo admite columnas numéricas. La agrupación de K-medias ignora los tipos de modelos (nominales y ordinales) y trata todas las columnas numéricas como columnas continuas". Simplemente busqué en Google y obtuve esto. El punto es media se define para variables continuas, no para binario, por lo que k significa no puede usar variables binarias.
GeorgeOfTheRF
1
Puede usarlos, tratándolos como continuos; pero interpretar el resultado será difícil, porque los centros de clúster ya no tendrán un valor binario; y en mi humilde opinión, todo está claro si el resultado es demasiado significativo: ¿por qué tiene sentido minimizar la varianza de una variable binaria? En su lugar, considere, por ejemplo, la extracción de elementos freuqent en variables binarias si corresponden a presente / ausente para descubrir patrones en sus datos.
Anony-Mousse
¿Hay algo más que necesite, más allá de las respuestas a continuación? Esto ha existido durante mucho tiempo, y es altamente visto y votado, pero no está claro que su pregunta haya sido resuelta a su satisfacción, y tampoco hay indicios de lo que aún podría estar perdiendo.
gung - Restablece a Monica

Respuestas:

31

Tiene razón en que la agrupación de k-means no debe hacerse con datos de tipos mixtos. Dado que k-means es esencialmente un algoritmo de búsqueda simple para encontrar una partición que minimice las distancias euclidianas cuadradas dentro del clúster entre las observaciones agrupadas y el centroide del clúster, solo debe usarse con datos donde las distancias euclidianas cuadradas serían significativas.

yoyo

En este punto, puede usar cualquier método de agrupación que pueda operar sobre una matriz de distancia en lugar de necesitar la matriz de datos original. (Tenga en cuenta que k-means necesita lo último). Las opciones más populares son la partición alrededor de medoides (PAM, que es esencialmente lo mismo que k-means, pero utiliza la observación más central en lugar del centroide), varios enfoques de agrupamiento jerárquico (por ejemplo , mediana, enlace único y enlace completo; con la agrupación jerárquica necesitará decidir dónde ' cortar el árbol ' para obtener las asignaciones finales del grupo) y DBSCAN, que permite formas de grupo mucho más flexibles.

Aquí hay una Rdemostración simple (nb, en realidad hay 3 grupos, pero la mayoría de los datos parecen 2 grupos apropiados):

library(cluster)  # we'll use these packages
library(fpc)

  # here we're generating 45 data in 3 clusters:
set.seed(3296)    # this makes the example exactly reproducible
n      = 15
cont   = c(rnorm(n, mean=0, sd=1),
           rnorm(n, mean=1, sd=1),
           rnorm(n, mean=2, sd=1) )
bin    = c(rbinom(n, size=1, prob=.2),
           rbinom(n, size=1, prob=.5),
           rbinom(n, size=1, prob=.8) )
ord    = c(rbinom(n, size=5, prob=.2),
           rbinom(n, size=5, prob=.5),
           rbinom(n, size=5, prob=.8) )
data   = data.frame(cont=cont, bin=bin, ord=factor(ord, ordered=TRUE))
  # this returns the distance matrix with Gower's distance:  
g.dist = daisy(data, metric="gower", type=list(symm=2))

Podemos comenzar buscando en diferentes números de clústeres con PAM:

  # we can start by searching over different numbers of clusters with PAM:
pc = pamk(g.dist, krange=1:5, criterion="asw")
pc[2:3]
# $nc
# [1] 2                 # 2 clusters maximize the average silhouette width
# 
# $crit
# [1] 0.0000000 0.6227580 0.5593053 0.5011497 0.4294626
pc = pc$pamobject;  pc  # this is the optimal PAM clustering
# Medoids:
#      ID       
# [1,] "29" "29"
# [2,] "33" "33"
# Clustering vector:
#  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 
#  1  1  1  1  1  2  1  1  1  1  1  2  1  2  1  2  2  1  1  1  2  1  2  1  2  2 
# 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 
#  1  2  1  2  2  1  2  2  2  2  1  2  1  2  2  2  2  2  2 
# Objective function:
#     build      swap 
# 0.1500934 0.1461762 
# 
# Available components:
# [1] "medoids"    "id.med"     "clustering" "objective"  "isolation" 
# [6] "clusinfo"   "silinfo"    "diss"       "call" 

Esos resultados se pueden comparar con los resultados de la agrupación jerárquica:

hc.m = hclust(g.dist, method="median")
hc.s = hclust(g.dist, method="single")
hc.c = hclust(g.dist, method="complete")
windows(height=3.5, width=9)
  layout(matrix(1:3, nrow=1))
  plot(hc.m)
  plot(hc.s)
  plot(hc.c)

ingrese la descripción de la imagen aquí

El método mediano sugiere 2 (posiblemente 3) grupos, el único solo admite 2, pero el método completo podría sugerir 2, 3 o 4 a mi ojo.

Finalmente, podemos probar DBSCAN. Esto requiere especificar dos parámetros: eps, la 'distancia de alcance' (qué tan cerca deben estar vinculadas dos observaciones) y minPts (el número mínimo de puntos que deben conectarse entre sí antes de que esté dispuesto a llamarlos un 'racimo'). Una regla general para minPts es usar una más que el número de dimensiones (en nuestro caso 3 + 1 = 4), pero no se recomienda tener un número que sea demasiado pequeño. El valor predeterminado para dbscanes 5; nos quedaremos con eso. Una forma de pensar en la distancia de alcance es ver qué porcentaje de las distancias son menores que cualquier valor dado. Podemos hacerlo examinando la distribución de las distancias:

windows()
  layout(matrix(1:2, nrow=1))
  plot(density(na.omit(g.dist[upper.tri(g.dist)])), main="kernel density")
  plot(ecdf(g.dist[upper.tri(g.dist)]), main="ECDF")

ingrese la descripción de la imagen aquí

Las distancias mismas parecen agruparse en grupos visualmente discernibles de "más cerca" y "más lejos". Un valor de .3 parece distinguir más claramente entre los dos grupos de distancias. Para explorar la sensibilidad de la salida a diferentes opciones de eps, también podemos probar .2 y .4:

dbc3 = dbscan(g.dist, eps=.3, MinPts=5, method="dist");  dbc3
# dbscan Pts=45 MinPts=5 eps=0.3
#        1  2
# seed  22 23
# total 22 23
dbc2 = dbscan(g.dist, eps=.2, MinPts=5, method="dist");  dbc2
# dbscan Pts=45 MinPts=5 eps=0.2
#         1  2
# border  2  1
# seed   20 22
# total  22 23
dbc4 = dbscan(g.dist, eps=.4, MinPts=5, method="dist");  dbc4
# dbscan Pts=45 MinPts=5 eps=0.4
#        1
# seed  45
# total 45

El uso eps=.3proporciona una solución muy limpia, que (al menos cualitativamente) está de acuerdo con lo que vimos de otros métodos anteriores.

Dado que no hay un grupo 1 significativo , debemos tener cuidado de tratar de hacer coincidir qué observaciones se llaman 'grupo 1' de diferentes grupos. En cambio, podemos formar tablas y si la mayoría de las observaciones llamadas 'grupo 1' en un ajuste se llaman 'grupo 2' en otro, veríamos que los resultados siguen siendo sustancialmente similares. En nuestro caso, los diferentes agrupamientos son en su mayoría muy estables y colocan las mismas observaciones en los mismos grupos cada vez; solo el agrupamiento jerárquico de enlace completo difiere:

  # comparing the clusterings
table(cutree(hc.m, k=2), cutree(hc.s, k=2))
#    1  2
# 1 22  0
# 2  0 23
table(cutree(hc.m, k=2), pc$clustering)
#    1  2
# 1 22  0
# 2  0 23
table(pc$clustering, dbc3$cluster)
#    1  2
# 1 22  0
# 2  0 23
table(cutree(hc.m, k=2), cutree(hc.c, k=2))
#    1  2
# 1 14  8
# 2  7 16

Por supuesto, no hay garantía de que ningún análisis de clúster recupere los verdaderos clústeres latentes en sus datos. La ausencia de las verdaderas etiquetas de clúster (que estarían disponibles en, por ejemplo, una situación de regresión logística) significa que una enorme cantidad de información no está disponible. Incluso con conjuntos de datos muy grandes, los clústeres pueden no estar suficientemente bien separados para ser perfectamente recuperables. En nuestro caso, dado que conocemos la verdadera membresía del clúster, podemos comparar eso con la salida para ver qué tan bien funcionó. Como señalé anteriormente, en realidad hay 3 grupos latentes, pero los datos dan la apariencia de 2 grupos:

pc$clustering[1:15]    # these were actually cluster 1 in the data generating process
# 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 
# 1  1  1  1  1  2  1  1  1  1  1  2  1  2  1 
pc$clustering[16:30]   # these were actually cluster 2 in the data generating process
# 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 
#  2  2  1  1  1  2  1  2  1  2  2  1  2  1  2 
pc$clustering[31:45]   # these were actually cluster 3 in the data generating process
# 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 
#  2  1  2  2  2  2  1  2  1  2  2  2  2  2  2 
gung - Restablece a Monica
fuente
en el trazado de agrupamiento jerárquico que mencionas median method suggests 2 (possibly 3) clusters, the single only supports 2, but the complete method could suggest 2, 3 or 4... ¿cómo llegas a esto? usando una altura de 0.3?
lukeg
1
@lukeg, las alturas de las uniones en el dendrograma representan qué tan lejos tienes que ir para fusionar 2 grupos. Está buscando dónde las distancias se hacen más largas para continuar aglomerando. Puede ser útil leer los hilos que discuten esto aquí y / o aquí .
gung - Restablece a Monica
2

Mire este documento de Finch, http://www.jds-online.com/files/JDS-192.pdf . Describe por qué la aplicación de métodos continuos a datos binarios puede agrupar los datos de manera incorrecta y, lo que es más importante, cuáles son algunas opciones en funciones de distancia apropiadas. No responde cómo agrupar con k-means, sino cómo agrupar correctamente los datos binarios utilizando métricas no euclidianas y un método jerárquico como Ward.

Chris
fuente