百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

使用Python的LDA主题建模(附链接)

toyiye 2024-06-21 12:20 10 浏览 0 评论

本文为大家介绍了主题建模的概念、LDA算法的原理,示例了如何使用Python建立一个基础的LDA主题模型,并使用pyLDAvis对主题进行可视化。

图片来源:Kamil Polak

引言

主题建模包括从文档术语中提取特征,并使用数学结构和框架(如矩阵分解和奇异值分解)来生成彼此可区分的术语聚类(cluster)或组,这些单词聚类继而形成主题或概念。

主题建模是一种对文档进行无监督分类的方法,类似于对数值数据进行聚类。

这些概念可以用来解释语料库的主题,也可以在各种文档中一同频繁出现的单词之间建立语义联系。

主题建模可以应用于以下方面:

发现数据集中隐藏的主题;

将文档分类到已经发现的主题中;

使用分类来组织/总结/搜索文档。

有各种框架和算法可以用以建立主题模型:

潜在语义索引(Latent semantic indexing)

潜在狄利克雷分配(Latent Dirichlet Allocation,LDA)

非负矩阵分解(Non-negative matrix factorization,NMF)

在本文中,我们将重点讨论如何使用Python进行LDA主题建模。具体来说,我们将讨论:

什么是潜在狄利克雷分配(LDA, Latent Dirichlet allocation);

LDA算法如何工作;

如何使用Python建立LDA主题模型。

什么是潜在狄利克雷分配(LDA, Latent Dirichlet allocation)?

潜在狄利克雷分配(LDA, Latent Dirichlet allocation)是一种生成概率模型(generative probabilistic model),该模型假设每个文档具有类似于概率潜在语义索引模型的主题的组合。

简而言之,LDA背后的思想是,每个文档可以通过主题的分布来描述,每个主题可以通过单词的分布来描述。

LDA算法如何工作?

LDA由两部分组成:

我们已知的属于文件的单词;

需要计算的属于一个主题的单词或属于一个主题的单词的概率。


注意:LDA不关心文档中单词的顺序。通常,LDA使用词袋特征(bag-of-word feature)表示来代表文档。

以下步骤非常简单地解释了LDA算法的工作原理:

1. 对于每个文档,随机将每个单词初始化为K个主题中的一个(事先选择K个主题);

2. 对于每个文档D,浏览每个单词w并计算:

P(T | D):文档D中,指定给主题T的单词的比例;

P(W | T):所有包含单词W的文档中,指定给主题T的比例。

3. 考虑所有其他单词及其主题分配,以概率P(T | D)′ P(W | T) 将单词W与主题T重新分配。

LDA主题模型的图示如下。

图片来源:Wiki

下图直观地展示了每个参数如何连接回文本文档和术语。假设我们有M个文档,文档中有N个单词,我们要生成的主题总数为K。


图中的黑盒代表核心算法,它利用前面提到的参数从文档中提取K个主题。

图片来源:Christine Doig

如何使用Python建立LDA主题模型

我们将使用Gensim包中的潜在狄利克雷分配(LDA)。

首先,我们需要导入包。核心包是re、gensim、spacy和pyLDAvis。此外,我们需要使用matplotlib、numpy和panases以进行数据处理和可视化。

1. import re
2. import numpy as np
3. import pandas as pd
4. from pprint import pprint
5. 
6. # Gensim
7. import gensim
8. import gensim.corpora as corpora
9. from gensim.utils import simple_preprocess
10. from gensim.models import CoherenceModel
11. 
12. # spacy for lemmatization
13. import spacy
14. 
15. # Plotting tools
16. import pyLDAvis
17. import pyLDAvis.gensim  # don't skip this
18. import matplotlib.pyplot as plt
19. %matplotlib inline
20. 
21. # Enable logging for gensim - optional
22. import logging
23. logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.ERROR)
24. 
25. import warnings
26. warnings.filterwarnings("ignore",category=DeprecationWarning)

像am/is/are/of/a/the/but/…这样的词不包含任何关于“主题”的信息。因此,作为预处理步骤,我们可以将它们从文档中移除。

要做到这一点,我们需要从NLT导入停用词。还可以通过添加一些额外的单词来扩展原始的停用词列表。

1.# NLTK Stop words
2. from nltk.corpus import stopwords
3. stop_words = stopwords.words('english')
4. stop_words.extend(['from', 'subject', 're', 'edu', 'use'])


在本教程中,我们将使用20个新闻组数据集,其中包含来自20个不同主题的大约11k个新闻组帖子。这可以作为newsgroups.json获得。

