主题模型 LDA 入门
主题模型 LDA 入门(附 Python 代码)
一、主题模型
在文本挖掘领域,大量的数据都是非结构化的,很难从信息中直接获取相关和期望的信息,一种文本挖掘的方法:主题模型(Topic Model)能够识别在文档里的主题,并且挖掘语料里隐藏信息,并且在主题聚合、从非结构化文本中提取信息、特征选择等场景有广泛的用途。
主题可以被定义为“语料库中具有相同词境的词的集合模式”,比如说,主题模型可以
- 将“健康”,“医生”,“病人”,“医院” 集合成 “医疗保健” 主题
 - 将 “农场”,“玉米”,“小麦” 集合成 “农业”主题
 
二、狄利克雷分布(Latent Dirichlet Allocation,LDA)主题模型
LDA 模式是生成式模型,在这里,假设需要建模的数据为 XX,标签信息为 YY。
判别式模型:对 YY 的产生过程进行描述,对特征信息本身不建模。判别式模型有利于构建分类器或者回归分析生成式模型需要对 XX 和 YY 同时建模,更适合做无监督学习分析。
生成式模型:描述一个联合概率分布 P(X,Y)P(X,Y) 的分解过程,这个分解过程是虚拟的过程,真实的数据不是这么产生的,但是任何一个数据的产生过程可以在数学上等价为一个联合概率分布。
LDA 是一种矩阵分解技术,在向量空间中,任何语料(文档的集合)可以表示为文档(Document - Term,DT)矩阵。下面矩阵表达了一个语料库的组成:
| . | W1W1 | W2W2 | … | WmWm | 
|---|---|---|---|---|
| D1D1 | 0 | 2 | … | 3 | 
| D2D2 | 1 | 4 | … | 0 | 
| ...... | … | … | … | … | 
| DnDn | 1 | 1 | … | 0 | 
其中,NN个文档 D1,D2,…,DnD1,D2,…,Dn的组成语料库,MM 个词 W1,W2,…,WmW1,W2,…,Wm 组成词汇表。矩阵中的值表示了词 WjWj在文档 DiDi 中出现的频率,同时,LDA 将这个矩阵转换为两个低维度的矩阵,M1M1 和 M2M2。
| . | Z1Z1 | Z2Z2 | … | ZkZk | 
|---|---|---|---|---|
| θ1θ1 | 0 | 2 | … | 3 | 
| θ2θ2 | 1 | 4 | … | 0 | 
| ...... | … | … | … | … | 
| θnθn | 1 | 1 | … | 0 | 
上面显示了 M1M1 矩阵的情况,它是一个 N∗KN∗K 大小的 document - topic 矩阵,NN 指文档的数量,KK 指主题的数量,M1M1 中,θiθi 是一个长度为 kk 的向量,用于描述当前文档 θiθi 在 kk 个主题上的分布情况,ZZ 表示具体的主题。
| . | W1W1 | W2W2 | … | WmWm | 
|---|---|---|---|---|
| ϕ1ϕ1 | 0 | 2 | … | 3 | 
| ϕ2ϕ2 | 1 | 4 | … | 0 | 
| ...... | … | … | … | … | 
| ϕkϕk | 1 | 1 | … | 0 | 
上面显示了 M2M2 矩阵的情况,它是一个 K∗VK∗V 维的 topic - term矩阵,KK 指主题的数量,VV 指词汇表的大小。M2M2 中每一行都是一个 ϕϕ 分布,也就是主题 ϕkϕk 在 mm 个词上的多项式分布情况,可以通过学习得到。
LDA 文档生成流程
LDA 假设文档是由多个主题的混合来产生的,每个文档的生成过程如下:
- 从全局的泊松分布参数为 的分布中生成一个文档的长度 NN
 - 从全局的狄利克雷参数为 alphaalpha 的分布中生成一个当前文档的 θθ
 - 对当前文档长度 NN 的每一个字都有 
- 从 θθ 为参数的多项式分布生成一个主题的下标 znzn
 - 从 θθ 和 zz 共同为参数的多项式分布中,产生一个字 wnwn
 
 
