Нахождение количества одинаковых групп

Рассмотрим задачу кластеризации, где известны истинные метки классов (скажем, g).

Предположим, p обозначает прогнозируемые метки кластеров (может быть получена любым подходом к кластеризации).

Таким образом, и g, и p разбивают набор данных на некоторые группы, хотя количество групп не обязательно должно быть одинаковым в двух случаях.

Среди этих двух наборов групп в некоторых случаях одна группа по g будет идентична другой группе по p, хотя их метки в двух случаях могут быть разными. Я хочу найти количество таких групп, т.е. я хочу найти количество случаев, когда метод кластеризации способен идеально определить класс.

Я понимаю, что это не стандартный способ оценки кластеризации (рекомендуются Rand Index, Dunn Index и т. д.), но меня это интересует. Я также понимаю, что это число будет очень маленьким в большинстве реальных данных, может быть, даже 0, но набор данных, с которым я сейчас работаю, имеет большое количество (около 1500) классов с наибольшим количеством наблюдений в одном класс не более 15. Таким образом, в этом случае это число, вероятно, будет довольно высоким.

Вот воспроизводимый пример и моя попытка (работа) над решением:

# 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

Created on 2019-05-22 by the reprex package (v0.3.0)

Это работает правильно, но требует времени (а я не люблю этот метод). Я полагаю, что можно использовать dplyr::group_by с g и p по отдельности и каким-то образом сравнить группы этих двух объектов. Я предполагаю, что есть другие лучшие подходы к этому, и я буду очень признателен за такие ответы.

Спасибо.

3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
2
0
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Преобразуйте g и p в factor с указанным levels на основе их появления в векторе и подсчитайте совпадающие частоты.

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

Чтобы понять, см.

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 

Мы можем игнорировать метки (поскольку метки групп не совпадают) и сосредоточиться только на частоте. Мы видим, что первое и четвертое значение имеют одинаковую частоту, следовательно, количество равно 2.

Если вы хотите узнать, какие группы похожи, вы можете сделать

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

Это говорит о том, что группа 3 в p аналогична группе 1 в g и одинакова для 2 и 4 соответственно.


Прежде чем решить это с помощью table, я сделал это с помощью split, хотя основная логика такая же.

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

РЕДАКТИРОВАТЬ

Если есть вероятность дисбаланса классов, нам нужно объединить уровни, чтобы включить всех. Например,

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

Предположим, что кластеров больше, чем классов (или наоборот). Тогда можно будет сделать эту строчку: table(factor(p, levels = unique(p))) == table(factor(g, levels = unique(g)))?

yarnabrina 22.05.2019 11:19

@yarnabrina В этом случае нам нужно объединить уровни. Смотрите обновленный ответ.

Ronak Shah 22.05.2019 11:32

Да, это сработает. Но я могу представить себе другой сценарий. Предположим, g2 <- c(1, 1, 2, 2, 2, 1, 3, 3, 3, 4, 5) и p2 <- c(13, 13, 11, 11, 11, 13, 14, 14, 11, 12, 11). Тогда вы получите 6, где и должно быть 2. Нужно ли мне изменить аргумент labels для этого?

yarnabrina 22.05.2019 12:15

@yarnabrina да, в таком случае измените их на одинаковые labelsg3 <- factor(g2, labels = letters[seq_len(length(unique(g2)))]); p3 <- factor(p2, labels = letters[seq_len(length(unique(p2)))]), а затем используйте отредактированный ответ.

Ronak Shah 22.05.2019 12:50

Спасибо. Только одно последнее уточнение: нужно ли letters?

yarnabrina 22.05.2019 13:44

Нет, вы можете использовать что угодно. Дело в том, что метки должны быть одинаковыми для обоих из них.

Ronak Shah 22.05.2019 14:20
Ответ принят как подходящий

Если вас также интересует комбинация правильно обнаруженных групп, вы можете попробовать это

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

Количество строк (вы можете использовать nrow()) даст вам количество правильно обнаруженных групп.

Не могли бы вы добавить некоторые пояснения? Я думаю, что он использует тот факт, что для идеального обнаружения класса каким-либо кластером ни метка класса, ни метка кластера не могут встречаться с каким-либо другим кластером или классом соответственно. Это так?

yarnabrina 22.05.2019 11:25

Точно, вы поняли!

MrNetherlands 22.05.2019 11:31

Другие вопросы по теме