Подтвердить что ты не робот

Модели темы: перекрестная проверка с лозунгом правдоподобия или недоумением

Я кластеризую документы, используя моделирование тем. Мне нужно найти оптимальные номера тем. Итак, я решил сделать десятикратную перекрестную проверку с темами 10, 20,... 60.

Я разделил свой корпус на десять партий и отложил одну партию для набора удержания. Я провел скрытое распределение дирихле (LDA) с использованием девяти партий (всего 180 документов) с темами от 10 до 60. Теперь я должен рассчитать недоумение или вероятность регистрации для набора ограничений.

Я нашел этот код на одном из сеансов CV. Я действительно не понимаю несколько строк ниже. У меня есть dtm-матрица, использующая набор ограничений (20 документов). Но я не знаю, как рассчитать недоумение или логарифмическую вероятность этого набора ограничений.


Вопросы:

  • Может ли кто-нибудь объяснить мне, что означают здесь (2, 100, 1 = 1)? Кроме того, что означает AssociatedPress [21:30]? Какую функцию (k) делает здесь?

    best.model <- lapply(seq(2, 100, by=1), function(k){ LDA(AssociatedPress[21:30,], k) })
    
  • Если я хочу рассчитать недоумение или логарифмическую вероятность набора удержания, называемого dtm, есть ли лучший код? Я знаю, что есть функции perplexity() и logLik(), но поскольку я новичок, я не могу понять, как реализовать его с моей матрицей удержания, называемой dtm.

  • Как я могу сделать десятикратное перекрестное подтверждение с моим корпусом, содержащим 200 документов? Есть ли код, который я могу вызвать? Я нашел caret для этой цели, но опять же не могу понять это.

4b9b3361

Ответ 1

Принятый ответ на этот вопрос хорош, насколько это возможно, но на самом деле он не описывает, как оценить недоумение в наборе данных валидации и как использовать перекрестную проверку.

Использование недоумения для простой проверки

Perplexity - это показатель того, насколько хорошо вероятностная модель подходит для нового набора данных. В пакете topicmodels R просто вписывается в функцию perplexity, которая принимает в качестве аргументов ранее подходящую модель темы и новый набор данных и возвращает один номер. Чем ниже, тем лучше.

Например, разделение данных AssociatedPress на обучающий набор (75% строк) и набор проверки (25% строк):

# load up some R packages including a few we'll need later
library(topicmodels)
library(doParallel)
library(ggplot2)
library(scales)

data("AssociatedPress", package = "topicmodels")

burnin = 1000
iter = 1000
keep = 50

full_data  <- AssociatedPress
n <- nrow(full_data)
#-----------validation--------
k <- 5

splitter <- sample(1:n, round(n * 0.75))
train_set <- full_data[splitter, ]
valid_set <- full_data[-splitter, ]

fitted <- LDA(train_set, k = k, method = "Gibbs",
                          control = list(burnin = burnin, iter = iter, keep = keep) )
perplexity(fitted, newdata = train_set) # about 2700
perplexity(fitted, newdata = valid_set) # about 4300

Недоумение выше для набора проверки, отличного от набора тренировок, потому что темы были оптимизированы на основе набора тренировок.

Использование недоумения и кросс-валидации для определения большого количества тем

Расширение этой идеи до перекрестной проверки просто. Разделите данные на разные подмножества (скажем, 5), и каждое подмножество получает один оборот в качестве набора проверки и четыре витка как часть набора тренировок. Тем не менее, это действительно вычислительно интенсивно, особенно при опробовании большего количества тем.

Возможно, вы сможете использовать caret, но я подозреваю, что он еще не обрабатывает моделирование тем. В любом случае, это то, что я предпочитаю делать сам, чтобы быть уверенным, что я понимаю, что происходит.

В приведенном ниже коде, даже при параллельной обработке на 7 логических процессорах, потребовалось 3,5 часа для работы на моем ноутбуке:

#----------------5-fold cross-validation, different numbers of topics----------------
# set up a cluster for parallel processing
cluster <- makeCluster(detectCores(logical = TRUE) - 1) # leave one CPU spare...
registerDoParallel(cluster)

# load up the needed R package on all the parallel sessions
clusterEvalQ(cluster, {
   library(topicmodels)
})

folds <- 5
splitfolds <- sample(1:folds, n, replace = TRUE)
candidate_k <- c(2, 3, 4, 5, 10, 20, 30, 40, 50, 75, 100, 200, 300) # candidates for how many topics

# export all the needed R objects to the parallel sessions
clusterExport(cluster, c("full_data", "burnin", "iter", "keep", "splitfolds", "folds", "candidate_k"))

