LDA主题模型

基本原理

LSA(Latent semantic analysis,隐性语义分析)、pLSA(Probabilistic latent semantic analysis,概率隐性语义分析)和 LDA(Latent Dirichlet allocation,隐狄利克雷分配)这三种模型都可以归类到话题模型(Topic model,或称为主题模型)中。相对于比较简单的向量空间模型,主题模型通过引入主题这个概念,更进一步地对文本进行语义层面上的理解。

LSA

LSA 模型就是对词-文档共现矩阵进行SVD,从而得到词和文档映射到抽象出的topic上的向量表示,之前的一篇博客稍微提到过一点。LSA 通过将词映射到topic上得到distributional representation(词的分布表示),进而缓解文档检索、文档相似度计算等任务中所面临的同义词(多词一义)问题:比如我搜索“Java 讲义”,如果系统只是用字符匹配来检索的话,是不会返回一篇出现了“Java 课件”但通篇没出现“讲义”这个词的文档的。所以说,单纯地从词-文档共现矩阵取出词向量表示和文档向量表示的向量空间模型,尽管利用了大规模文档集的统计信息,仍然是无法直接从“语义”这个层面上去理解文本的。但是 LSA 这种将词映射到topic上的向量表示,很难去应对一词多义问题:比如“Java”这个词既可能指编程语言,也可能指爪哇岛,即使这两种含义的“Java”都在文档集里出现过,得到的 LSA 模型也无法很好地区分。

pLSA

pLSA 模型是有向图模型,将主题作为隐变量,构建了一个简单的贝叶斯网,采用EM算法估计模型参数。相比于 LSA 略显“随意”的SVD,pLSA 的统计基础更为牢固。

相比于 LDA 模型里涉及先验分布,pLSA 模型相对简单:观测变量为文档 有没有做LDA主题分析的软件 lda主题分析原理_主题模型(文档集共 M 篇文档)、词 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_02(设词汇表共有 V 个互不相同的词),隐变量为主题 有没有做LDA主题分析的软件 lda主题分析原理_主题模型_03(共 K 个主题)。在给定文档集后,我们可以得到一个词-文档共现矩阵,每个元素 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_04 表示的是词 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_05 在文档 有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_06 中的词频。也就是说,pLSA 模型也是基于词-文档共现矩阵的,不考虑词序
pLSA 模型通过以下过程来生成文档(记号里全部省去了对参数的依赖):
(1) 以概率 有没有做LDA主题分析的软件 lda主题分析原理_Java_07 选择一篇文档 有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_06
(2) 以概率 有没有做LDA主题分析的软件 lda主题分析原理_Java_09 得到一个主题 有没有做LDA主题分析的软件 lda主题分析原理_主题模型_10
(3) 以概率 有没有做LDA主题分析的软件 lda主题分析原理_Java_11 生成一个词 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_05
概率图模型如下所示

有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_13


图里面的浅色节点代表不可观测的隐变量,方框是指变量重复(plate notation),内部方框表示的是文档 有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_06 的长度是 N,外部方框表示的是文档集共 M 篇文档。pLSA 模型的参数 有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_15 显而易见就是:有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_16 个 有没有做LDA主题分析的软件 lda主题分析原理_Java_09有没有做LDA主题分析的软件 lda主题分析原理_主题模型_18 个 有没有做LDA主题分析的软件 lda主题分析原理_Java_11有没有做LDA主题分析的软件 lda主题分析原理_Java_09 表征的是给定文档在各个主题下的分布情况,文档在全部主题上服从多项式分布(共 M 个);有没有做LDA主题分析的软件 lda主题分析原理_Java_11 则表征给定主题的词语分布情况,主题在全部词语上服从多项式分布(共 K 个)。

拿到贝叶斯网当然先要看看联合分布咯。这个贝叶斯网表达的是如下的联合分布:

有没有做LDA主题分析的软件 lda主题分析原理_主题模型_22

有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_23

假设有一篇文档为 有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_24 ,生成它的概率就是有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_25

我们看一下 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_26 的表达式。如果不考虑随机变量之间的条件独立性的话,有

有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_27

但是观察图模型中的 d 、z 、w 可以知道,它们三个是有向图模型里非常典型的 head-to-tail 的情况:当 z 已知时,d 和 w 条件独立,也就是

有没有做LDA主题分析的软件 lda主题分析原理_Java_28

进而有

有没有做LDA主题分析的软件 lda主题分析原理_Java_29

所以最终的联合分布表达式为

有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_30

