LDA(Latent Dirichlet Allocation)主题模型

来源:互联网 发布:大数据平台是什么意思 编辑:程序博客网 时间:2024/05/21 07:58

LDA于2003年由 David Blei, Andrew Ng和 Michael I. Jordan提出,因为模型的简单和有效,掀起了主题模型研究的波浪。虽然说LDA模型简单,但是它的数学推导却不是那么平易近人,一般初学者会深陷数学细节推导中不能自拔。于是牛人们看不下去了,纷纷站出来发表了各种教程。国内方面rickjin有著名的《LDA数学八卦》,国外的Gregor Heinrich有著名的《Parameter estimation for text analysis》。其实有了这两篇互补的通俗教程,大家沉住心看个4、5遍,基本就可以明白LDA为什么是简单的了。那么其实也没我什么事了,然而心中总有一种被大牛点播的豁然开朗的快感,实在是不吐不快啊。

什么是主题

因为LDA是一种主题模型,那么首先必须明确知道LDA是怎么看待主题的。对于一篇新闻报道,我们看到里面讲了昨天NBA篮球比赛,那么用大腿想都知道它的主题是关于体育的。为什么我们大腿会那么聪明呢?这时大腿会回答因为里面出现了“科比”、“湖人”等等关键词。那么好了,我们可以定义主题是一种关键词集合,如果另外一篇文章出现这些关键词,我们可以直接判断他属于某种主题。但是,亲爱的读者请你想想,这样定义主题有什么弊端呢?按照这种定义,我们会很容易给出这样的条件:一旦文章出现了一个球星的名字,那么那篇文章的主题就是体育。可能你马上会骂我在瞎说,然后反驳说不一定,文章确实有球星的名字,但是里面全部在讲球星的性丑闻,和篮球没半毛钱关系,此时主题是娱乐还差不多。所以一个词不能硬性地扣一个主题的帽子,如果说一篇文章出现了某个球星的名字,我们只能说有很大概率他属于体育的主题,但也有小概率属于娱乐的主题。于是就会有这种现象:同一个词,在不同的主题背景下,它出现的概率是不同的。并且我们都可以基本确定,一个词不能代表一种主题,那么到底什么才是主题呢?耐不住性子的同学会说,既然一个词代表不了一种主题,那我就把所有词都用来代表一种主题,然后你自己去慢慢意会。没错,这样确实是一种完全的方式,主题本来就蕴含在所有词之中,这样确实是最保险的做法,但是你会发现这样等于什么都没做。老奸巨猾的LDA也是这么想的,但他狡猾之处在于它用非常圆滑手段地将主题用所有词汇表达出来。怎么个圆滑法呢?手段便是概率。LDA认为天下所有文章都是用基本的词汇组合而成,此时假设有词库V={v1,v2,....,vn},那么如何表达主题k呢?LDA说通过词汇的概率分布来反映主题!多么狡猾的家伙。我们举个例子来说明LDA的观点。假设有词库

{}
假设有两个主题
{}
LDA说体育这个主题就是:
{:0.3:0.3:0.3:0.03:0.03:0.04}
(数字代表某个词的出现概率),而政治这个主题就是:
{:0.03:0.03:0.04:0.3:0.3:0.3}
LDA就是这样说明什么是主题的,竟说得我无言以对,细思之下也是非常合理。

文章在讲什么

给你一篇文章读,然后请你简要概括文章在讲什么,你可能会这样回答:80%在讲政治的话题,剩下15%在讲娱乐,其余都是废话。这里大概可以提炼出三种主题:政治,娱乐,废话。也就是说,对于某一篇文章,很有可能里面不止在讲一种主题,而是几种主题混在一起的。读者可能会问,LDA是一种可以从文档中提炼主题模型,那他在建模的时候有没有考虑这种情形啊,他会不会忘记考虑了。那您就大可放心了,深谋远虑的LDA早就注意到这些了。LDA认为,文章和主题之间并不一定是一一对应的,也就是说,文章可以有多个主题,一个主题可以在多篇文章之中。这种说法,相信读者只能点头称是。假设现在有K个主题,有M篇文章,那么每篇文章里面不同主题的组成比例应该是怎样的呢?由于上一小节我们知道不能硬性的将某个词套上某个主题,那么这里我们当然不能讲某个主题套在某个文章中,也就是有这样的现象:同一个主题,在不同的文章中,他出现的比例(概率)是不同的,看到这里,读者可能已经发现,文档和主题之间的关系和主题和词汇的关系是多么惊人的类似!LDA先人一步地将这一发现说出来,它说,上一节我们巧妙地用词汇的分布来表达主题,那么这一次也不例外,我们巧妙地用主题的分布来表达文章!同样,我们举个例子来说明一下,假设现在有两篇文章:

