У меня есть набор документов, которые я пытаюсь кластеризовать на основе их словарного запаса (то есть сначала делаю корпус, а затем разреженную матрицу с помощью команды DocumentTermMatrix и так далее). Чтобы улучшить кластеры и лучше понять, какие функции/слова заставляют конкретный документ попадать в конкретный кластер, я хотел бы знать, каковы наиболее отличительные черты для каждого кластера.
Пример этого есть в книге Ланца Machine Learning with R, если вы ее знаете - он группирует профили подростков в социальных сетях по интересам, к которым они привязаны, и в итоге получается таблица наподобие это показывает "каждый кластер ... с функциями, которые больше всего отличают его от других кластеров":
cluster 1 | cluster 2 | cluster 3 ....
swimming | band | sports ...
dance | music | kissed ....
Теперь мои функции не столь информативны, но я все же хотел бы построить что-то подобное.
Однако в книге не объясняется, как была построена таблица. Я изо всех сил старался творчески гуглить, и, возможно, ответом является какой-то очевидный расчет средств кластера, но, будучи новичком в R, а также в статистике, я не мог этого понять. Любая помощь очень ценится, включая ссылки на предыдущие вопросы или другие ресурсы, которые я, возможно, пропустил!
Спасибо.
Ответ 1 · рейтинг 3 · holzben
У меня была аналогичная проблема некоторое время назад..
Вот что я сделал:
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)
ХТН