这些主题基于词的概率分布来产生词,给定文档数据集,LDA 可以学习出,是哪些主题产生了这些文档。
对于文档生成过程,则有,首先对于文档 nn 中的每一个字,都先从文档矩阵 M1M1 中的 θiθi 中产生一个下标,告诉我们现在要从主题矩阵 M2M2 中的哪一行 ϕmϕm生成当前的字。
训练过程(吉布斯采样)
吉布斯采样 (Gibbs Sampling) 首先选取概率向量的一个维度,给定其他维度的变量值当前维度的值,不断收敛来输出待估计的参数。具体地
- 随机给每一篇文档的每一个词 ww,随机分配主题编号 zz
 - 统计每个主题 zizi 下出现字 ww 的数量,以及每个文档 nn 中出现主题 zizi 中的词 ww的数量
 - 每次排除当前词 ww 的主题分布 zizi,根据其他所有词的主题分类,来估计当前词 ww 分配到各个主题 z1,z2,…,zkz1,z2,…,zk的概率,即计算 p(zi|z−i,d,w)p(zi|z−i,d,w) (Gibbs updating rule))。得到当前词属于所有主题z1,z2,…,zkz1,z2,…,zk 的概率分布后,重新为词采样一个新的主题 z1z1。用同样的方法不断更新的下一个词的主题,直到每个文档下的主题分布θnθn 和每个主题下的词分布 ϕkϕk 收敛。
 - 最后输出待估计参数,θnθn 和 ϕkϕk ,每个单词的主题 zn,kzn,k 也可以得到。
 
LDA 对于每个文档的每一个字都有一个主题下标。但从文档聚类的角度来说,LDA 没有一个文档统一的聚类标签,而是每个字都有一个聚类标签,这个就是主题。LDA 每个字都有可能属于不同的类别,每个文档都有可能属于不同的类别。在大量的迭代后,主题分布和字分布都比较稳定也比较好了,LDA 模型收敛。
三、LDA 的参数
αα :表示 document-topic 密度, αα 越高,文档包含的主题更多,反之包含的主题更少
ββ :表示 topic-word 密度, ββ 越高,主题包含的单词更多,反之包含的单词更少
主题数量:主题数量从语料中抽取得到,使用 Kullback Leibler Divergence Score 可以获取最好的主题数量。
主题词数:组成一个主题所需要的词的数量。这些词的数量通常根据需求得到,如果说需求是抽取特征或者关键词,那么主题词数比较少,如果是抽取概念或者论点,那么主题词数比较多。
迭代次数:使得 LDA 算法收敛的最大迭代次数
四、Running in Python
准备文档集合
doc1 = "Sugar is bad to consume. My sister likes to have sugar, but not my father."
doc2 = "My father spends a lot of time driving my sister around to dance practice."
doc3 = "Doctors suggest that driving may cause increased stress and blood pressure."
doc4 = "Sometimes I feel pressure to perform well at school, but my father never seems to drive my sister to do better."
doc5 = "Health experts say that Sugar is not good for your lifestyle."
# 整合文档数据
doc_complete = [doc1, doc2, doc3, doc4, doc5]
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 
数据清洗和预处理
数据清洗对于任何文本挖掘任务来说都非常重要,在这个任务中,移除标点符号,停用词和标准化语料库(Lemmatizer,对于英文,将词归元)。
from nltk import stopwords
from nltk.stem.wordnet import WordNetLemmatizer
import string
stop = set(stopwords.words('english'))
exclude = set(string.punctuation)
lemma = WordNetLemmatizer()
def clean(doc):
    stop_free = " ".join([i for i in doc.lower().split() if i not in stop])
    punc_free = ''.join(ch for ch in stop_free if ch not in exclude)
    normalized = " ".join(lemma.lemmatize(word) for word in punc_free.split())
    return normalized
