潜在 Dirichlet 分配(LDA)是一种生成模型,它生成一系列主题。每个主题由一个词分布表示。假设每个主题由其前40个词来表示。
给定一个新文档,如何确定哪些主题构成了这个新文档,而不需要重新运行LDA?换句话说,如何使用估计的主题来推断一个新的未见文档的主题?
更新:
在估计过程中,我们执行以下操作(为了简化,我忽略了超参数)
for(int iter=0;iter<1000;iter++){ for(int token=0;token<numTokens;token++){ double[] values=new double[numTopics]; double pz=0.0d; for(int topic=0;topic<numTopics;topic++){ probabilityOfWordGivenTopic= topicCount[topic][word[token]] / numTokenInTopic[topic]; probabilityOfTopicGivenDocument= docCount[doc[token]][topic] / docLength[doc[token]]; pz= probabilityOfWordGivenTopic * probabilityOfTopicGivenDocument; values[topic]=pz; total+=pz; } }}
谢谢你。
回答:
在推断步骤中,你基本上需要为新文档的词分配主题。
对于已见的词,使用你的估计模型来分配概率。以你的例子来说,既然你有40个主题,你已经在LDA估计过程中学习了词-主题分布(phi矩阵)。现在,对于在训练期间见过的词,比如w,取这个矩阵的第w列向量,这个向量的大小为40。这个向量为你提供了词w属于每个主题的类成员概率。例如,这个向量是(.02, .01, …. .004),这意味着P(w|t_1)=.02,等等。
在新文档中,每当你看到这个词w时,从这个分布中抽样并为其分配一个主题。显然,这个词w更有可能被分配到它真正的(技术上讲,是从估计过程中学习到的)主题类别中。
对于OOV词(即在训练期间未见过的词),一种常见的做法是使用均匀分布,即在你的例子中使用1/40的概率来为其分配主题。
编辑
以下是从JGibbsLDA提取的代码片段:
for (int m = 0; m < newModel.M; ++m){ for (int n = 0; n < newModel.data.docs[m].length; n++){ // (newz_i = newz[m][n] // sample from p(z_i|z_-1,w) int topic = infSampling(m, n); newModel.z[m].set(n, topic); } }//end foreach new doc
推断抽样的主要步骤是为词w分配概率。请注意,这个概率部分依赖于估计模型的概率(代码中的trnModel.nw[w][k]),部分依赖于新分配的概率(newModel.nw[_w][k])。对于OOV词,trnModel.nw[w][k]被设置为1/K。这个概率不依赖于P(w|d)。相反,P(w|d)只是在通过Gibbs抽样完成主题分配后计算的后验概率。
// do multinomial sampling via cummulative method for (int k = 0; k < newModel.K; k++){ newModel.p[k] = (trnModel.nw[w][k] + newModel.nw[_w][k] + newModel.beta)/(trnModel.nwsum[k] + newModel.nwsum[k] + Vbeta) * (newModel.nd[m][k] + newModel.alpha)/(newModel.ndsum[m] + Kalpha); }