这样的话,我们要做的事就是从文档集里估计出上面的参数。pLSA 是频率学派的方法,将模型参数看作具体值,而不是有先验的随机变量。所以,考虑最大化对数似然函数:

有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_31

第二项可以直接去掉,那么不妨直接记:

有没有做LDA主题分析的软件 lda主题分析原理_Java_32

参数估计:EM算法迭代求解

由于参数全部在求和号里被外层的log套住,所以很难直接求偏导数估计参数。到了这里,就轮到EM算法闪亮登场了。之前的一篇简单介绍EM的博客里解决的是这样的问题:观测变量 y ,隐变量 z ,参数 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_33 ,目标函数 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_34 (省略有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_33依赖),Q函数 有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_36 ,进而有 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_37

  1. E步,求期望
    那么,仿照上面的写法,对于 pLSA 模型来说,Q函数的形式为
    有没有做LDA主题分析的软件 lda主题分析原理_主题模型_38
    (1) 联合概率 有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_39 的求解:
    有没有做LDA主题分析的软件 lda主题分析原理_Java_40
    (2) 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_41 的求解:
    所谓的 有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_42 实际上就是上一步迭代的全部 有没有做LDA主题分析的软件 lda主题分析原理_Java_43 个 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_44有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_45 个 有没有做LDA主题分析的软件 lda主题分析原理_主题模型_46 。为了避免歧义,将时间步 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_47 迭代得到的参数值加一个下标 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_47
    有没有做LDA主题分析的软件 lda主题分析原理_主题模型_49
    基于以上两个结果,得到Q函数的形式为
    有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_50
    终于,在这个形式里面,除了 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_33(全部 有没有做LDA主题分析的软件 lda主题分析原理_Java_43 个 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_44有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_45 个 有没有做LDA主题分析的软件 lda主题分析原理_主题模型_46),已经全部为已知量。
  2. M步,求极大值
    剩下的工作就是有没有做LDA主题分析的软件 lda主题分析原理_主题模型_56
    问题将会被概括为如下的约束最优化问题: 目标函数:有没有做LDA主题分析的软件 lda主题分析原理_Java_57
    约束:有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_58有没有做LDA主题分析的软件 lda主题分析原理_主题模型_59
    使用Lagrange乘数法,得到Lagrange函数为
    有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_60
    令其对参数的偏导数等于零,得到 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_61 个方程,这些方程的解就是最优化问题的解:
    有没有做LDA主题分析的软件 lda主题分析原理_主题模型_62
    有没有做LDA主题分析的软件 lda主题分析原理_主题模型_63
    方程的解为
    有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_64
    有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_65
    注意到两个约束条件,即
    有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_66
    有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_67
    从中可求得 有没有做LDA主题分析的软件 lda主题分析原理_Java_68有没有做LDA主题分析的软件 lda主题分析原理_主题模型_69 ,所以方程的解为
    有没有做LDA主题分析的软件 lda主题分析原理_主题模型_70
    有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_71
    当模型参数全部估计好后,便得到了完整的 pLSA 模型。上面的迭代过程很明显是一个频数估计(极大似然估计)的形式,意义很明确。模型使用EM算法进行参数估计时往往都会推导出这样的结果,例如HMM。
LDA

我们来看看PLSA和LDA生成文档的方式。在PLSA中,生成文档的方式如下:

  1. 按照概率有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_72选择一篇文档有没有做LDA主题分析的软件 lda主题分析原理_Java_73
  2. 根据选择的文档有没有做LDA主题分析的软件 lda主题分析原理_Java_73,从从主题分布中按照概率有没有做LDA主题分析的软件 lda主题分析原理_Java_75选择一个隐含的主题类别有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_76
  3. 根据选择的主题有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_76, 从词分布中按照概率有没有做LDA主题分析的软件 lda主题分析原理_主题模型_78选择一个词有没有做LDA主题分析的软件 lda主题分析原理_Java_79

