2 votes

Trouver le nombre de groupes identiques

Considérons un problème de regroupement, où les véritables étiquettes de classe sont connues (disons g ).

Supposons, p dénote les étiquettes prédites des clusters (peuvent être obtenues par n'importe quelle approche de clustering).

Donc, les deux g y p divise l'ensemble des données en plusieurs groupes, mais le nombre de groupes ne doit pas nécessairement être le même dans les deux cas.

Parmi ces deux ensembles de groupes, dans certains cas, un groupe par g sera identique à un autre groupe par p bien que leurs étiquettes puissent être différentes dans deux cas. Je veux trouver le nombre de tels groupes, c'est-à-dire le nombre de cas où la méthode de clustering est capable de détecter parfaitement une classe.

Je comprends que ce n'est pas une façon standard d'évaluer le clustering (l'indice Rand, l'indice Dunn, etc. sont recommandés), mais cela m'intéresse. Je comprends également que ce nombre sera très faible dans la plupart des données de la vie réelle, peut-être même qu'il ne s'agira pas d'une valeur de référence. 0 Mais l'ensemble de données sur lequel je travaille actuellement comporte un grand nombre (environ 1500) de classes, le nombre le plus élevé d'observations dans une classe étant au maximum de 15. Donc, dans ce cas, ce nombre est susceptible d'être assez élevé.

Voici un exemple reproductible et ma tentative (fonctionnelle) de solution :

# true labels
g <- c(1, 1, 2, 2, 2, 1, 3, 3, 3, 4)

# predicted labels
p <- c(3, 3, 1, 1, 1, 3, 4, 4, 1, 2)

# correctly detected groups
n_correct <- 2 # (1st class and 3rd cluster), (4th class and 2nd cluster)

# attempt
distinct_class_labels <- unique(x = g)
counter <- 0
for (i in seq_along(along.with = distinct_class_labels))
{
  cluster_labels_of_obs_in_ith_class <- subset(x = p,
                                               subset = (g == distinct_class_labels[i]))
  unique_cluster_labels_of_obs_in_ith_class <- unique(x = cluster_labels_of_obs_in_ith_class)
  if (length(x = unique_cluster_labels_of_obs_in_ith_class) == 1)
  {
    class_labels_of_obs_in_this_cluster <- subset(x = g,
                                                  subset = (p == unique_cluster_labels_of_obs_in_ith_class))
    if (length(x = unique(x = class_labels_of_obs_in_this_cluster)) == 1)
    {
      counter <- (counter + 1)
    }
  }
}
counter
#> [1] 2

Créé le 2019-05-22 par le paquet reprex (v0.3.0)

Cela fonctionne correctement, mais cela prend du temps (et je n'aime pas cette méthode). Je suppose que l'on peut utiliser dplyr::group_by avec les deux g y p séparément et d'une certaine manière, comparer les groupes de ces deux objets. Je suppose qu'il existe d'autres approches plus efficaces et je vous serais reconnaissant de bien vouloir me répondre.

Merci.

2voto

cholland Points 383

Si vous êtes également intéressé par la combinaison des groupes correctement détectés, vous pouvez essayer ceci

library(tidyverse)

tibble(g = g, p=p) %>%
  distinct(g,p) %>% # unique combinations of g and p
  add_count(g, name="g_count") %>% # count how often each class/label occurs in g and p. When it is unambiguous assigned it should be 1
  add_count(p, name="p_count") %>%
  filter(g_count == 1 & p_count == 1) %>%
  select(g,p)

# A tibble: 2 x 2
      g     p
  <dbl> <dbl>
1     1     3
2     4     2

Le nombre de lignes (vous pouvez utiliser nrow() ) vous donnera le nombre de groupes correctement détectés

1voto

Ronak Shah Points 24715

Convertir g y p à factor con levels spécifiés en fonction de leur occurrence dans le vecteur et compter les fréquences qui correspondent.

sum(table(factor(p, levels = unique(p))) == table(factor(g, levels = unique(g))))
#[1] 2

Pour comprendre, voir

table(factor(p, levels = unique(p)))

#3 1 4 2 
#3 4 2 1 
table(factor(g, levels = unique(g)))

#1 2 3 4 
#3 3 3 1 

Nous pouvons ignorer les étiquettes (car les étiquettes des groupes ne sont pas les mêmes) et nous concentrer uniquement sur la fréquence. Nous pouvons voir que la première et la quatrième valeur ont la même fréquence, d'où le compte 2.

Si vous voulez savoir quels groupes sont similaires, vous pouvez faire ce qui suit

inds <- table(factor(p, levels = unique(p))) == table(factor(g, levels = unique(g)))
unique(p)[inds]
#[1] 3 2
unique(g)[inds]
#[1] 1 4

Cela signifie que le groupe 3 dans p est similaire au groupe 1 dans g et de même pour 2 et 4 respectivement.


Avant de le résoudre en utilisant table Je l'ai fait avec split bien que la logique sous-jacente soit la même.

sum(lengths(split(p, factor(p, levels = unique(p)))) == 
    lengths(split(g, factor(g, levels = unique(g)))))

EDIT

S'il y a un risque de déséquilibre entre les classes, nous devons combiner les niveaux pour les inclure tous. Par exemple,

g1 <- c(g, 5)
p1 <- c(p, 1)

sum(table(factor(p1, levels = unique(c(p1, g1)))) ==  
    table(factor(g1, levels = unique(c(g1, p1)))))
#[1] 2

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X