# we parallelize by the different number of topics.  A processor is allocated a value
# of k, and does the cross-validation serially.  This is because it is assumed there
# are more candidate values of k than there are cross-validation folds, hence it
# will be more efficient to parallelise
system.time({
results <- foreach(j = 1:length(candidate_k), .combine = rbind) %dopar%{
   k <- candidate_k[j]
   results_1k <- matrix(0, nrow = folds, ncol = 2)
   colnames(results_1k) <- c("k", "perplexity")
   for(i in 1:folds){
      train_set <- full_data[splitfolds != i , ]
      valid_set <- full_data[splitfolds == i, ]

      fitted <- LDA(train_set, k = k, method = "Gibbs",
                    control = list(burnin = burnin, iter = iter, keep = keep) )
      results_1k[i,] <- c(k, perplexity(fitted, newdata = valid_set))
   }
   return(results_1k)
}
})
stopCluster(cluster)

results_df <- as.data.frame(results)

ggplot(results_df, aes(x = k, y = perplexity)) +
   geom_point() +
   geom_smooth(se = FALSE) +
   ggtitle("5-fold cross-validation of topic modelling with the 'Associated Press' dataset",
           "(ie five different models fit for each candidate number of topics)") +
   labs(x = "Candidate number of topics", y = "Perplexity when fitting the trained model to the hold-out set")

Мы видим в результатах, что 200 тем слишком много, и некоторые из них слишком сложны, а 50 слишком мало. Из числа опробованных тем, 100 является лучшим, с наименьшим средним недоумением на пяти разных наборах простоя.

введите описание изображения здесь

Ответ 2

Я написал ответ на CV, на который вы ссылаетесь, здесь немного подробнее:

  • seq(2, 100, by =1) просто создает числовую последовательность от 2 до 100 с помощью единиц, поэтому 2, 3, 4, 5,... 100. Это числа тем, которые я хочу использовать в моделях. Одна модель с двумя темами, другая с 3 темами, другая с 4 темами и т.д. До 100 тем.

  • AssociatedPress[21:30] - это просто подмножество встроенных данных в пакете topicmodels. Я просто использовал подмножество в этом примере, чтобы он работал быстрее.

Что касается общего вопроса об оптимальных номерах тем, я теперь следую примеру Мартина Ponweiser по выбору модели по гармоническому средству (4.3.3 в своем тезисе, который находится здесь: http://epub.wu.ac.at/3558/1/main.pdf). Вот как я это делаю в данный момент:

library(topicmodels)
#
# get some of the example data that bundled with the package
#
data("AssociatedPress", package = "topicmodels")

harmonicMean <- function(logLikelihoods, precision=2000L) {
  library("Rmpfr")
  llMed <- median(logLikelihoods)
  as.double(llMed - log(mean(exp(-mpfr(logLikelihoods,
                                       prec = precision) + llMed))))
}

# The log-likelihood values are then determined by first fitting the model using for example
k = 20
burnin = 1000
iter = 1000
keep = 50

fitted <- LDA(AssociatedPress[21:30,], k = k, method = "Gibbs",control = list(burnin = burnin, iter = iter, keep = keep) )

# where keep indicates that every keep iteration the log-likelihood is evaluated and stored. This returns all log-likelihood values including burnin, i.e., these need to be omitted before calculating the harmonic mean:

logLiks <- [email protected][-c(1:(burnin/keep))]

# assuming that burnin is a multiple of keep and

 harmonicMean(logLiks)

Итак, сделайте это над последовательностью тематических моделей с различным количеством тем...

# generate numerous topic models with different numbers of topics
sequ <- seq(2, 50, 1) # in this case a sequence of numbers from 1 to 50, by ones.
fitted_many <- lapply(sequ, function(k) LDA(AssociatedPress[21:30,], k = k, method = "Gibbs",control = list(burnin = burnin, iter = iter, keep = keep) ))

# extract logliks from each topic
logLiks_many <- lapply(fitted_many, function(L)  [email protected][-c(1:(burnin/keep))])

# compute harmonic means
hm_many <- sapply(logLiks_many, function(h) harmonicMean(h))

# inspect
plot(sequ, hm_many, type = "l")

# compute optimum number of topics
sequ[which.max(hm_many)]
## 6

enter image description here Здесь вывод с номерами тем по оси х, что указывает на то, что 6 тем являются оптимальными.

Перекрестная проверка тематических моделей довольно хорошо документирована в документах, которые поставляются с пакетом, см. здесь, например: http://cran.r-project.org/web/packages/topicmodels/vignettes/topicmodels.pdf Дать попробуйте, а затем вернитесь с более конкретным вопросом о кодировании CV с тематическими моделями.