LDA 中,生成文档的过程如下:

  1. 按照先验概率有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_72选择一篇文档有没有做LDA主题分析的软件 lda主题分析原理_Java_73
  2. 从Dirichlet分布有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_82中取样生成文档有没有做LDA主题分析的软件 lda主题分析原理_Java_73的主题分布有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_84,主题分布有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_84由超参数为有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_82的Dirichlet分布生成
  3. 从主题的多项式分布有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_84中取样生成文档有没有做LDA主题分析的软件 lda主题分析原理_Java_73第 j 个词的主题有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_89
  4. 从Dirichlet分布有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_90中取样生成主题有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_89对应的词语分布有没有做LDA主题分析的软件 lda主题分析原理_主题模型_92,词语分布有没有做LDA主题分析的软件 lda主题分析原理_主题模型_92由参数为有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_90的Dirichlet分布生成
  5. 从词语的多项式分布有没有做LDA主题分析的软件 lda主题分析原理_主题模型_92中采样最终生成词语有没有做LDA主题分析的软件 lda主题分析原理_Java_96
    可以看出,LDA 在 PLSA 的基础上,为主题分布和词分布分别加了两个 Dirichlet 先验。
    我们来看一个例子,如图所示:

    上图中有三个主题,在PLSA中,我们会以固定的概率来抽取一个主题词,比如0.5的概率抽取教育这个主题词,然后根据抽取出来的主题词,找其对应的词分布,再根据词分布,抽取一个词汇。由此,可以看出PLSA中,主题分布和词分布都是唯一确定的。但是,在LDA中,主题分布和词分布是不确定的,LDA的作者们采用的是贝叶斯派的思想,认为它们应该服从一个分布,主题分布和词分布都是多项式分布,因为多项式分布和狄利克雷分布是共轭结构,在LDA中主题分布和词分布使用了Dirichlet分布作为它们的共轭先验分布。所以,也就有了一句广为流传的话 – LDA 就是 PLSA 的贝叶斯化版本。下面两张图片很好的体现了两者的区别:


    在PLSA和LDA的两篇论文中,使用了下面的图片来解释模型,它们也很好的对比了PLSA和LDA的不同之处。


    现在我们来详细讲解论文中的LDA模型,即上图。

有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_97, 这个过程表示在生成第m篇文档的时候,先从抽取了一个doc-topic骰子有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_98, 然后投掷这个骰子生成了文档中第n个词的topic编号有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_99;

有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_100, 这个过程表示,从K个topic-word骰子有没有做LDA主题分析的软件 lda主题分析原理_Java_101中,挑选编号为有没有做LDA主题分析的软件 lda主题分析原理_Java_102的骰子进行投掷,然后生成词汇有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_103;

在LDA中,也是采用词袋模型,M篇文档会对应M个独立Dirichlet-Multinomial共轭结构;K个topic会对应K个独立的Dirichlet-Multinomial共轭结构。
上面的LDA的处理过程是一篇文档一篇文档的过程来处理,并不是实际的处理过程。文档中每个词的生成都要抛两次骰子,第一次抛一个doc-topic骰子得到 topic, 第二次抛一个topic-word骰子得到 word,每次生成每篇文档中的一个词的时候这两次抛骰子的动作是紧邻轮换进行的。如果语料中一共有 N 个词,则上帝一共要抛 2N次骰子,轮换的抛doc-topic骰子和 topic-word骰子。但实际上有一些抛骰子的顺序是可以交换的,我们可以等价的调整2N次抛骰子的次序:前N次只抛doc-topic骰子得到语料中所有词的 topics,然后基于得到的每个词的 topic 编号,后N次只抛topic-word骰子生成 N 个word。此时,可以得到:
有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_104

Gibbs Sampling

根据上一小节中的联合概率分布有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_105, 我们可以使用Gibbs Sampling对其进行采样。
语料库有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_106中的第i个词我们记为有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_107, 其中i=(m,n)是一个二维下标,对应于第m篇文档的第n个词,用有没有做LDA主题分析的软件 lda主题分析原理_主题模型_108 表示去除下标为i的词。根据第二小节中的Gibbs Sampling 算法,我们需要求任一个坐标轴 i 对应的条件分布 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_109 。假设已经观测到的词 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_110, 则由贝叶斯法则,我们容易得到:
有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_111
由于有没有做LDA主题分析的软件 lda主题分析原理_Java_112 只涉及到第 m 篇文档和第k个 topic,所以上式的条件概率计算中, 实际上也只会涉及到与之相关的两个Dirichlet-Multinomial 共轭结构,其它的 M+K−2 个 Dirichlet-Multinomial 共轭结构和有没有做LDA主题分析的软件 lda主题分析原理_Java_112是独立的。去掉一个词汇,并不会改变M + K 个Dirichlet-Multinomial共轭结构,只是某些地方的计数减少而已。于是有:
有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_114
下面进行本篇文章最终的核心数学公式推导:
有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_115
最终得到的 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_116 就是对应的两个 Dirichlet 后验分布在贝叶斯框架下的参数估计。借助于前面介绍的Dirichlet 参数估计的公式 ,有:
有没有做LDA主题分析的软件 lda主题分析原理_Java_117
最终,我们得到LDA 模型的 Gibbs Sampling 公式为:
有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_118

LDA Training

