我的编程空间,编程开发者的网络收藏夹
学习永远不晚

用 Python 实现 LDA

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

用 Python 实现 LDA

原文出处:Jordan Barber

  • LDA 是什么
  • LDA 演练
    • 需要用到的包
    • 导入文档
    • 清洗文档 
      • 分词
      • 移除停用词
      • 词干提取
    • 创建 document-term matrix
    • 应用 LDA 模型
    • 检查结果
    • LDA 原理
    • 完整代码

隐含狄利克雷分布(以下简写为 LDA)是一种主题模型,它基于一组文档中的词频生成主题。对于在给定的文档集中准确合理地找到主题的混合,LDA 是一种非常有效的方法。

这一部分,我会用一个高度简化过的文档集来演练生成一个 LDA 模型的过程。这并不是对 LDA 的全面讲解。这个演练的目的是为大家准备数据,以及用 LDA 模型得到相应输出的核心步骤提供指导。

需要用到的包

该演练当中使用的 Python 包有:

  • NLTK, Python 的一个自然语言处理工具包。对于任何一种自然语言的处理都非常有用。
    • 在 Mac/Unix 下使用 pip 安装:$ sudo pip install -U nltk.
  • stop_words,一个包含停用词的 Python 包。
    • 在 Mac/Unix 下使用 pip 安装:$ sudo pip install stop-words.
  • gensim,包含我们要用到的 LDA 模型的一个主题模型包。 
    • 在 Mac/Unix 下使用 pip 安装:$ sudo pip install gensim.

导入文档

这是我们的文档用例:

doc_a = "Brocolli is good to eat. My brother likes to eat good brocolli, but not my mother."
doc_b = "My mother spends a lot of time driving my brother around to baseball practice."
doc_c = "Some health experts suggest that driving may cause increased tension and blood pressure."
doc_d = "I often feel pressure to perform well at school, but my mother never seems to drive my brother to do better."
doc_e = "Health professionals say that brocolli is good for your health."

# compile sample documents into a list
doc_set = [doc_a, doc_b, doc_c, doc_d, doc_e]  

清洗文档

数据清洗对于生成一个有效的主题模型是极其极其重要的:俗话说,“输入的是垃圾,得到的一定也是垃圾”(Garbage in, garbarge out.)。下面的步骤就是自然语言处理的常见方法:

  • 分词:将文档转化为其原子元素。
  • 停用词处理:移除无意义的词。
  • 词干提取:将同义词合并。

分词

分词即将一个文档分成其原子元素。在这个例子中,我们将其分为单词。分词有很多种方法,我们用的是 NLTK 的 tokenize.regexp 模块:

from nltk.tokenize import RegexpTokenizer
tokenizer = RegexpTokenizer(r'\w+') 

上面的代码会匹配所有单字字符,直到其遇到像空格这样的非单字的字符。这是个很简单的方法,但是会出现一些问题,比如像“don't”这样的单词就会被分成两个词“don”和“t“。NLTK 提供了很多像 nltk.tokenize.simple 这样的预留的特定结构的词。对于特殊用例,最好还是用 regex 和不断的迭代来使你的文档精确地分词。

注意:这个例子是对单个文档调用 tokenize()。你需要创建一个 for 循环来遍历所有文档。用下面这个脚本做个示例。

raw = doc_a.lower()
tokens = tokenizer.tokenize(raw)

>>> print(tokens)
['brocolli', 'is', 'good', 'to', 'eat', 'my', 'brother', 'likes', 'to', 'eat', 'good', 'brocolli', 'but', 'not', 'my', 'mother'] 

文档 doc_a 现在就是一个词的列表了。

停用词

英语中的一些特定组成部分,比如“for”,“or”这样的连词,或是“the”这种词对主题模型毫无意义。这些词叫做停用词,需要从我们的单词列表中移除。

停用词的定义是非常灵活的,在不同种类的文档中对应的停用词的含义是不同的。比如,如果我们要为一系列音乐评论做主题模型,那像“The Who”(英国的一支摇滚乐队)这种词就会有点麻烦,因为“the”通常都会作为一个常见的停用词而被移除。你可以根据实际情况来创建自己的停用词列表,或者用其他的包。

