Comment utiliser les variables binaires et continues ensemble dans le clustering?

27

J'ai besoin d'utiliser des variables binaires (valeurs 0 et 1) dans k-means. Mais k-means ne fonctionne qu'avec des variables continues. Je sais que certaines personnes utilisent encore ces variables binaires dans k-means en ignorant le fait que k-means n'est conçu que pour des variables continues. C'est inacceptable pour moi.

Des questions:

  1. Alors, quelle est la manière statistiquement / mathématiquement correcte d'utiliser des variables binaires dans le clustering k-means / hiérarchique?
  2. Comment implémenter la solution en SAS / R?
GeorgeOfTheRF
la source
1
Je suis curieux de connaître la source de vos informations selon laquelle "K signifie n'est conçu que pour des variables continues". Pourriez-vous citer une référence?
whuber
2
jmp.com/support/help/K-Means_Clustering.shtml "Le clustering K-Means ne prend en charge que les colonnes numériques. Le clustering K-Means ignore les types de modèle (nominaux et ordinaux) et traite toutes les colonnes numériques comme des colonnes continues." Je viens de googler et j'ai obtenu ceci. Le point est la moyenne est défini pour les variables continues et non pour les binaires, donc k signifie ne peut pas utiliser de variables binaires.
GeorgeOfTheRF
1
Il peut les utiliser en les traitant comme continus; mais l'interprétation du résultat sera difficile, car les centres de cluster n'auront plus de valeur binaire; et à mon humble avis, le résultat est trop clair - pourquoi minimiser la variance d'une variable binaire est-il logique? Au lieu de cela, considérez par exemple l'extraction de jeux d'éléments freuqents sur des variables binaires si elles correspondent au présent / absent pour découvrir des modèles dans vos données.
Anony-Mousse
Y a-t-il quelque chose de plus dont vous avez besoin, au-delà des réponses ci-dessous? Cela existe depuis longtemps et est très apprécié et surévalué, mais il n'est pas clair que votre question a été résolue à votre satisfaction, et il n'y a également aucune indication de ce que vous pourriez encore manquer.
gung - Réintégrer Monica

Réponses:

31

Vous avez raison de dire que le clustering k-means ne doit pas être effectué avec des données de types mixtes. Étant donné que k-means est essentiellement un algorithme de recherche simple pour trouver une partition qui minimise les distances euclidiennes au sein d'un cluster entre les observations groupées et le centroïde du cluster, il ne doit être utilisé qu'avec des données où les distances euclidiennes au carré seraient significatives.

Lorsque vos données sont constituées de variables de types mixtes, vous devez utiliser la distance de Gower. Utilisateur CV @ttnphns a un bon aperçu de la distance de Gower ici . Essentiellement, vous calculez tour à tour une matrice de distance pour vos lignes pour chaque variable, en utilisant un type de distance qui convient à ce type de variable (par exemple, Euclidien pour les données continues, etc.); la distance finale de la ligne à est la moyenne (éventuellement pondérée) des distances pour chaque variable. Une chose à savoir est que la distance de Gower n'est pas réellement une métrique . Néanmoins, avec des données mitigées, la distance de Gower est largement le seul jeu en ville. i jeje

À ce stade, vous pouvez utiliser n'importe quelle méthode de clustering qui peut fonctionner sur une matrice de distance au lieu d'avoir besoin de la matrice de données d'origine. (Notez que k-means a besoin de ce dernier.) Les choix les plus populaires sont le partitionnement autour des médoïdes (PAM, qui est essentiellement le même que k-means, mais utilise l'observation la plus centrale plutôt que le centroïde), diverses approches de regroupement hiérarchique (par exemple , médiane, liaison simple et liaison complète; avec le clustering hiérarchique, vous devrez décider où `` couper l'arborescence '' pour obtenir les affectations finales du cluster), et DBSCAN qui permet des formes de cluster beaucoup plus flexibles.

Voici une Rdémo simple (nb, il y a en fait 3 clusters, mais les données ressemblent surtout à 2 clusters appropriés):

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))