1. # Import Dataset
2. df = pd.read_json('https://raw.githubusercontent.com/selva86/datasets/master/newsgroups.json')
3. print(df.target_names.unique())
4. df.head()

删除电子邮件链接和换行符

在我们开始主题建模之前,需要清理数据集。首先,删除电子邮件链接、多余的空格和换行符。

1. # Convert to list
2. data = df.content.values.tolist()
3. 
4. # Remove Emails
5. data = [re.sub('\S*@\S*\s?', '', sent) for sent in data]
6. 
7. # Remove new line characters
8. data = [re.sub('\s+', ' ', sent) for sent in data]
9. 
10. # Remove distracting single quotes
11. data = [re.sub("\'", "", sent) for sent in data]
12. 
13. pprint(data[:1])

标记(tokenize)单词和清理文本

让我们把每个句子标记成一个单词列表,去掉标点符号和不必要的字符。

1. def sent_to_words(sentences):
2.     for sentence in sentences:
3.         yield(gensim.utils.simple_preprocess(str(sentence), deacc=True))  # deacc=True removes punctuations
4. 
5. data_words = list(sent_to_words(data))
6. 
7. print(data_words[:1])

创建二元(Bigram)模型和三元(Trigram)模型

1. # Build the bigram and trigram models
2. bigram = gensim.models.Phrases(data_words, min_count=5, threshold=100) # higher threshold fewer phrases.
3. trigram = gensim.models.Phrases(bigram[data_words], threshold=100)  
4. 
5. # Faster way to get a sentence clubbed as a trigram/bigram
6. bigram_mod = gensim.models.phrases.Phraser(bigram)
7. trigram_mod = gensim.models.phrases.Phraser(trigram)
8. 
9. # See trigram example
10. print(trigram_mod[bigram_mod[data_words[0]]])

删除停用词(stopword),建立二元模型和词形还原(Lemmatize)


在这一步中,我们分别定义了函数以删除停止词、建立二元模型和词形还原,并且依次调用了这些函数。

1.# Define functions for stopwords, bigrams, trigrams and lemmatization
2. def remove_stopwords(texts):
3.     return [[word for word in simple_preprocess(str(doc)) if word not in stop_words] for doc in texts]
4. 
5. def make_bigrams(texts):
6.     return [bigram_mod[doc] for doc in texts]
7. 
8. def make_trigrams(texts):
9.     return [trigram_mod[bigram_mod[doc]] for doc in texts]
10. 
11. def lemmatization(texts, allowed_postags=['NOUN', 'ADJ', 'VERB', 'ADV']):
12.     """https://spacy.io/api/annotation"""
13.     texts_out = []
14.     for sent in texts:
15.         doc = nlp(" ".join(sent)) 
16.         texts_out.append([token.lemma_ for token in doc if token.pos_ in allowed_postags])
17.     return texts_out


1. # Remove Stop Words
2. data_words_nostops = remove_stopwords(data_words)
3. 
4. # Form Bigrams
5. data_words_bigrams = make_bigrams(data_words_nostops)
6. 
7. # Initialize spacy 'en' model, keeping only tagger component (for efficiency)
8. # python3 -m spacy download en
9. nlp = spacy.load('en', disable=['parser', 'ner'])
10. 
11. # Do lemmatization keeping only noun, adj, vb, adv
12. data_lemmatized = lemmatization(data_words_bigrams, allowed_postags=['NOUN', 'ADJ', 'VERB', 'ADV'])
13. 
14. print(data_lemmatized[:1])

创建主题建模所需的词典和语料库(corpus)

Gensim为文档中的每个单词创建一个唯一的id,但是在此之前,我们需要创建一个字典和语料库作为模型的输入。

1. # Create Dictionary
2. id2word = corpora.Dictionary(data_lemmatized)
3. 
4. # Create Corpus
5. texts = data_lemmatized
6. 
7. # Term Document Frequency
8. corpus = [id2word.doc2bow(text) for text in texts]
9. 
10. # View
11. print(corpus[:1])

建立主题模型

现在我们准备进入核心步骤,使用LDA进行主题建模。让我们开始建立模型。我们将建立20个不同主题的LDA模型,其中每个主题都是关键字的组合,每个关键字在主题中都具有一定的权重(weightage)。

一些参数的解释如下:

num_topics —需要预先定义的主题数量;

chunksize — 每个训练块(training chunk)中要使用的文档数量;