有三个主题
那么
:[,,,,,....,,]
:[,,,,,....,,]
也就是说,一篇文章在讲什么,通过不同的主题比例就可以概括得出。

文章是如何生成的

在前面两小节中,LDA认为,每个主题会对应一个词汇分布,而每个文档会对应一个主题分布,那么一篇文章是如何被写出来的呢?读者可能会说靠灵感+词汇。LDA脸一沉,感觉完蛋,灵感是什么玩意?LDA苦思冥想,最后没办法,想了个馊主意,它说

=
这也是没办法中的办法。因此对于某一篇文章的生产过程是这样的:

  1. 确定主题和词汇的分布
  2. 确定文章和主题的分布
  3. 随机确定该文章的词汇个数N
  4. 如果当前生成的词汇个数小于N执行第5步,否则执行第6步
  5. 由文档和主题分布随机生成一个主题,通过该主题由主题和词汇分布随机生成一个词,继续执行第4步
  6. 文章生成结束

只要确定好两个分布(主题与词汇分布,文章与主题分布),然后随机生成文章各个主题比例,再根据各个主题随机生成词,词与词之间的顺序关系被彻底忽略了,这就是LDA眼中世间所有文章的生成过程!聪明的读者肯定觉得LDA完全就是一个骗子,这样认为文章的生成未免也太过天真了吧。然而事实就是如此,这也是为什么说LDA是一个很简单的模型。幸好我们这是用LDA来做主题分析,而不是用来生成文章,而从上上节的分析我们知道,主题其实就是一种词汇分布,这里并不涉及到词与词的顺序关系,所以LDA这种BOW(bag of words)的模型也是有它的简便和实用之处的。

LDA数学分析

上一小节,我们忽略了一个问题,就是如何确定主题和词汇分布,还有文档与词汇的分布,但是要搞明白这个问题,就避免不了一些数学分析了。再次强烈推荐rickjin的《LDA数学八卦》还有Gregor Heinrich有著名的《Parameter estimation for text analysis》。此处我只做一些关键扼要的理论推导 :-)

多项式分布

回忆一下概率论学的东西,假设一个硬币正面朝上的概率是p,如果重复抛n次硬币,正面朝上的次数为k的概率分布就是二项分布,也就是

Cknpk(1p)nk
如果抛nk个不同的硬币,假设每个硬币正面朝上的概率分别是p1,p2,....,pk,那么抛n次之后,各个硬币正面朝上的次数n1,n2,....,nk的概率分布就是多项式分布了,记为
n!n1!n2!,....,nk!p1n1p2n2....pknk
LDA出来说话了:主题和词汇的分布就是多项式分布!因为一个主题里面不同词汇出现的概率不同,如果只有1个词汇,那么它就是二项分布,但是词汇不可能只有1个,所以它理所当然就是符合多项式分布。这是挺合理的假设,反正我们现在研究的内容是为词汇按主题给出不同的概率分布,其实也就是给出不同词汇在不同主题下的出现比例,我们并不关系词汇之间的顺序关系,所以多项式分布已经很好地刻画出这种关系了。LDA又说:文章和主题之间的分布也是符合多项式分布!因为一篇文章要确定不同主题的出现概率,和主题要确定每个词汇的出现概率是完全可以类比的!思考一下我们也接受了LDA的说法,接下来我们介绍一些记号:

  • V代表我们字典的词汇个数
  • K代表主题的个数
  • M代表文章的个数
  • ϕk代表第k个主题的多项式分布参数,长度为V,那么Φ是一个KV的矩阵,每一行代表一个主题的多项式分布参数
  • θm代表第m篇文章的多项式分布参数,长度为K,那么Θ是一个MK的矩阵,没一行代表一篇文章的多项式分布参数
  • Nm代表第m篇文章的长度
  • zm,n代表第m篇文章第n个词由哪个主题产生的
  • wm,n代表第m篇文章第n个词

那么对于第k个主题,令w代表一次实验产生的词,那么它就服从:

wMulti(w|ϕk)
对于第m篇文章,令z代表一次实验产生的主题,那么它就服从:
zMulti(z|θm)
然后为了产生第m篇文章,只要简单的按顺序利用Multi(z|θm)随机生成zm,1,zm,2,zm,3,...,zm,Nm,然后对号入座,再利用Multi(w|ϕzm,n),生成wm,1,wm,2,wm,3,...,wm,Nm即可。

