为什么 LDA 预测不正确
Why are LDA predictions incorrect
第 1 步
我正在使用 R 和 "topicmodels" 包从 4.5k 文档语料库构建 LDA 模型。我执行了通常的预处理步骤(停用词、削减 low/high 词频、词形还原)并最终得到了一个我很满意的 100 个主题模型。事实上,它几乎是满足我需求的完美模型。
justlda <- LDA(k=100, x=dtm_lemma, method="Gibbs", control=control_list_gibbs)
第 2 步
然后我使用与上面完全相同的过程预处理一个新的(模型看不到的)300 个文档语料库,然后将其转换为文档术语矩阵,然后使用 "posterior" 函数相同的包来预测新数据的主题。 该语料库来自同一作者,与训练集非常相似。
我的问题
我得到的预测(后验概率)是完全错误的。
这是我用来获取后验的代码:
topics = posterior(justlda, dtm_lemma, control = control_list_gibbs)$topics
- justlda是第一步用全语料建立的模型
- dtm_lemma是新数据预处理后的document-term矩阵
- 控制是lda参数(两者相同)。
感觉不仅预测错了,题目权重也很低。没有什么是主导话题。 (对于这个 100 个主题的模型,大多数主题的权重为 0.08,我很幸运得到了一个甚至不相关的 0.20 权重...)
我使用 NLP/LDA 和 R 语言的经验还不到一年。我觉得我可能在某个地方犯了一个非常业余的错误,可以解释错误的预测?
这样的结果正常吗?我可能做错了什么?
我不是 100% 确定你所说的 'wrong' 是什么意思。我做了一个快速测试,看看 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
来获取每个文档的 gamma 值,再次只保留最有可能的值:
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,其中第二个有一个额外的术语,而另一个缺少一个术语。因此 dimnames 是不同的。我们可以通过将 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
您现在可以将其用作后验的新数据。
第 1 步
我正在使用 R 和 "topicmodels" 包从 4.5k 文档语料库构建 LDA 模型。我执行了通常的预处理步骤(停用词、削减 low/high 词频、词形还原)并最终得到了一个我很满意的 100 个主题模型。事实上,它几乎是满足我需求的完美模型。
justlda <- LDA(k=100, x=dtm_lemma, method="Gibbs", control=control_list_gibbs)
第 2 步
然后我使用与上面完全相同的过程预处理一个新的(模型看不到的)300 个文档语料库,然后将其转换为文档术语矩阵,然后使用 "posterior" 函数相同的包来预测新数据的主题。 该语料库来自同一作者,与训练集非常相似。
我的问题
我得到的预测(后验概率)是完全错误的。 这是我用来获取后验的代码:
topics = posterior(justlda, dtm_lemma, control = control_list_gibbs)$topics
- justlda是第一步用全语料建立的模型
- dtm_lemma是新数据预处理后的document-term矩阵
- 控制是lda参数(两者相同)。
感觉不仅预测错了,题目权重也很低。没有什么是主导话题。 (对于这个 100 个主题的模型,大多数主题的权重为 0.08,我很幸运得到了一个甚至不相关的 0.20 权重...)
我使用 NLP/LDA 和 R 语言的经验还不到一年。我觉得我可能在某个地方犯了一个非常业余的错误,可以解释错误的预测?
这样的结果正常吗?我可能做错了什么?
我不是 100% 确定你所说的 'wrong' 是什么意思。我做了一个快速测试,看看 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
来获取每个文档的 gamma 值,再次只保留最有可能的值:
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,其中第二个有一个额外的术语,而另一个缺少一个术语。因此 dimnames 是不同的。我们可以通过将 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
您现在可以将其用作后验的新数据。