LDA处理文本

LDA处理文本

LDA简单介绍

LDA是一种文档主题生成模型,也称为一个三层贝叶斯概率模型,包含词、主题和文档三层结构。我们认为一篇文章的每个词都是通过以一定概率选择了某个主题,并从这个主题中以一定概率选择某个词语。文档到主题服从多项式分布,主题到词服从多项式分布。
在这里插入图片描述
LDA是一种非监督机器学习技术,可以用来识别大规模文档集或语料库中潜藏的主题信息。它采用了词袋(bag of words)的方法,这种方法将每一篇文档视为一个词频向量,从而将文本信息转化为易于建模的数字信息。但是词袋方法没有考虑词与词之间的顺序,这简化了问题的复杂性,同时也为模型的改进提供了契机。每一篇文档代表了一些主题所构成的一个概率分布,而每一个主题又代表了很多单词所构成的一个概率分布。

LDA生成过程

对于语料库中的每篇文档,LDA定义了如下生成过程:
(1)对每一篇文档,从主题分布中抽取一个主题;
(2)从上述被抽到的主题所对应的单词分布中抽取一个单词;
(3)重复上述过程直至遍历文档中的每一个单词。

LDA整体流程

文档集合D,主题集合T
D中每个文档d看作一个单词序列<w1, w2, …… ,wn>,wi表示第i个单词,设d有n个单词。(LDA里面称之为wordbag,实际上每个单词的出现位置对LDA算法无影响)
文档集合D中的所有单词组成一个大集合VOCABULARY(简称VOC)。

LDA以文档集合D作为输入,希望训练出两个结果向量(设聚成k个topic,VOC中共包含m个词)。

对每个D中的文档d,对应到不同Topic的概率θd<pt1,…,ptk>,其中,pti表示d对应T中第i个topic的概率。计算方法是直观的,pti=nti/n,其中nti表示d中对应第i个topic的词的数目,n是d中所有词的总数。

对每个T中的topic,生成不同单词的概率φt<pw1,…,pwm>,其中,pwi表示t生成VOC中第i个单词的概率。计算方法同样很直观,pwi=Nwi/N,其中Nwi表示对应到topict的VOC中第i个单词的数目,N表示所有对应到topict的单词总数。

LDA的核心公式如下:

p(w|d)=p(w|t)*p(t|d)

直观的看这个公式,就是以Topic作为中间层,可以通过当前的θd和φt给出了文档d中出现单词w的概率。其中p(t|d)利用θd计算得到,p(w|t)利用φt计算得到。

实际上,利用当前的θd和φt,我们可以为一个文档中的一个单词计算它对应任意一个Topic时的p(w|d),然后根据这些结果来更新这个词应该对应的topic。然后,如果这个更新改变了这个单词所对应的Topic,就会反过来影响θd和φt。

LDA操作过程

上手过程

from gensim import corpora, models
import jieba.posseg as jp, jieba
# 文本集
texts = [
    '美国教练坦言,没输给中国女排,是输给了郎平',
    '美国无缘四强,听听主教练的评价',
    '中国女排晋级世锦赛四强,全面解析主教练郎平的执教艺术',
    '为什么越来越多的人买MPV,而放弃SUV?跑一趟长途就知道了',
    '跑了长途才知道,SUV和轿车之间的差距',
    '家用的轿车买什么好']
jieba.add_word('四强', 9,  'n')
flags = ('n', 'nr', 'ns', 'nt', 'eng', 'v', 'd')  # 词性
stopwords = ('没', '就', '知道', '是', '才', '听听', '坦言', '全面', '越来越', '评价', '放弃', '人')  # 停用词

分词

# 分词
words_list = []
for text in texts:
    words = [w.word for w in jp.cut(text) if w.flag in flags and w.word not in stopwords]
    words_list.append(words)
print(words_list)
>>[['美国', '输给', '中国女排', '输给', '郎平'], ['美国', '无缘', '四强', '主教练'], ['中国女排', '晋级', '世锦赛', '四强', '主教练', '郎平', '执教', '艺术'], ['买', 'MPV', 'SUV', '跑', '长途'], ['跑', '长途', 'SUV', '轿车', '差距'], ['家用', '轿车', '买']]

构造词典

# 构造词典
dictionary = corpora.Dictionary(words_list)
# 基于词典,使【词】→【稀疏向量】,并将向量放入列表,形成【稀疏向量集】
corpus = [dictionary.doc2bow(words) for words in words_list]
print(dictionary.token2id)
>>{'中国女排': 0, '美国': 1, '输给': 2, '郎平': 3, '主教练': 4, '四强': 5, '无缘': 6, '世锦赛': 7, '执教': 8, '晋级': 9, '艺术': 10, 'MPV': 11, 'SUV': 12, '买': 13, '跑': 14, '长途': 15, '差距': 16, '轿车': 17, '家用': 18}
print(corpus)
>>[[(0, 1), (1, 1), (2, 2), (3, 1)], [(1, 1), (4, 1), (5, 1), (6, 1)], [(0, 1), (3, 1), (4, 1), (5, 1), (7, 1), (8, 1), (9, 1), (10, 1)], [(11, 1), (12, 1), (13, 1), (14, 1), (15, 1)], [(12, 1), (14, 1), (15, 1), (16, 1), (17, 1)], [(13, 1), (17, 1), (18, 1)]]