Dirichlet分布

忘记告诉大家,LDA属于江湖中的贝叶斯学派,在贝叶斯学派眼中,像上面提到的ϕkθm都是随机变量,随机变量怎么可以没有先验概率分布呢?这岂不是贻笑大方吗?所以LDA整理了一下衣领,马上提出了他们的先验概率分布:

ϕ⃗ Dirichlet(α⃗ )
θ⃗ Dirichlet(β⃗ )
为什么LDA要说它的先验分布是Dirichlet分布呢?其中最大的原因是因为多项式分布和Dirichlet分布是一对共轭分布,共轭分布有什么好处呢?好处在于计算后验概率有极大的便利!说到底是LDA看中它计算方便。增加了先验概率分布,那么在确定文章与主题分布还有主题与词汇分布的时候,就由先验概率分布先随机生成确定多项式分布的参数。用一个联合概率分布来描述第m篇文章生成过程:
p(zm,wm,θm,Φ|α⃗ ,β⃗ )=nNmp(wm,n|ϕzm,n)p(zm,n|θm)p(θm|α⃗ )p(Φ|β⃗ )

Gibbs 采样算法

实际应用中,我们通常是有一堆文章,然后要我们去自动提取主题,或者通过现有的文章训练出LDA模型,然后预测新的文章所属主题分类。也就是我们的兴趣点在于求出ΘΦ的后验概率分布。虽然LDA的模型思想很简单,但是要精确求出参数的后验概率分布却是不可行的,只能通过近似的方式求解。幸好人们发现了很多方法来求解,其中比较简单的就是Gibbs采样,Gibbs采样算法实现起来比较简单,对于LDA,它必须先解决一个问题:

p(zm,i|zm,¬i,wm)
其中zm={zm,ik,zm,¬i}zm,¬i代表第m篇文章里面去除主题zm,i的其他所有主题。其具体推导一开始推荐的文章都有详尽严格的过程,这里实在没有必要在赘述,直接给出结果(为了表达方便,这里去除下标m):
p(zi=k|z¬i,w⃗ )=p(w⃗ ,z⃗ )p(w⃗ ,z¬i)=p(w⃗ |z⃗ )p(w¬i|z¬i)p(wi)p(z⃗ )p(z¬i)p(w⃗ |z⃗ )p(w¬i|z¬i)p(z⃗ )p(z¬i)n(t)k,¬i+βtVt=1n(t)k,¬i+βtn(k)m,¬i+αkKk=1n(k)m,¬i+αkn(t)k,¬i+βtVt=1n(t)k,¬i+βt(n(k)m,¬i+αk)
其中n(t)k代表第m篇文章中词汇t属于主题k出现的次数,n(t)k,¬i代表除去其中zi的剩余个数,也就是说
n(t)k,¬i=n(t)k1
类似的,n(k)m代表第m篇文章中主题k出现的次数,n(k)m,¬i代表除去其中zi的剩余个数,也就是说
n(k)m,¬i=n(k)m1
所以计算p(zi|z¬i,w⃗ )变成简单地在计数的问题。通过Gibbs采样算法后,最后的模型参数可以这样得出:
ϕk,t=n(t)k+βtVt=1n(t)k+βt
θm,k=n(k)m+αkKk=1n(k)m+αk

判断新文章的主题分布

由上一小节,我们可以通过大量文章求解出LDA这个模型,那么对于一篇新的文章,如何计算它的主题分布呢?一个方式是将文章加入到原来的训练集合里面{z~,z⃗ ;w~,w⃗ },然后得到它的采样条件概率为:

p(zi~=k|z~¬i,z⃗ ,w⃗ ,w~)n(t)k+n~(t)k,¬i+βtVt=1n(t)k+n~(t)k,¬i+βtn(k)m~,¬i+αkKk=1n(k)m~,¬i+αk
再重新跑一次Gibbs采样,然后得到它的分布。实际上这种做法确实是最优的,但是太慢了,怎么办呢?因为新来的文章,它的词汇是固定的,我们上节已经求出ϕk,t,也就是词汇和主题的分布已经是确定的,我们没必要再浪费计算力了,也就是我们认为对一篇新文章,它已经难以撼动之前成千上万文章的统计结果了,也就是说:
n(t)k+n~(t)k,¬i+βtVt=1n(t)k+n~(t)k,¬i+βtn(t)k+βtVt=1n(t)k+βt
所以我们新的条件采样概率变成了:
p(zi~=k|w~i=t,z~¬i,z⃗ ,w⃗ ,w~¬i)ϕk,t(n(k)m~,¬i+αk)
然后我们又可以开动Gibbs采样发动机,得到最终的分布结果:
θm~,k=n(k)m~+αkKk=1n(k)m~+αk