alpha — 影响主题稀疏性的超参数;

passess — 训练评估的总数。

1. # Build LDA model
2. lda_model = gensim.models.ldamodel.LdaModel(corpus=corpus,
3.                                            id2word=id2word,
4.                                            num_topics=20, 
5.                                            random_state=100,
6.                                            update_every=1,
7.                                            chunksize=100,
8.                                            passes=10,
9.                                            alpha='auto',
10.                                            per_word_topics=True)

查看LDA模型中的主题


我们可以可视化每个主题的关键词和每个关键词的权重(重要性)。

1.# Print the Keyword in the 10 topics
2. pprint(lda_model.print_topics())
3. doc_lda = lda_model[corpus]

计算模型困惑度(Perplexity)和一致性分数(Coherence Score)

模型困惑度是对概率分布或概率模型预测样本好坏的一种度量。主题一致性通过测量主题中得分高的单词之间的语义相似度来衡量单个主题的得分。

简而言之,它们提供了一种方便的方法来判断一个给定的主题模型有多好。

1. # Compute Perplexity
2. print('\nPerplexity: ', lda_model.log_perplexity(corpus))  # a measure of how good the model is. lower the better.
3. 
4. # Compute Coherence Score
5. coherence_model_lda = CoherenceModel(model=lda_model, texts=data_lemmatized, dictionary=id2word, coherence='c_v')
6. coherence_lda = coherence_model_lda.get_coherence()
7. print('\nCoherence Score: ', coherence_lda)

可视化主题-关键词

现在,我们可以检查生成的主题和相关的关键词。最好的方法是使用pyLDAvis可视化我们的模型。

pyLDAvis旨在帮助用户在一个适合文本数据语料库的主题模型中解释主题。它从拟合好的的线性判别分析主题模型(LDA)中提取信息,以实现基于网络的交互式可视化。

1. # Visualize the topics2. pyLDAvis.enable_notebook()3. vis = pyLDAvis.gensim.prepare(lda_model, corpus, id2word)4. vis

至此,我们成功建立了一个可观的主题模型!

简要地解释一下结果:左手边的每个气泡代表一个话题。气泡越大,该主题就越盛行。根据经验,一个好的主题模型会有大的、不重叠的气泡。

我们也可以点击右边的侧边工具条,以调整阿尔法(alpha)参数。

结语

主题建模是自然语言处理的主要应用之一。本文的目的是解释什么是主题建模,以及如何在实际使用中实现潜在狄利克雷分配(LDA)模型。

为此,我们深入研究了LDA的原理,使用Gensim包中的LDA构建了一个基础的主题模型,并使用pyLDAvis对主题进行了可视化。

希望您喜欢该文并有所收获。

References:

Jelodar, H., Wang, Y., Yuan, C. et al. Latent Dirichlet allocation (LDA) and topic modeling: models, applications, a survey. Multimed Tools Appl 78, 15169–15211 (2019). https://doi.org/10.1007/s11042-018-6894-4

https://jovian.ai/outlink?url=https%3A%2F%2Fdoi.org%2F10.1007%2Fs11042-018-6894-4

D. Sarkar, Text Analytics with Python. A Practical Real-World Approach to Gaining Actionable Insights from Your Data

https://www.machinelearningplus.com/nlp/topic-modeling-gensim-python/

https://jovian.ai/outlink?url=https%3A%2F%2Fwww.machinelearningplus.com%2Fnlp%2Ftopic-modeling-gensim-python%2F

https://towardsdatascience.com/topic-modelling-in-python-with-nltk-and-gensim-4ef03213cd21

https://jovian.ai/outlink?url=https%3A%2F%2Ftowardsdatascience.com%2Ftopic-modelling-in-python-with-nltk-and-gensim-4ef03213cd21

https://towardsdatascience.com/end-to-end-topic-modeling-in-python-latent-dirichlet-allocation-lda-35ce4ed6b3e0

https://jovian.ai/outlink?url=https%3A%2F%2Ftowardsdatascience.com%2Fend-to-end-topic-modeling-in-python-latent-dirichlet-allocation-lda-35ce4ed6b3e0

https://towardsdatascience.com/latent-dirichlet-allocation-lda-9d1cd064ffa2

https://towardsdatascience.com/light-on-math-machine-learning-intuitive-guide-to-latent-dirichlet-allocation-437c81220158

http://blog.echen.me/2011/08/22/introduction-to-latent-dirichlet-allocation/

编辑:王菁

校对:林亦霖

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码