Nous pouvons commencer par rechercher sur différents nombres de clusters avec 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" 

Ces résultats peuvent être comparés aux résultats du clustering hiérarchique:

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)

entrez la description de l'image ici

La méthode médiane suggère 2 (peut-être 3) grappes, le single ne supporte que 2, mais la méthode complète pourrait suggérer 2, 3 ou 4 à mon œil.

Enfin, nous pouvons essayer DBSCAN. Cela nécessite de spécifier deux paramètres: eps, la `` distance d'accessibilité '' (à quelle distance deux observations doivent être reliées ensemble) et minPts (le nombre minimum de points qui doivent être connectés les uns aux autres avant de vouloir les appeler un 'grappe'). Une règle de base pour minPts est d'utiliser une de plus que le nombre de dimensions (dans notre cas 3 + 1 = 4), mais avoir un nombre trop petit n'est pas recommandé. La valeur par défaut pour dbscanest 5; nous nous en tiendrons à cela. Une façon de penser à la distance d'accessibilité est de voir quel pourcentage des distances est inférieur à une valeur donnée. Nous pouvons le faire en examinant la distribution des distances:

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")

entrez la description de l'image ici

Les distances elles-mêmes semblent se regrouper en groupes visuellement perceptibles de «plus près» et «plus loin». Une valeur de 0,3 semble faire la distinction la plus nette entre les deux groupes de distances. Pour explorer la sensibilité de la sortie à différents choix d'eps, nous pouvons également essayer .2 et .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

L'utilisation eps=.3donne une solution très propre, qui (au moins qualitativement) est en accord avec ce que nous avons vu des autres méthodes ci-dessus.

Puisqu'il n'y a pas de cluster 1 significatif , nous devons faire attention d'essayer de faire correspondre les observations qui sont appelées `` cluster 1 '' à partir de différents clusters. Au lieu de cela, nous pouvons former des tableaux et si la plupart des observations appelées «cluster 1» dans un ajustement sont appelées «cluster 2» dans un autre, nous verrions que les résultats sont toujours substantiellement similaires. Dans notre cas, les différents clusters sont pour la plupart très stables et mettent à chaque fois les mêmes observations dans les mêmes clusters; seul le clustering hiérarchique de liaison complet diffère:

  # 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

Bien sûr, rien ne garantit qu'une analyse de cluster récupérera les véritables clusters latents dans vos données. L'absence des véritables étiquettes de cluster (qui seraient disponibles, par exemple, dans une situation de régression logistique) signifie qu'une énorme quantité d'informations n'est pas disponible. Même avec de très grands ensembles de données, les clusters peuvent ne pas être suffisamment bien séparés pour être parfaitement récupérables. Dans notre cas, puisque nous connaissons la véritable appartenance à un cluster, nous pouvons comparer cela à la sortie pour voir dans quelle mesure cela a fonctionné. Comme je l'ai noté ci-dessus, il y a en fait 3 clusters latents, mais les données donnent plutôt l'apparence de 2 clusters:

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 - Réintégrer Monica
la source
lors du regroupement hiérarchique, vous traitez de mentionner median method suggests 2 (possibly 3) clusters, the single only supports 2, but the complete method could suggest 2, 3 or 4.. comment arrivez-vous à cela? en utilisant une hauteur de 0,3?
lukeg
1
@lukeg, les hauteurs des jointures sur le dendrogramme représentent jusqu'où vous devez aller pour fusionner 2 clusters. Vous cherchez où les distances vont plus loin pour continuer à s'agglomérer. Il pourrait être utile de lire les discussions qui en discutent ici et / ou ici .
gung - Rétablir Monica
2

Regardez cet article de Finch, http://www.jds-online.com/files/JDS-192.pdf . Il décrit à la fois pourquoi l'application de méthodes continues aux données binaires peut regrouper les données de manière inexacte et, plus important encore, quels sont certains choix dans les fonctions de distance appropriées. Il ne explique pas comment regrouper avec k-means, mais plutôt comment regrouper correctement les données binaires en utilisant des métriques non euclidiennes et une méthode hiérarchique comme Ward.

Chris
la source