Кластеризация: как выделить наиболее отличительные черты?

У меня есть набор документов, которые я пытаюсь кластеризовать на основе их словарного запаса (то есть сначала делаю корпус, а затем разреженную матрицу с помощью команды DocumentTermMatrix и так далее). Чтобы улучшить кластеры и лучше понять, какие функции/слова заставляют конкретный документ попадать в конкретный кластер, я хотел бы знать, каковы наиболее отличительные черты для каждого кластера.

Пример этого есть в книге Ланца Machine Learning with R, если вы ее знаете — он группирует профили подростков в социальных сетях по интересам, к которым они привязаны, и в итоге получается таблица наподобие это показывает «каждый кластер ... с функциями, которые больше всего отличают его от других кластеров»:

cluster 1  | cluster 2 | cluster 3 ....
swimming   | band      | sports  ... 
dance      | music     | kissed ....

Теперь мои функции не столь информативны, но я все же хотел бы построить что-то подобное.
Однако в книге не объясняется, как была построена таблица. Я изо всех сил старался творчески гуглить, и, возможно, ответом является какой-то очевидный расчет средств кластера, но, будучи новичком в R, а также в статистике, я не мог этого понять. Любая помощь очень ценится, включая ссылки на предыдущие вопросы или другие ресурсы, которые я, возможно, пропустил!

Спасибо.


person user3206277    schedule 17.01.2014    source источник


Ответы (1)


У меня была аналогичная проблема некоторое время назад..

Вот что я сделал:

require("tm")
require("skmeans")
require("slam")

# clus: a skmeans object
# dtm: a Document Term Matrix
# first: eg. 10 most frequent words per cluster
# unique: if FALSE all words of the DTM will be used
#         if TRUE only cluster specific words will be used 



# result: List with words and frequency of words 
#         If unique = TRUE, only cluster specific words will be considered.
#         Words which occur in more than one cluster will be ignored.



mfrq_words_per_cluster <- function(clus, dtm, first = 10, unique = TRUE){
  if(!any(class(clus) == "skmeans")) return("clus must be an skmeans object")

  dtm <- as.simple_triplet_matrix(dtm)
  indM <- table(names(clus$cluster), clus$cluster) == 1 # generate bool matrix

  hfun <- function(ind, dtm){ # help function, summing up words
    if(is.null(dtm[ind, ]))  dtm[ind, ] else  col_sums(dtm[ind, ])
  }
  frqM <- apply(indM, 2, hfun, dtm = dtm)

  if(unique){
    # eliminate word which occur in several clusters
    frqM <- frqM[rowSums(frqM > 0) == 1, ] 
  }
  # export to list, order and take first x elements 
  res <- lapply(1:ncol(frqM), function(i, mat, first)
                head(sort(mat[, i], decreasing = TRUE), first),
                mat = frqM, first = first)

  names(res) <- paste0("CLUSTER_", 1:ncol(frqM))
  return(res)
}

Небольшой пример:

data("crude")
dtm <- DocumentTermMatrix(crude, control =
                          list(removePunctuation = TRUE,
                               removeNumbers = TRUE,
                               stopwords = TRUE))

rownames(dtm) <- paste0("Doc_", 1:20)
clus <- skmeans(dtm, 3)


mfrq_words_per_cluster(clus, dtm)
mfrq_words_per_cluster(clus, dtm, unique = FALSE)

ХТН

person holzben    schedule 17.01.2014
comment
Бесконечно благодарен! Это работает как шарм и делает именно то, что я хотел. - person user3206277; 18.01.2014
comment
Привет @holzben, я использовал вашу функцию выше в своем анализе, но у меня возникла икота. Я разместил этот вопрос. Не могли бы вы взглянуть и посмотреть, сможете ли вы решить это? Большое спасибо [ссылка] stackoverflow.com/questions/23444693/ - person user3456230; 04.05.2014
comment
эй, я кратко просмотрел ваш файл ... не могу найти никакой ошибки, не присматриваясь, но моя рекомендация (как и другие) уменьшите ваш набор данных, например. 50 твитов и посмотрите, работает ли функция правильно... ваш файл слишком большой для проверки функции -бен - person holzben; 06.05.2014