Regroupement de données de dénombrement très biaisées: des suggestions à faire (transformer, etc.)?

11

Problème de base

Voici mon problème de base: j'essaie de regrouper un ensemble de données contenant des variables très asymétriques avec des nombres. Les variables contiennent de nombreux zéros et ne sont donc pas très informatives pour ma procédure de clustering - qui est probablement l'algorithme k-means.

Très bien, dites-vous, transformez simplement les variables en utilisant la racine carrée, le cox carré ou le logarithme. Mais comme mes variables sont basées sur des variables catégorielles, je crains de pouvoir introduire un biais en manipulant une variable (basée sur une valeur de la variable catégorielle), tout en laissant les autres (basées sur d'autres valeurs de la variable catégorielle) telles qu'elles sont .

Allons plus en détail.

L'ensemble de données

Mon jeu de données représente les achats d'articles. Les articles ont différentes catégories, par exemple la couleur: bleu, rouge et vert. Les achats sont ensuite regroupés, par exemple par les clients. Chacun de ces clients est représenté par une ligne de mon ensemble de données, donc je dois en quelque sorte agréger les achats sur les clients.

Pour ce faire, je compte le nombre d'achats, où l'article est d'une certaine couleur. Ainsi , au lieu d'une seule variable color, je me retrouve avec trois variables count_red, count_blueet count_green.

Voici un exemple d'illustration:

-----------------------------------------------------------
customer | count_red  |    count_blue   | count_green     |
-----------------------------------------------------------
c0       |    12      |        5        |       0         |
-----------------------------------------------------------
c1       |     3      |        4        |       0         |
-----------------------------------------------------------
c2       |     2      |       21        |       0         |
-----------------------------------------------------------
c3       |     4      |        8        |       1         |
-----------------------------------------------------------

En fait, je n'utilise pas de comptes absolus au final, j'utilise des ratios (fraction des articles verts de tous les articles achetés par client).

-----------------------------------------------------------
customer | count_red  |    count_blue   | count_green     |
-----------------------------------------------------------
c0       |    0.71    |        0.29     |       0.00      |
-----------------------------------------------------------
c1       |    0.43    |        0.57     |       0.00      |
-----------------------------------------------------------
c2       |    0.09    |        0.91     |       0.00      |
-----------------------------------------------------------
c3       |    0.31    |        0.62     |       0.08      |
-----------------------------------------------------------

Le résultat est le même: pour une de mes couleurs, par exemple le vert (personne n'aime le vert), j'obtiens une variable de gauche contenant de nombreux zéros. Par conséquent, k-means ne parvient pas à trouver un bon partitionnement pour cette variable.

D'un autre côté, si je standardise mes variables (soustraire la moyenne, diviser par l'écart-type), la variable verte "explose" en raison de sa petite variance et prend des valeurs dans une plage beaucoup plus grande que les autres variables, ce qui la fait paraître plus important pour k-means qu'il ne l'est réellement.

L'idée suivante est de transformer la variable verte sk (r) ewed.

Transformer la variable asymétrique

Si je transforme la variable verte en appliquant la racine carrée, elle semble un peu moins asymétrique. (Ici, la variable verte est tracée en rouge et vert pour éviter toute confusion.)

entrez la description de l'image ici

Rouge: variable d'origine; bleu: transformé par racine carrée.

Disons que je suis satisfait du résultat de cette transformation (ce que je ne suis pas, car les zéros faussent encore fortement la distribution). Dois-je maintenant aussi mettre à l'échelle les variables rouges et bleues, bien que leurs distributions semblent bonnes?

Conclusion

En d'autres termes, est-ce que je déforme les résultats du clustering en gérant la couleur verte dans un sens, mais pas du tout le rouge et le bleu? En fin de compte, les trois variables appartiennent ensemble, alors ne devraient-elles pas être gérées de la même manière?

ÉDITER

Pour clarifier: je suis conscient que k-means n'est probablement pas la voie à suivre pour les données basées sur le nombre. Ma question est cependant vraiment sur le traitement des variables dépendantes. Le choix de la bonne méthode est une question distincte.

La contrainte inhérente à mes variables est que

count_red(i) + count_blue(i) + count_green(i) = n(i), où n(i)est le nombre total d'achats du client i.

(Ou, de manière équivalente, count_red(i) + count_blue(i) + count_green(i) = 1lors de l'utilisation de nombres relatifs.)

Si je transforme mes variables différemment, cela correspond à donner des poids différents aux trois termes de la contrainte. Si mon objectif est de séparer de manière optimale des groupes de clients, dois-je me soucier de ne pas respecter cette contrainte? Ou "la fin justifie-t-elle les moyens"?

pederpansen
la source
Bienvenue sur CV! Merci d'avoir rendu votre première question si claire et bien rédigée.
Silverfish
Je n'ai pas bien compris votre jeu de données. Les variables (attributs) sont count_red, count_blueet count_greenet les données sont des comptes. Droite? Quelles sont alors les lignes - les articles? Et vous allez regrouper les articles?
ttnphns
Les lignes représentent généralement des groupes d'achats agrégés. Vous pouvez les considérer comme des clients qui ont acheté plusieurs articles. J'ai mis à jour ma question avec un exemple de jeu de données pour le rendre plus clair.
pederpansen du
Vous souhaitez regrouper des "clients"?
ttnphns
Oui. J'ai l'intention de regrouper les achats par intervalles de temps également et par conséquent par intervalles de temps de cluster, mais pour l'instant: les clients.
pederpansen

Réponses:

7

@ttnphns a fourni une bonne réponse.

Bien faire un clustering, c'est souvent réfléchir très sérieusement à vos données, alors faisons-en une partie. À mon avis, l'aspect le plus fondamental de vos données est qu'elles sont de composition .

D'un autre côté, votre principale préoccupation semble être que vous avez beaucoup de 0 pour les produits verts et vous vous demandez en particulier si vous ne pouvez transformer que les valeurs vertes pour les rendre plus similaires aux autres. Mais comme ce sont des données de composition, vous ne pouvez pas penser à un ensemble de décomptes indépendamment des autres. De plus, il semble que ce qui vous intéresse vraiment, ce sont les probabilités des clients d'acheter des produits de différentes couleurs, mais parce que beaucoup n'en ont pas acheté de verts, vous craignez de ne pas pouvoir estimer ces probabilités. Une façon de résoudre ce problème consiste à utiliser une approche quelque peu bayésienne dans laquelle nous poussons les proportions estimées des clients vers une proportion moyenne, le montant du décalage étant influencé par leur éloignement de la moyenne et la quantité de données dont vous disposez pour estimer leur véritable probabilités.

Ci-dessous, j'utilise votre exemple de jeu de données pour illustrer (en R) une façon d'aborder votre situation. J'ai lu les données et les ai converties en proportions en ligne, puis j'ai calculé les proportions moyennes par colonne. J'ajoute les moyennes à chaque compte pour obtenir des comptes ajustés et de nouvelles proportions en ligne. Cela pousse la proportion estimée de chaque client vers la proportion moyenne de chaque produit. Si vous vouliez un coup de pouce plus fort, vous pouvez utiliser un multiple des moyens (tels que, 15*mean.props) à la place.

d = read.table(text="id  red    blue    green
...
c3  4   8   1", header=TRUE)
tab = as.table(as.matrix(d[,-1]))
rownames(tab) = paste0("c", 0:3)
tab
#    red blue green
# c0  12    5     0
# c1   3    4     0
# c2   2   21     0
# c3   4    8     1
props = prop.table(tab, 1)
props
#           red       blue      green
# c0 0.70588235 0.29411765 0.00000000
# c1 0.42857143 0.57142857 0.00000000
# c2 0.08695652 0.91304348 0.00000000
# c3 0.30769231 0.61538462 0.07692308
mean.props = apply(props, 2, FUN=function(x){ weighted.mean(x, rowSums(tab)) })
mean.props
#        red       blue      green 
# 0.35000000 0.63333333 0.01666667 
adj.counts = sweep(tab, 2, mean.props, FUN="+");  adj.counts
#            red        blue       green
# c0 12.35000000  5.63333333  0.01666667
# c1  3.35000000  4.63333333  0.01666667
# c2  2.35000000 21.63333333  0.01666667
# c3  4.35000000  8.63333333  1.01666667
adj.props = prop.table(adj.counts, 1);  adj.props
#             red         blue        green
# c0 0.6861111111 0.3129629630 0.0009259259
# c1 0.4187500000 0.5791666667 0.0020833333
# c2 0.0979166667 0.9013888889 0.0006944444
# c3 0.3107142857 0.6166666667 0.0726190476

Il y a plusieurs résultats à cela. L'une d'elles est que vous avez maintenant des estimations non nulles des probabilités sous-jacentes d'achat de produits verts, même lorsqu'un client n'a pas encore de dossier d'achat de produits verts. Une autre conséquence est que vous avez maintenant des valeurs quelque peu continues, alors que les proportions d'origine étaient plus discrètes; c'est-à-dire que l'ensemble d'estimations possibles est moins restreint, donc une mesure de distance comme la distance euclidienne au carré pourrait avoir plus de sens maintenant.

Nous pouvons visualiser les données pour voir ce qui s'est passé. Parce que ce sont des données de composition, nous n'avons en fait que deux informations, et nous pouvons les tracer dans un seul nuage de points. Avec la plupart des informations dans les catégories rouge et bleu, il est logique de les utiliser comme axes. Vous pouvez voir que les proportions ajustées (les nombres rouges) sont légèrement décalées par rapport à leurs positions d'origine.

windows()
  plot(props[,1], props[,2], pch=as.character(0:3),
       xlab="Proportion Red", ylab="Proportion Blue", xlim=c(0,1), ylim=c(0,1))
  points(adj.props[,1], adj.props[,2], pch=as.character(0:3), col="red")

entrez la description de l'image ici

À ce stade, vous avez des données et beaucoup de gens commenceraient par les normaliser. Encore une fois, comme ce sont des données de composition, j'exécuterais des analyses de grappe sans faire de normalisation - ces valeurs sont déjà proportionnées et la normalisation détruirait certaines des informations relationnelles. En fait, en regardant l'intrigue, je pense que vous n'avez vraiment qu'une seule dimension d'information ici. (Au moins dans l'échantillon de données; votre véritable ensemble de données peut être différent.) À moins que, d'un point de vue commercial, vous ne pensiez qu'il est important de reconnaître les personnes qui ont une probabilité substantielle d'acheter des produits verts en tant que groupe distinct de clients, je permettrait d'extraire les scores de la première composante principale (qui représente 99,5% de la variance dans cet ensemble de données) et de les regrouper.

pc.a.props = prcomp(adj.props[,1:2], center=T, scale=T)
cumsum(pc.a.props$sdev^2)/sum(pc.a.props$sdev^2)
# [1] 0.9946557 1.000000
pc.a.props$x
#           PC1         PC2
# c0 -1.7398975 -0.03897251
# c1 -0.1853614 -0.04803648
# c2  1.6882400 -0.06707115
# c3  0.2370189  0.15408015
library(mclust)
mc = Mclust(pc.a.props$x[,1])
summary(mc)
# ----------------------------------------------------
# Gaussian finite mixture model fitted by EM algorithm 
# ----------------------------------------------------
# 
# Mclust E (univariate, equal variance) model with 3 components:
# 
#  log.likelihood n df       BIC       ICL
#       -2.228357 4  6 -12.77448 -12.77448
# 
# Clustering table:
# 1 2 3 
# 1 2 1 
gung - Réintégrer Monica
la source
+1 parce que vous avez reconnu qu'il s'agit de données de composition, mais pourquoi ne pas simplement utiliser des techniques de transformation standard pour la composition. des données au lieu de cette idée étrange de "comptes moyens ajustés"? Cela me semble ad hoc, y a-t-il une référence particulière pour ceci ou quelque chose de similaire? Pourquoi est-ce mieux qu'une simple transformation log-ratio centrée et ensuite regrouper le premier score PC des données transformées? (ce que demanderait un critique raisonnable d'une application d'analyse de données
composites
Merci, @ usεr11852. Les nombres> 2, mais finis, sont des options multinomiales. Il s'agit (d'une forme d'une analyse empirique) bayésienne avec un a priori de Dirichlet (le conjugué). Je suis sûr que d'autres options sont possibles. Cependant, je ne vois pas immédiatement comment les ratios de prise fonctionneraient avec les 0.
gung - Réintègre Monica
2
Merci pour le lien. Si vous avez une seule dimension de composant non nulle, vous pouvez l'utiliser pour une transformation log-ratio additive (à l'exclusion de l'idée évidente d'imputation; voir les commentaires ici ). Le CLR serait désactivé, car il utilise une moyenne géométrique. Des travaux ont été menés sur les "données de composition gonflées à zéro"; voir par exemple ici , ici et ici .
usεr11852
1
Il semble que vous en sachiez beaucoup plus sur ce sujet que moi, @ usεr11852. Ma réponse était vraiment d'essayer de rendre ces faits sur la nature de la situation explicites / de soulever la question et de faire une suggestion préliminaire. Pourquoi ne pas apporter votre propre réponse (mieux informée)?
gung - Réintègre Monica
7

Il n'est pas judicieux de transformer les variables individuellement car elles sont liées (comme vous l'avez remarqué) et de faire k-means parce que les données sont des comptes (vous pourriez, mais k-means est préférable de le faire sur des attributs continus tels que la longueur par exemple) .