LDA模型

# LDA模型,num_topics设置主题的个数
lda = models.ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=2)
print(lda)
LdaModel(num_terms=19, num_topics=2, decay=0.5, chunksize=2000)

打印主题

# 打印所有主题,每个主题显示5个词
for topic in lda.print_topics(num_words=5):
    print(topic)
>>(0, '0.082*"郎平" + 0.080*"中国女排" + 0.077*"输给" + 0.075*"四强" + 0.075*"主教练"')
(1, '0.100*"买" + 0.086*"轿车" + 0.086*"长途" + 0.082*"跑" + 0.080*"SUV"')

doc2bow函数

在这里插入图片描述

主题推断

for e, values in enumerate(lda.inference(corpus)[0]):
    print(texts[e])
    for ee, value in enumerate(values):
        print('\t主题%d推断值%.2f' % (ee, value))
>>
美国教练坦言,没输给中国女排,是输给了郎平
	主题0推断值5.45
	主题1推断值0.55
美国无缘四强,听听主教练的评价
	主题0推断值4.39
	主题1推断值0.61
中国女排晋级世锦赛四强,全面解析主教练郎平的执教艺术
	主题0推断值8.45
	主题1推断值0.55
为什么越来越多的人买MPV,而放弃SUV?跑一趟长途就知道了
	主题0推断值0.58
	主题1推断值5.42
跑了长途才知道,SUV和轿车之间的差距
	主题0推断值0.66
	主题1推断值5.34
家用的轿车买什么好
	主题0推断值0.56
	主题1推断值3.44
newtext = '中国女排将在郎平的率领下向世界女排三大赛的三连冠发起冲击'
bow = dictionary.doc2bow([word.word for word in jp.cut(newtext) if word.flag in flags and word.word not in stopwords])
ndarray = lda.inference([bow])[0]
print(newtext)
for e, value in enumerate(ndarray[0]):
    print('\t主题%d推断值%.2f' % (e, value))
中国女排将在郎平的率领下向世界女排三大赛的三连冠发起冲击
	主题0推断值2.47
	主题1推断值0.53

词和主题的关系

单个词和主题的关系
#单个词和主题的关系
word_id = dictionary.doc2idx(['长途'])[0]
for i in lda.get_term_topics(word_id):
    print('【长途】与【主题%d】的关系值:%.2f%%' % (i[0], i[1]*100))
>>【长途】与【主题0】的关系值:2.94%
【长途】与【主题1】的关系值:6.39%
全部词和主题的关系
#全部词与主题的关系(minimum_probability设置概率阈值)
for word, word_id in dictionary.token2id.items():
    print(word, lda.get_term_topics(word_id, minimum_probability=1e-8))
>>
中国女排 [(0, 0.06442815), (1, 0.014080671)]
美国 [(0, 0.05490445), (1, 0.026663143)]
输给 [(0, 0.061345495), (1, 0.017999072)]
郎平 [(0, 0.06625165), (1, 0.011863526)]
主教练 [(0, 0.05975414), (1, 0.020088725)]
四强 [(0, 0.059979346), (1, 0.019790726)]
无缘 [(0, 0.025368767), (1, 0.020737274)]
世锦赛 [(0, 0.03366431), (1, 0.01001923)]
执教 [(0, 0.034435168), (1, 0.009128721)]
晋级 [(0, 0.03374774), (1, 0.009921753)]
艺术 [(0, 0.033762135), (1, 0.0099049155)]
MPV [(0, 0.008605375), (1, 0.046699677)]
SUV [(0, 0.033518188), (1, 0.057664976)][(0, 0.020289622), (1, 0.07797615)][(0, 0.031679653), (1, 0.060431425)]
长途 [(0, 0.029418245), (1, 0.0638557)]
差距 [(0, 0.024054041), (1, 0.022578618)]
轿车 [(0, 0.029404663), (1, 0.063876286)]
家用 [(0, 0.010735649), (1, 0.043013442)]
每个主题,所有词概率和为1
# 对于每个主题,所有词对应的概率,求和=1
print(lda.show_topic(0, 9999))
print('概率总和', sum(i[1] for i in lda.show_topic(0, 9999)))
[('郎平', 0.081504114), ('中国女排', 0.07969216), ('输给', 0.07662659), ('四强', 0.07526694), ('主教练', 0.07504273), ('美国', 0.07020949), ('执教', 0.049633656), ('艺术', 0.04894922), ('晋级', 0.048934568), ('世锦赛', 0.04884967), ('SUV', 0.04870095), ('跑', 0.04682636), ('长途', 0.044511233), ('轿车', 0.044497292), ('无缘', 0.040333282), ('差距', 0.038965795), ('买', 0.035010517), ('家用', 0.024490705), ('MPV', 0.02195474)]
概率总和 1.0000000149011612

参考资料

朴素贝叶斯
用LDA处理文本
LDA简洁模型

  • 9
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值