doc_clean = [clean(doc).split() for doc in doc_complete]
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 
准备 Document - Term 矩阵
语料是由所有的文档组成的,要运行数学模型,将语料转化为矩阵来表达是比较好的方式。LDA 模型在整个 DT 矩阵中寻找重复的词语模式。Python 提供了许多很好的库来进行文本挖掘任务,“genism” 是处理文本数据比较好的库。下面的代码掩饰如何转换语料为 Document - Term 矩阵:
import genism
from gensim import corpora
# 创建语料的词语词典,每个单独的词语都会被赋予一个索引
dictionary = corpora.Dictionary(doc_clean)
# 使用上面的词典,将转换文档列表(语料)变成 DT 矩阵
doc_term_matrix = [dictionary.doc2bow(doc) for doc in doc_clean]
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 
构建 LDA 模型
创建一个 LDA 对象,使用 DT 矩阵进行训练。训练需要上面的一些超参数,gensim 模块允许 LDA 模型从训练语料中进行估计,并且从新的文档中获得对主题分布的推断。
# 使用 gensim 来创建 LDA 模型对象
Lda = genism.models.ldamodel.LdaModel
# 在 DT 矩阵上运行和训练 LDA 模型
ldamodel = Lda(doc_term_matrix, num_topics=3, id2word = dictionary, passes=50)
- 1
 - 2
 - 3
 - 4
 - 5
 
结果
# 输出结果
print(ldamodel.print_topics(num_topics=3, num_words=3))
[
    '0.168*health + 0.083*sugar + 0.072*bad,
    '0.061*consume + 0.050*drive + 0.050*sister,
    '0.049*pressur + 0.049*father + 0.049*sister
]
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 
每一行包含了主题词和主题词的权重,Topic 1 可以看作为“不良健康习惯”,Topic 3 可以看作 “家庭”。
五、提高主题模型结果的一些方法
主题模型的结果完全取决于特征在语料库中的表示,但是语料通常表示为比较稀疏的文档矩阵,因此减少矩阵的维度可以提升主题模型的结果。
1. 根据词频调整稀疏矩阵
根据频率来分布词,高频词更可能出现在结果中,低频词实际上是语料库中的弱特征,对于词频进行分析,可以决定什么频率的值应该被视为阈值。
2. 根据词性标注 (Part of Speech Tag) 调整稀疏矩阵
比起频率特征,词性特征更关注于上下文的信息。主题模型尝试去映射相近的词作为主题,但是每个词在上下文上有可能重要性不同,比如说介词 “IN” 包含 “within”,“upon”, “except”,基数词 “CD” 包含:许多(many),若干(several),个把(a,few)等等,情态助动词 “MD” 包含 “may”,“must” 等等,这些词可能只是语言的支撑词,对实际意义影响不大,因此可以通过词性来消除这些词的影响。
3. 调整 LDA 的 Batch 大小
为了得到主题中最重要的主题词,语料可以被分为固定大小的 batch,在这些 batch 上运行 LDA 模型会提供不同的结果,但是最佳的主题词会在这些 batch 上有交集。
主题模型用于特征选择
比如说文本分类任务中,LDA 可以用来选择特征,因为训练数据中含有类别信息,可以在不同类别的结果中,删除相同的、比较常见的主题词,为主题类别提供更好的特征。
结语
本文主要参考了[1],没有什么公式,用于对 LDA 有一个大概的了解,后面也会更深入 LDA 模型,可以一边运行上面的代码一边感受 LDA 的作用。
主题模型 LDA 入门的更多相关文章
- 自然语言处理基础与实战(8)- 主题模型LDA理解与应用
		
本文主要用于理解主题模型LDA(Latent Dirichlet Allocation)其背后的数学原理及其推导过程.本菇力求用简单的推理来论证LDA背后复杂的数学知识,苦于自身数学基础不够,因此文中 ...
 - 主题模型TopicModel:主题模型LDA的应用
		
http://blog.csdn.net/pipisorry/article/details/45665779 主题模型LDA的应用 拿到这些topic后继续后面的这些应用怎么做呢:除了推断出这些主题 ...
 - LDA主题模型三连击-入门/理论/代码
		
目录 概况 为什么需要 LDA是什么 LDA的应用 gensim应用 数学原理 预备知识 抽取模型 样本生成 代码编写 本文将从三个方面介绍LDA主题模型--整体概况.数学推导.动手实现. 关于LDA ...
 - 主题模型-LDA浅析
		
