我正在一个项目中,我要提取有关一系列开放式论文内容的信息。在这个特定的项目中,作为大型实验的一部分,有148人撰写了有关假设的学生组织的文章。尽管在我的领域(社会心理学),分析这些数据的典型方法是手工编写论文,但我想定量地进行此操作,因为手工编码既费工又过于主观味道。
在对定量分析免费响应数据的方法进行调查期间,我偶然发现了一种称为主题建模(或潜在Dirichlet分配或LDA)的方法。主题建模采用数据的单词袋表示(术语文档矩阵),并使用有关单词共现的信息来提取数据的潜在主题。这种方法对我的应用程序似乎很完美。
不幸的是,当我将主题建模应用于数据时,我发现了两个问题:
- 主题建模发现的主题有时很难解释
- 当我使用其他随机种子重新运行主题模型时,主题似乎发生了巨大变化
我特别关心第2期。因此,我有两个相关的问题:
- 在LDA程序中,我可以做些什么来优化我的模型拟合程序的可解释性和稳定性?就我个人而言,我不太关心寻找具有最低困惑度和/或最佳模型拟合度的模型-我主要是想使用此过程来帮助我理解和表征本研究参与者在论文中写的内容。但是,我当然不希望我的结果成为随机种子的假象!
- 与上述问题相关,LDA是否需要多少数据的标准?我见过的大多数使用这种方法的论文都分析了大型语料库(例如,过去20年中所有科学论文的档案),但是,由于我使用的是实验数据,因此我的文档语料库要小得多。
我在这里张贴了论文数据,以供任何想弄脏他或她的手的人使用,并且我在下面粘贴了我正在使用的R代码。
require(tm)
require(topicmodels)
# Create a corpus from the essay
c <- Corpus(DataframeSource(essays))
inspect(c)
# Remove punctuation and put the words in lower case
c <- tm_map(c, removePunctuation)
c <- tm_map(c, tolower)
# Create a DocumentTermMatrix. The stopwords are the LIWC function word categories
# I have a copy of the LIWC dictionary, but if you want to do a similar analysis,
# use the default stop words in tm
dtm <- DocumentTermMatrix(c, control = list(stopwords =
c(dict$funct, dict$pronoun, dict$ppron, dict$i, dict$we, dict$you, dict$shehe,
dict$they, dict$inpers, dict$article, dict$aux)))
# Term frequency inverse-document frequency to select the desired words
term_tfidf <- tapply(dtm$v/rowSums(as.matrix(dtm))[dtm$i], dtm$j, mean) * log2(nDocs(dtm)/colSums(as.matrix(dtm)))
summary(term_tfidf)
dtm <- dtm[, term_tfidf >= 0.04]
lda <- LDA(dtm, k = 5, seed = 532)
perplexity(lda)
(terms <- terms(lda, 10))
(topics <- topics(lda))
编辑:
我尝试nstart
按照Flounderer在评论中的建议进行修改。不幸的是,如下所示,即使设置nstart
为1000,主题也会因随机种子而异。再次强调一下,我在以下两个模型的估计中唯一要更改的是用于开始模型估计的随机种子,但是,这两个主题似乎根本不一致。
lda <- LDA(dtm, k = 5, seed = 535, control = list(nstart = 1000))
(terms <- terms(lda, 10))
Topic 1 Topic 2 Topic 3 Topic 4 Topic 5
[1,] "international" "ethnicity" "free" "credit" "kind"
[2,] "communicate" "true" "team" "mandatory" "bridge"
[3,] "gain" "asians" "cooperate" "music" "close"
[4,] "use" "hand" "order" "seen" "deal"
[5,] "big" "hold" "play" "barrier" "designed"
[6,] "communication" "effective" "big" "stereotypes" "effort"
[7,] "america" "emphasis" "beginning" "asians" "implemented"
[8,] "chinese" "halls" "china" "fantastic" "websites"
[9,] "ethnicity" "minorities" "difference" "focusing" "planned"
[10,] "networks" "population" "easier" "force" "body"
lda <- LDA(dtm, k = 5, seed = 536, control = list(nstart = 1000))
(terms <- terms(lda, 10))
Topic 1 Topic 2 Topic 3 Topic 4 Topic 5
[1,] "kind" "international" "issue" "willing" "play"
[2,] "easier" "ethnicity" "close" "use" "trying"
[3,] "gain" "communication" "currently" "hand" "unity"
[4,] "websites" "communicate" "implemented" "networks" "decision"
[5,] "credit" "bridge" "particularly" "stereotypes" "gap"
[6,] "effort" "america" "credit" "communicate" "normally"
[7,] "barriers" "connection" "fulfill" "came" "asians"
[8,] "effects" "kind" "grew" "asians" "created"
[9,] "established" "order" "perspectives" "big" "effective"
[10,] "strangers" "skills" "big" "budget" "prejudice"
nstart
并查看该课程的网站,以查看其中任一内容是否有用。(顺便说一句,如果您在评论中插入您的评论,我会投票赞成。我想在接受任何内容之前先征询其他人的意见,但我认为您的评论足以算作一个答案)。
LDA
在topicmodels
包中的函数中调整控制参数。特别是,您可以尝试nstart
做大一些。这保证了您的结果更稳定,因为LDA函数将使用不同的随机种子反复运行,然后返回最佳结果。不幸的是,增加到nstart
1000,会使算法的工作量增加1000倍(续)