À votre place, je calculerais la distance chi carré (parfaite pour les comptes) entre chaque paire de clients, en fonction des variables contenant les comptes. Ensuite, effectuez un clustering hiérarchique (par exemple, méthode de liaison moyenne ou méthode de liaison complète - ils ne calculent pas les centroïdes et ne nécessitent donc pas de distance euclidienne) ou un autre cluster fonctionnant avec des matrices de distance arbitraires.

Copie d'exemples de données de la question:

-----------------------------------------------------------
customer | count_red  |    count_blue   | count_green     |
-----------------------------------------------------------
c0       |    12      |        5        |       0         |
-----------------------------------------------------------
c1       |     3      |        4        |       0         |
-----------------------------------------------------------
c2       |     2      |       21        |       0         |
-----------------------------------------------------------
c3       |     4      |        8        |       1         |
-----------------------------------------------------------

Considérez la paire c0et c1calculez la statistique du chi carré pour leur 2x3table de fréquences. Prenez-en la racine carrée (comme vous la prenez lorsque vous calculez la distance euclidienne habituelle). Telle est votre distance. Si la distance est proche de 0, les deux clients sont similaires.

Cela peut vous déranger que les sommes dans les rangées de votre tableau diffèrent et cela affecte donc la distance chi carré lorsque vous comparez c0avec c1vs c0avec c2. Calculez ensuite la (racine de) la distance Phi-carré : Phi-sq = Chi-sq/NNest le nombre total combiné dans les deux lignes (clients) actuellement considérées. C'est donc la distance normalisée par rapport aux dénombrements globaux.