在我们的例子中,我们使用 Pypi 的 stop_words 包,这是一个相对比较保守的列表。我们可以调用 get_stop_words() 来创建一个停用词列表:

from stop_words import get_stop_words

# create English stop words list
en_stop = get_stop_words('en') 

现在,移除停用词只是一个循环遍历我们的单词的工作了,将每一个词都和 en_list 列表作比较。

# remove stop words from tokens
stopped_tokens = [i for i in tokens if not i in en_stop]

>>> print(stopped_tokens)
['brocolli', 'good', 'eat', 'brother', 'likes', 'eat', 'good', 'brocolli', 'mother'] 

词干提取

词干提取是 NLP 的另一个常见技术,它用于将相似的单词去除词缀得到词根。例如:“stemming”,“stemmer”,“stemmed”都有相似的意思;词干提取就是去除这些词的词缀而得到词根“stem”。这对主题模型来说很重要,否则如果将这些单词看做不同的实体,会降低他们在模型中的重要程度。

和停用词一样,词干提取也是非常灵活的,有些方法在特定的情形下可能会出问题。Porter stemming algorithm 是使用最广泛的方法。我们从 NLTK 中引入 Porter Stemmer 模块来实现这个算法:

from nltk.stem.porter import PorterStemmer

# Create p_stemmer of class PorterStemmer
p_stemmer = PorterStemmer() 
注意,p_stemmer 要求所有单词的类型都是 str。p_stemmer 以词干的形式返回字符串参数。

# stem token
texts = [p_stemmer.stem(i) for i in stopped_tokens]

>>> print(stemmed_tokens)
['brocolli', 'good', 'eat', 'brother', 'like', 'eat', 'good', 'brocolli', 'mother'] 

构建 document-term matrix

(译注:document-term matrix 是一个描述文档词频的矩阵,每一行对应文档集中的一篇文档,每一列对应一个单词,这个矩阵可以根据实际情况,采用不同的统计方法来构建。)

清洗阶段的结果就是文本(texts),从单个的文档中整理出来的分好词,去除了停用词而且提取了词干的单词列表。假设我们已经循环遍历了所有文档,将每份文档都整理成为了文本。现在,文本就是一个(单词)列表的列表了,每个单词列表就代表一份原文档。

要生成一个 LDA model,我们需要知道每个词在文档中出现的频繁程度。为此我们需要用到一个叫 gensim 的包来构建 document-term matrix:

from gensim import corpora, models

dictionary = corpora.Dictionary(texts) 

Dictionary() 方法遍历所有的文本,为每个不重复的单词分配一个单独的整数 ID,同时收集该单词出现次数以及相关的统计信息。试试用 print(dictionary.token2id) 来查看每个单词的id。

接下来,我们要将 dictionary 转化为一个词袋:

doc2bow() 方法将 dictionary 转化为一个词袋。得到的结果 corpus 是一个向量的列表,向量的个数就是文档数。在每个文档向量中都包含一系列元组。举个例子,print(corpus[0]) 结果如下:

>>> print(corpus[0])
[(0, 2), (1, 1), (2, 2), (3, 2), (4, 1), (5, 1)] 

这个元组列表代表我们的第一个文档 doc_a。元组的形式是(单词 ID,词频)。所以如果 print(dictionary.roken2id) 显示 brocolli 的 id 是 0,那么第一个元组就代表 brocolli 这个词在 doc_a 里出现了两次。只有在文档中出现过的词才会包含在 doc2bow() 中,否则它将不会出现在文档向量之中。

应用 LDA 模型

corpus 是一个 document-term matrix,现在,我们已经为生成一个 LDA 模型做好准备了:

ldamodel = gensim.models.ldamodel.LdaModel(corpus, num_topics=3, id2word = dictionary, passes=20) 

LdaModel 类的详细描述可以在 gensim 文档中查看。我们的实例中用到的参数:

参数:

  • num_topics: 必须。LDA 模型要求用户决定应该生成多少个主题。由于我们的文档集很小,所以我们只生成三个主题。
  • id2word:必须。LdaModel 类要求我们之前的 dictionary 把 id 都映射成为字符串。
  • passes:可选。模型遍历语料库的次数。遍历的次数越多,模型越精确。但是对于非常大的语料库,遍历太多次会花费很长的时间。

检查结果

我们的 LDA 模型已经用 ldamodel 储存好了。我们可以用 print_topic 和 print_topics 方法来查看主题:

>>> print(ldamodel.print_topics(num_topics=3, num_words=3))
['0.141*health + 0.080*brocolli + 0.080*good', '0.060*eat + 0.060*drive + 0.060*brother', '0.059*pressur + 0.059*mother + 0.059*brother'] 

这是什么意思呢?每一个生成的主题都用逗号分隔开。每个主题当中有三个该主题当中最可能出现的单词。即使我们的文档集很小,这个模型依旧是很可靠的。还有一些需要我们考虑的问题:

- health, brocolli 和 good 在一起时有很好的含义。

- 第二个主题有点让人疑惑,如果我们重新查看源文档,可以看到 drive 有很多种含义:driving a car 意思是开车,driving oneself to improve 是激励自己进步。这是我们在结果中需要注意的地方。

- 第三个主题包含 mother 和 brother,这很合理。

调整模型的主题数和遍历次数对于得到一个好的结果是很重要的。两个主题看起来更适合我们的文档。

ldamodel = gensim.models.ldamodel.LdaModel(corpus, num_topics=2, id2word = dictionary, passes=20)

>>> print(ldamodel.print_topics(num_topics=2, num_words=4))
['0.054*pressur + 0.054*drive + 0.054*brother + 0.054*mother', '0.070*brocolli + 0.070*good + 0.070*health + 0.050*eat'] 

LDA 到底做了什么?

这个解释有点长,但是对于理解我们千辛万苦生成的模型非常有帮助。

LDA 假定文档是从主题的混合生成的。这些主题又是由一些单词的特定概率分布而生成的。就像我们演练的模型一样。换句话说,LDA 假定文档以以下步骤生成:

  1. 确定一个文档中的单词数。假设我们的文档有六个单词。 
  2. 确定该文档由哪些主题混合而来,例如,这个文档包含 1/2 的“健康”(health)主题和 1/2 的“蔬菜”(vegetables)主题。
  3. 用每个主题的多项分布生成的单词来填充文档中的单词槽。在我们的例子中,“健康”主题占文档的 1/2,或者说占三个词。“健康”主题有“diet”这个词的可能性是 20%,或者有“execise" 这个词的概率是 15%,单词槽就是基于这些概率来填充的。

基于文档如何生成的假定,LDA 反其道而行之,并尝试找出最初哪些主题会创建这些文档。

完整代码

from nltk.tokenize import RegexpTokenizer
from stop_words import get_stop_words
from nltk.stem.porter import PorterStemmer
from gensim import corpora, models
import gensim

tokenizer = RegexpTokenizer(r'\w+')

# create English stop words list
en_stop = get_stop_words('en')

# Create p_stemmer of class PorterStemmer
p_stemmer = PorterStemmer()
    
# create sample documents
doc_a = "Brocolli is good to eat. My brother likes to eat good brocolli, but not my mother."
doc_b = "My mother spends a lot of time driving my brother around to baseball practice."
doc_c = "Some health experts suggest that driving may cause increased tension and blood pressure."
doc_d = "I often feel pressure to perform well at school, but my mother never seems to drive my brother to do better."
doc_e = "Health professionals say that brocolli is good for your health." 

# compile sample documents into a list
doc_set = [doc_a, doc_b, doc_c, doc_d, doc_e]

# list for tokenized documents in loop
texts = []

# loop through document list
for i in doc_set:
    
    # clean and tokenize document string
    raw = i.lower()
    tokens = tokenizer.tokenize(raw)

    # remove stop words from tokens
    stopped_tokens = [i for i in tokens if not i in en_stop]
    
    # stem tokens
    stemmed_tokens = [p_stemmer.stem(i) for i in stopped_tokens]
    
    # add tokens to list
    texts.append(stemmed_tokens)