根据上一小节中的公式,我们的目标有两个:

  1. 估计模型中的参数 有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_119有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_120;
  2. 对于新来的一篇文档,我们能够计算这篇文档的 topic 分布有没有做LDA主题分析的软件 lda主题分析原理_Java_121
    训练的过程:
  3. 对语料库中的每篇文档中的每个词汇有没有做LDA主题分析的软件 lda主题分析原理_主题模型_122,随机的赋予一个topic编号z
  4. 重新扫描语料库,对每个词有没有做LDA主题分析的软件 lda主题分析原理_主题模型_122,使用Gibbs Sampling公式对其采样,求出它的topic,在语料中更新
  5. 重复步骤2,直到Gibbs Sampling收敛
  6. 统计语料库的topic-word共现频率矩阵,该矩阵就是LDA的模型;
    根据这个topic-word频率矩阵,我们可以计算每一个p(word|topic)概率,从而算出模型参数有没有做LDA主题分析的软件 lda主题分析原理_有没有做LDA主题分析的软件_119, 这就是那 K 个 topic-word 骰子。而语料库中的文档对应的骰子参数 有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_120 在以上训练过程中也是可以计算出来的,只要在 Gibbs Sampling 收敛之后,统计每篇文档中的 topic 的频率分布,我们就可以计算每一个 p(topic|doc) 概率,于是就可以计算出每一个有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_126。由于参数有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_126
LDA Inference

有了 LDA 的模型,对于新来的文档 doc, 我们只要认为 Gibbs Sampling 公式中的 有没有做LDA主题分析的软件 lda主题分析原理_主题模型_128 部分是稳定不变的,是由训练语料得到的模型提供的,所以采样过程中我们只要估计该文档的 topic 分布有没有做LDA主题分析的软件 lda主题分析原理_向量空间模型_15就好了. 具体算法如下:

  1. 对当前文档中的每个单词有没有做LDA主题分析的软件 lda主题分析原理_主题模型_122, 随机初始化一个topic编号z;
  2. 使用Gibbs Sampling公式,对每个词有没有做LDA主题分析的软件 lda主题分析原理_主题模型_122, 重新采样其topic;
  3. 重复以上过程,知道Gibbs Sampling收敛;
  4. 统计文档中的topic分布,该分布就是有没有做LDA主题分析的软件 lda主题分析原理_Java_121
    Tips

懂 LDA 的面试官通常会询问求职者,LDA 中主题数目如何确定?

在 LDA 中,主题的数目没有一个固定的最优解。模型训练时,需要事先设置主题数,训练人员需要根据训练出来的结果,手动调参,有优化主题数目,进而优化文本分类结果。

LDA实践

修改之前 SVM与贝叶斯分类中提取特征的部分即可

from scipy.sparse import hstack
def tf_LDA_deal_cnews(input_file_name,out_file_name):
    bunch=_read_bunch(input_file_name)#读取数据
    stop_words=get_stop_words()#得到停用词
    #实例化bunch对象
    #tmd(权重列表)
    #vocabulary(词典索引)
    space_bunch=Bunch(targets=bunch.targets,filename=bunch.filenames,labels=bunch.labels,tmd=[],vocabulary={})
    #使用特征提取函数TfidfVectorizer初始化向量空间模型
    tf_vector=TfidfVectorizer(stop_words=stop_words,sublinear_tf=True,max_df=0.5,max_features=10000)#提取函数的初始化,啥数据都没有处理。选择能代表新闻特征、独一无二的词汇,词频大于50%的就被过滤掉???如果过大、过小会如何?
    
    tf_features=tf_vector.fit_transform(bunch.contents)
    ## lda
    lda = LatentDirichletAllocation(n_topics=10, max_iter=5,
                                learning_method='online',
                                learning_offset=50.,
                                random_state=0)
    cnt_vector =CountVectorizer(stop_words=stop_words,max_df=0.5,max_features=10000)
    cntTf = cnt_vector.fit_transform(bunch.contents)
    LDA_features = lda.fit_transform(cntTf)
    
    
    
    print(tf_features.shape)
    print(LDA_features.shape)
    space_bunch.tmd= hstack((tf_features,LDA_features))
    print(space_bunch.tmd.shape)
    space_bunch.vocabulary=tf_vector.vocabulary_#词典索引,统计词频
    '''
    print(space_bunch.vocabulary)输出格式如下:
    {'黄蜂': 834, 'vs': 38, '湖人': 557, '首发': 820, '科比': 609, '带伤': 352, '保罗': 156,
    '''
    _write_bunch(space_bunch,out_file_name)#写入文件