Here is the matrix of sqrt(Chi-sq) distance between your four customers
 .000   1.275   4.057   2.292
1.275    .000   2.124    .862
4.057   2.124    .000   2.261
2.292    .862   2.261    .000

And here is the matrix of sqrt(Phi-sq) distance 
.000    .260    .641    .418
.260    .000    .388    .193
.641    .388    .000    .377
.418    .193    .377    .000

Ainsi, la distance entre deux lignes de données est la (racine carrée de) la statistique chi carré ou phi carré de la 2 x ptable de fréquences ( pest le nombre de colonnes dans les données). Si une ou plusieurs colonnes de la 2 x ptable en cours sont à zéro, coupez cette colonne et calculez la distance en fonction des colonnes non nulles restantes (c'est OK et c'est ainsi, par exemple, que SPSS fait quand il calcule la distance). La distance khi carré est en fait une distance euclidienne pondérée.

ttnphns
la source
Merci pour cette réponse élaborée. J'apprécie que vous ayez donné des conseils sur quelque chose qui n'était pas ma question initiale: K-means (avec la distance euclidienne implicite) est-il le bon choix pour ce cas d'utilisation? Je soupçonnais que non, et vous l'avez confirmé. Cependant, je ne comprends toujours pas pourquoi . Pourriez-vous expliquer 1) pourquoi la distance chi carré (ou phi carré) est un bon choix pour les données de comptage? 2) pour revenir à ma question initiale: existe-t-il un bon argument (mathématique / empirique) pour lequel toutes les variables devraient être traitées de la même manière que "elles sont liées"?
pederpansen du
Un client choisit parmi les trois couleurs lorsqu'il fait un seul achat: les trois couleurs ne sont pas des "variables" conceptuellement indépendantes. De plus, vos données comptent. Il était immédiatement clair pour moi qu'une mesure basée sur le chi carré devrait être optimale. En ce qui concerne votre dernier point - je pourrais vous demander en retour: pourquoi devraient-ils être traités différemment? A vous a donné une solution pour effectuer le travail de clustering. Y a-t-il quelque chose que vous n'aimez pas ou qui vous fait douter?
ttnphns du
2
Je ne pense pas non plus que k-means (minimisation de la variance!) Soit la voie à suivre: k-means utilise des moyens . Vos données sont des entiers et comportent de nombreux zéros. Les centres de cluster ne seront pas des entiers et auront peu de zéros. Ils sont totalement différents de vos points de données, comment peuvent-ils être représentatifs? Conclusion: ne vous battez pas pour transformer vos données en k-means. Comprenez le problème et adaptez les algorithmes à votre problème, et non l'inverse. Si vous adaptez vos données au problème de k-means, ce peut être toujours le mauvais problème ...
A QUIT - Anony-Mousse
1
Lorsque vous standardisez vos variables pour égaliser leurs variances, cela équivaut à peu près à égaliser les totaux dans les colonnes de votre tableau de données. Lorsque vous transformez l'inclinaison, cela équivaut à peu près à augmenter les nombres plus importants mais pas plus petits dans votre table. Vous pouvez le faire (et même après cela, vous pouvez calculer le chi ou le phi comme je l'ai suggéré), mais sachez que vous avez tordu les données originales. Était-ce justifié, avez-vous découvert et non dissimulé des informations précieuses? Était-ce une torture inutile des données? Au final, vous êtes le seul à décider de ces réflexions.
ttnphns
2
Il est facile de détruire les propriétés fondamentales par une normalisation inappropriée. Par exemple, si vos données totalisent 1 dans chaque ligne, la normalisation de chaque colonne détruira cette propriété. Sur ces données, vous devriez plutôt envisager par exemple des mesures de divergence (distances pour les distributions). En comptant les données, définir des mesures d'intersection telles que Jaccard peut être plus informatif; mais ils ont besoin de vecteurs binaires. etc.
A QUITTER - Anony-Mousse