LDA的Gibbs采样实现

对于程序员来说,看惯代码,没有代码有点无所适从,有没有简单LDA的实现漂亮代码呢?答案是有的,LingPipe里面的LatentDirichletAllocation这个类,完整地按照Gregor Heinrich有著名的《Parameter estimation for text analysis》介绍的算法实现了,代码非常简单,并且可读性极高,建议抓来一看,必然大有毗益。此处我们贴出Gregor中提供的伪代码,以供查看:

  • 初始化阶段,出乎意料的简单,只要初始化4个统计量,分别是:
    • 文档m对应主题k的计数: nkm
    • 文档m的词汇数:nm
    • 主题k对应的词汇为t的计数:ntk
    • 主题k的词汇数:nk
  • nkm,nm,ntk,nk内存清0,然后根据以下程序随机初始化值:
    • 遍历每一个文档m[1,M]
      • 遍历每个词汇n[1,Nm]
        • 从多项式分布Mult(1/K)得到一个采样值:zmn=k
        • nkm=nkm+1
        • nm=nm+1
        • ntk=ntk+1
        • nk=nk+1
  • Gibbs采样过程,以下是一个采样周期的执行过程:
    • 遍历每一个文档m[1,M]
      • 遍历每个词汇n[1,Nm]
        • 对于当前的wm,n的主题k对应的词汇t执行:
          • nkm=nkm1
          • nm=nm1
          • ntk=ntk1
          • nk=nk1
          • 根据p(zi=k|z¬i,w⃗ )获得一个采样值:k^=zm,n并执行:
            • nk^m=nk^m+1
            • nm=nm+1
            • ntk^=ntk^+1
            • nk^=nk^+1

难以置信的简单,一般在收敛之前,需要跑一定数量的采样次数让采样程序大致收敛,这个次数一般称为:burnin period。我们希望从采样程序中获得独立的样本,但是显然以上的采样过程明显依赖上一个采样结果,那么我们可以在上一次采样后,先抛弃一定数量的采样结果,再获得一个采样结果,这样可以大致做到样本独立,这样真正采样的时候,总有一定的滞后次数,这样的样本与样本的间隔称为:SampleLag。

LDA为什么有效

如果您反复读了前面反复强调的两篇LDA科普大作,并清楚了解它的实现细节,相信另一个问题会慢慢萦绕在心中——为什么LDA能够work?LDA为什么比pLSA强?强在何处?
Quora上面有一个相对直观的解释,我大概总结一下,由于LDA用Dirichlet作为Prior分布,而作为Prior的Dirichlet在其分布参数α⃗ 取很小的时候(一般αK/50, β取值0.01),可以使得其采样的多项式参数变得稀疏。LDA有两对稀疏对抗,主题与文档的稀疏性和主题与词汇的稀疏性之间的对抗,而LDA会从数据中学习到一个权衡结果。为什么Dirichlet会有稀疏性质呢?可以参照以这篇:
《Notes on Multinomial sparsity and the Dirichlet concentration parameter α》
这篇note提到的Dirichlet其实可以看成几个Gamma分布变换而来,具体变换证明可以参照Quora另一个解答:Construction of Dirichlet distribution with Gamma distribution。另一个好处是,多了先验分布的模型比pLSA更加健壮,不容易导致overfiting,如果看回上面推导Gibbs Sampling的公式,Dirichlet其实起到一种Smooth的效果。可以再参考Kevin Gimpel写的《Modeling Topics》,对于几种常见基础的主题模型的对比,也可以解除不少困惑。

参考文献

  • 《LDA数学八卦》
  • 《Parameter estimation for text analysis》
  • 《gibbs sampling for the uninitiated》
  • 《text mining and topic models》
  • 《A Theoretical and Practical Implementation Tutorial on Topic Modeling and Gibbs Sampling》
  • 《Probabilistic Latent Semantic Analysis》
  • LingPipe
  • 《Modeling Topics》
  • 《Notes on Multinomial sparsity and the Dirichlet concentration parameter α》
  • Why does LDA works?
  • Construction of Dirichlet distribution with Gamma distribution
1 0