七月NLP课程笔记(3)-LDA主题模型
这个感觉第一次看真是难懂,详细公式和说明见 http://blog.csdn.net/v_july_v/article/details/41209515
# 什么是主题模型
有一篇文章,属于科技/体育/娱乐主题? 输入:文章,输出:属于哪个主题分类
# 直观版解释
什么是“生成式模型”? 假设事先给定了这几个主题:Arts、Budgets、Children、Education,以一定的概率选取上述某个主题,再以一定的概率选取那个主题下的某个单词,不断的重复这两步,最终生成如下图所示的一篇文章(其中不同颜色的词语分别对应上图中不同主题下的词)。
而LDA要做的正好是反向的过程,即看到了这篇文章,要猜测它属于各个主题的概率。
# 什么是LDA
Latent Dirichlet Allocation 一种无监督的贝叶斯模型。 将文档集中每篇文档的主题按概率分布的形式给出。无监督学习,无需训练集,仅需要给定文档集及主题个数k。另一个优点是,对每个主题,均可以找出一些词语来描述它。 是一种词袋模型,词的先后顺序没有关系。
# LDA的核心公式
P(单词|文档) = P(单词|主题)* P(主题|文档)
左边是可以通过观测得到,右边需要通过训练无监督学习得到。
# LDA的学习过程
开始之前,随机给公式右边的两个概率分布,针对每个文档、主题、单词赋概率值。 1)对第s个文档的第i个单词,令其所属主题为第j个,则可以计算
Pj(wi|ds) = P(wi|tj) * P(tj|ds)
2)对这个文档的这个单词,所有可能属于的主题j进行枚举,计算得到Pj(wi|ds),最简单的思路是选取使此值最大的那个j,作为该单词i所属的主题。 3)如果某个单词i选择了一个与之前不同的主题,也就是说会影响到P(wi|tj)和P(tj|ds)的计算,则需要重新计算这两个值,然后重新计算Pj(wi|ds)……如此迭代
# 先验,后验和似然
举一个例子,三个门ABC,一个后面有奖品,假设你选中了B门,此时,主持人打开C门,后面没有奖品,请问你此时是否要换门? 关于这个问题有一些不同的思路 (1)普通频度学的角度,分两步来看待,B后面有奖品的概率是1/3,B后面没奖品(A或C中有奖品)的概率为2/3。主持人打开C后,如果仍坚持B,则总的中奖概率为
1/3*100% + 2/3*0 = 1/3
如果改换为A,则中奖的概率为
2/3*100% + 1/3*0 = 2/3
所以应该更换。 (2)贝叶斯学派的角度,主持人打开C门其实是提供了一些信息的,而上面的想法没有考虑这一点,主持人为什么要打开C而不是打开A? 由此来计算
P(B|打开C)= P(打开C|B)*P(B) / P(打开C)
设 P(打开C|B)=k
, 则S
上式继续写= k*1/3 / P(打开C)
= k/3 / (P(A)*P(打开C|A) + P(B)*P(打开C|B))
= k/3 / (1*1/3+k*1/3)
= k/k+1
2
3
4
同样算来,P(A|打开C) = 1/k+1
。 而K作为概率,一般情况下小于1,也就是说在打开C的情况下,更可能在A门后,所以要换门。
上面例子里,开始我们认为1/3就是先验,而主持人打开C提供了信息则是似然,经过似然修正了不够准确的先验,即为后验概率。
LDA的原理部分详见开头的博客文章,后续多看看。理解更深入一点再做补充。
# python中的处理
首先需要进行文本预处理,比如去除空值,去除无用的邮箱网址电话等信息,中文的话需要进行分词,此外还需要去除停用词等操作。
使用Gensim包来进行LDA模型的处理。
from gensim import corpora, models, similarities
import gensim
2
文本要处理成二维数组形式,外层是每个文档,内层是每个文档中切好的各个单词。 然后用词袋的方法,把每个单词,用字典中的数字index代替
dictionary = corpora.Dictionary(texts)
corpus = [dictionary.doc2bow(text) for text in texts]
2
例如,
corpus[13]
# output:表示下标13的文档词袋里有三个词,下标为36、505、508,各自出现了一次
[(36, 1), (505, 1), (508, 1)]
2
3
接下来建立模型:
lda = gensim.models.ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=20)
可以查看主题及其关键词:
lda.print_topics(num_topics=20, num_words=5)
可以查看某个下标的主题及其关键词:
lda.print_topic(10, topn=5)
进行预测时,仍按上述格式将文档处理成词袋模型(bow, bag of words)。
# 传入词袋,查看主题的可能性
lda.get_document_topics(bow)
# 传入一个单词id,查看其属于哪个主题的可能性大
lda.get_term_topics(word_id)
2
3
4