# turn our tokenized documents into a id <-> term dictionary
dictionary = corpora.Dictionary(texts)
    
# convert tokenized documents into a document-term matrix
corpus = [dictionary.doc2bow(text) for text in texts]

# generate LDA model
ldamodel = gensim.models.ldamodel.LdaModel(corpus, num_topics=2, id2word = dictionary, passes=20)​ 


关于 LDA 原理的更多分析,推荐两份资料《LDA 数学八卦》和《LDA 漫游指南》。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

用 Python 实现 LDA

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

用 Python 实现 LDA

原文出处:Jordan BarberLDA 是什么LDA 演练需要用到的包导入文档清洗文档 分词移除停用词词干提取创建 document-term matrix应用 LDA 模型检查结果LDA 原理完整代码隐含狄利克雷分布(以下简写为 LD
2023-01-31

用python实现ping

这里使用的是最简易的方式,使用python的子进程管理模块,调用系统的ping命令,代码如下:import subprocess    import rep = subprocess.Popen(["ping.exe", 'google.c
2023-01-31

[Python]用python实现批量/

针对前面的代码 http://lxsym.blog.51cto.com/1364623/1065854,还存在的问题进行了改善:    1、去掉明文密码,通过交互输入密码    2、通过传参执行相关命令,增加灵活性    3、异常处理   
2023-01-31

用Python实现modbus slav

最近在研究modbus master和modbus slave。项目要求实现modbus slave虚拟机来做功能测试。网上modbus master相关的demo很多,但是modbus slave相关的demo很少。还是Google给力,
2023-01-31

使用 python 实现 Voronoi

以下程序 使用python实现 Voronoi图from PIL import Imageimport randomimport math def generate_voronoi_diagram(width, height, num_ce
2023-01-31

用Python实现Zabbix-API

做运维的朋友应该知道,公司IDC机房经常有上架、下架、报修和报废的服务器。如果服务器数量很多的时候很容易造成监控遗漏。       大的互联网公司把监控系统和CMDB(资产管理系统|配置管理数据库系统)集成在一起,当上架一台新机器的时候CM
2023-01-30

利用virtualenv实现Python

由于开发需求,需要Python2和Python3共存,利用当下最流行的虚拟环境工具virtualenv实现。#安装virtualenvpip install virtualenv#使用virtualenv创建虚拟环境virtualenv p
2023-01-31

实现正确实现Python调用jar包

博主最近在做python的项目,需要调用jar包,但是虽然参考了网上很多的教程,但是有一点是无法解决,那就是用python无法启动jvm虚拟机!!!这是所有工作的前提,重装了好多次也没有解决,最后请教大佬解决了。问题的关键点在于:电脑的位数
2023-01-31

Python基础 用Python实现时钟

语言:Python IDE:Python.IDE编写时钟程序,要求根据时间动态更新 代码思路 需求:5个Turtle对象, 1个绘制外表盘+3个模拟表上针+1个输出文字 Step1:建立Turtle对象并初始化 Step2:静态表盘绘制
2023-01-31

用python实现调用jar包

本文作者:botoo背景:python3.6 32位 + jre 32位 + windows64位首先环境搭建:安装jpype,安装的时候输入 pip install jpype1 (后面要加一个1)*一定要注意 jre和python的位数
2023-01-31

python调用mrjob实现hadoo

咱们一般写mapreduce是通过java和streaming来写的,身为pythoner的我,java不会,没办法就用streaming来写mapreduce日志分析。 这里要介绍一个模块,是基于streaming搞的东西。mrjob 可
2023-01-31

20190118-利用Python实现P

1.利用Python实现Pig Latin字母游戏“Pig Latin”是一个英语儿童文字改写游戏,整个游戏遵从下述规则:a. 元音字母是‘a’、‘e’、‘i’、‘o’、‘u’。字母‘y’在不是第一个字母的情况下,也被视作元音字母。其他字母
2023-01-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录