Почему прогнозы LDA неверны - PullRequest
2 голосов
/ 17 марта 2019

Шаг 1

Я использую R и пакет "topicmodels" для построения модели LDA из корпуса документов 4.5k. Я делаю обычные шаги предварительной обработки (стоп-слова, обрезание частот низких / высоких слов, лемматизация) и в итоге получаю модель из 100 тем, которой я доволен. На самом деле, это почти идеальная модель для моих нужд.

justlda <- LDA(k=100, x=dtm_lemma, method="Gibbs", control=control_list_gibbs)

Шаг 2

Затем я предварительно обработал, используя тот же точный процесс, что и выше, новый (невидимый моделью) корпус 300 документов, затем преобразовал его в матрицу термина документов, а затем использовал функцию "апостериор" того же пакета, чтобы предсказать темы по новым данным. Этот корпус исходит от тех же авторов и очень похож на учебный набор.

Моя проблема

Предсказания (апостериорные вероятности), которые я получаю, совершенно неверны. Вот код, который я использую для получения апостериорного кода:

topics = posterior(justlda, dtm_lemma, control = control_list_gibbs)$topics
  • justlda - это модель, построенная со всем корпусом на шаге 1.
  • dtm_lemma - предварительно обработанная матрица термина документа для новых данных.
  • Управление параметрами (одинаково для обоих).

Мне кажется, что не только неправильные прогнозы, но и вес тем очень низок. Ничто не выходит в качестве доминирующей темы. (Для этой модели из 100 тем большинство тем выходит в виде 0,08, и мне повезло получить вес 0,20, который даже не актуален ...)

Я получил менее года опыта работы с NLP / LDA и языком R. Я чувствую, что где-то допускаю очень любительскую ошибку, которая может объяснить неправильные прогнозы?

Нормальные ли это результаты? Что я мог делать не так?

1 Ответ

1 голос
/ 18 марта 2019

Я не уверен на 100%, что вы подразумеваете под «неправильно».Я быстро проверил, работает ли posterior на новых данных.Сначала я запускаю модель со всеми документами набора данных AssociatedPress:

library(topicmodels)
data("AssociatedPress")
ap_lda <- LDA(AssociatedPress, k = 5, control = list(seed = 1234))

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

library(tidytext)
library(dplyr)
library(tidyr)
ap_documents <- tidy(ap_lda, matrix = "gamma")
ap_documents %>% 
  group_by(document) %>% 
  top_n(1, gamma) %>% # keep only most likely topic
  arrange(document)
# A tibble: 2,246 x 3
# Groups:   document [2,246]
   document topic gamma
      <int> <int> <dbl>
 1        1     4 0.999
 2        2     2 0.529
 3        3     4 0.999
 4        4     4 0.518
 5        5     4 0.995
 6        6     2 0.971
 7        7     1 0.728
 8        8     2 0.941
 9        9     4 0.477
10       10     5 0.500
# ... with 2,236 more rows

Теперь я снова запускаю тот же LDA, но отказываюсь от первых 10 документов:

AssociatedPress_train <- AssociatedPress[11:nrow(AssociatedPress), ]
AssociatedPress_test <- AssociatedPress[1:10, ]

ap_lda <- LDA(AssociatedPress_train, k = 5, control = list(seed = 1234))

Я использую posterior для получения значений гаммы для каждого документа и снова сохраняю наиболее вероятное значение:

posterior(object = ap_lda, newdata = AssociatedPress_test)$topics %>%
  as_tibble() %>% 
  mutate(document = seq_len(nrow(.))) %>% 
  gather(topic, gamma, -document) %>% 
  group_by(document) %>% 
  top_n(1, gamma) %>% # keep only most probable topic
  arrange(document)
# A tibble: 10 x 3
# Groups:   document [10]
   document topic gamma
      <int> <chr> <dbl>
 1        1 4     0.898
 2        2 2     0.497
 3        3 4     0.896
 4        4 4     0.468
 5        5 4     0.870
 6        6 2     0.754
 7        7 1     0.509
 8        8 2     0.913
 9        9 4     0.476
10       10 2     0.399

Все, кроме документа 10, имеют такую ​​же наиболее вероятную тему, как и раньше.Так что, кажется, все работает нормально!Поэтому я не вижу непосредственной проблемы с вашим кодом.

Одна вещь, которую я не проверял, это то, что происходит, если DTM обучения и набора тестов имеют разные столбцы.Я подозреваю, что это будет проблемой.

Вот краткий пример того, как вы могли бы справиться с этим:

text1 <- tibble(doc = 1, word = LETTERS[1:10])
text2 <- tibble(doc = 1, word = LETTERS[2:11])
dtm1 <- text1 %>%
  count(doc, word) %>%
  arrange(word) %>%
  cast_dtm(doc, word, n)

dtm2 <- text2 %>%
  count(doc, word) %>%
  arrange(word) %>%
  cast_dtm(doc, word, n)

all.equal(dtm1$dimnames$Terms, dtm2$dimnames$Terms)
[1] "10 string mismatches"

Я делаю два DTM, где у второго есть дополнительный термин и не хватаетодин термин из другого.Диммы, таким образом, разные.Мы можем сделать их равными, приведя DTM обратно в аккуратный формат, удалив лишний термин и добавив пропущенные термины перед повторным приведением DTM:

dtm2_clean <- tidy(dtm2) %>% 
  filter(term %in% dtm1$dimnames$Terms) %>% 
  rbind(tibble(document = 1, 
               term = dtm1$dimnames$Terms, # adding term but no counts
               count = 0)) %>% 
  arrange(term) %>% 
  cast_dtm(document, term, count)

all.equal(dtm1$dimnames$Terms, dtm2_clean$dimnames$Terms)
[1] TRUE

Теперь вы можете использовать это как новые данные для апостериорного.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...