(一)LDA作用 传统判断两个文档相似性的方法是通过查看两个文档共同出现的单词的多少,如TF-IDF等,这种方法没有考虑到文字背后的语义关联,可能在两个文档共同出现的单词很少甚至没有,但两个文档是相似 ...
 - 主题模型LDA及在推荐系统中的应用
		
1 关于主题模型 使用LDA做推荐已经有一段时间了,LDA的推导过程反复看过很多遍,今天有点理顺的感觉,就先写一版. 隐含狄利克雷分布简称LDA(latent dirichlet allocation ...
 - LDA( Latent Dirichlet Allocation)主题模型 学习报告
		
1 问题描述 LDA由Blei, David M..Ng, Andrew Y..Jordan于2003年提出,是一种主题模型,它可以将文档集中每篇文档的主题以概率分布的形式给出,从而通过分析一 ...
 - [综] Latent Dirichlet Allocation(LDA)主题模型算法
		
多项分布 http://szjc.math168.com/book/ebookdetail.aspx?cateid=1&§ionid=983 二项分布和多项分布 http:// ...
 - R语言︱LDA主题模型——最优主题数选取(topicmodels)+LDAvis可视化(lda+LDAvis)
		
每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 笔者寄语:在自己学LDA主题模型时候,发现该模 ...
 - 理解 LDA 主题模型
		
前言 gamma函数 0 整体把握LDA 1 gamma函数 beta分布 1 beta分布 2 Beta-Binomial 共轭 3 共轭先验分布 4 从beta分布推广到Dirichlet 分布 ...
 
随机推荐
- Office365学习笔记—列表查询,删除条目,更新条目。
			
1,基于Query语句的列表查询. function retrieveListItems(itemId) { var siteUrl=_spPageContextInfo.webServerRelat ...
 - winform 里 如何实现文件上传
			
看了网上写的 用webclient类的uploadfile方法, 我在本地建立了个webform,winform窗体, 现在可以本地实现文件传递,可以选择文件传到d:\temp路径下,但怎们传到服务 ...
 - JasperReport4.6生成PDF中文
			
Web项目中PDF显示中文 本人无奈使用JasperReport4.6,因为这本书(好像也是唯一的一本国内的介绍JasperReport的书), 选择"文件"→New命令,弹出一个 ...
 - 身份认证系统(三)什么是OAuth2
			
本文准备用最简单的语言告诉大家什么是OAuth2 ,OAuth2是干什么的. 我们有一个资源服务器,资源服务器中有一系列的用户数据. 现在有一个应用想想要获取我们的用户数据. 那么最简单的方法就是我们 ...
 - Swift_类和结构体
			
Swift_类和结构体 点击查看源码 struct Resolution { var width = 0 var height = 0 } class VideoMode { var resoluti ...
 - angular动态绑定样式以及改变UI框架样式的方法
			
一:angular动态绑定样式 举个栗子: <tr *ngFor="let dataTr of tableData;let i = index" [formGroupName ...
 - 开源框架:DBUtils使用详解
			
一.先熟悉DBUtils的API: 简介:DbUtils是一个为简化JDBC操作的小类库. (一)整个dbutils总共才3个包: 1.包org.apache.commons.dbutils 接 ...
 - 记一次MySQL中Waiting for table metadata lock问题的处理
			
起因:由于需要,要把一张表的一个字段从不是 null 改成 可null,我用的Navicat Premium ,但是在保存的时候,工具无响应了,几个同事操作都是这样的,很奇怪,怀疑是不是由于表被锁了还 ...
 - 安装psutil时提示缺少python.h头文件(作记录)
			
通过pip或者源码安装psutil,都会提示缺少python.h头文件,错误提示如下: ... psutil/_psutil_common.c:9:20: fatal error: Python.h: ...
 - 用Head方法获得百度搜索结果的真实地址
			
用Head方法获得百度搜索结果的真实地址 在百度中搜索"Java",第一条结果的链接为: https://www.baidu.com/link?url=HBOOMbhPKH4SfI ...