Gensim:一款进行文本主题识别的 Python 工具库

article/2025/8/22 20:09:36

从大量文本中自动提取人们谈论的主题(主题识别)是自然语言处理的基本应用之一。大型文本示例包括社交媒体订阅、消费者对酒店、电影和其他业务的评价、用户评论、新闻和客户发来的邮件。

在本中,将使用LDA 从 20Newsgroup 数据集 中提取主题的实战案例。欢迎深入探讨,喜欢记得点赞、关注、收藏。

【注】完整版代码、数据、技术交流文末获取

主题识别的基础知识

本节将涵盖主题识别和建模的原则。云朵君将和大家一起学习如何使用词袋方法和简单的 NLP 模型从文本中检测和提取主题。

词形还原

将单词简化为词根或词干称为词形还原。

首先实例化 WordNetLemmatizer 。调用 '.lemmatize()' 方法来构建一个名为 LEM 的tokens 的新列表。然后调用 Counter 类并生成一个名为 bag_words 的新 Counter,最后输出六个最有可能的主题。

lemmatizer = WordNetLemmatizer() 
lem_tokens = [lemmatizer.lemmatize(t) for t in stopwords_removed] 
bag_words = Counter(lem_tokens) 
print(bag_words.most_common(6))

Gensim 和 LDA

LDA 全称为 Latent Dirichlet Allocation,中文为潜在狄利克雷分配。

Gensim 是一个可以创建和查询语料库的开源自然语言处理 (NLP) 库。它通过构建词嵌入(embeddings)或向量(vectors)来进行操作,然后将其用于对主题进行建模。

深度学习算法用于构建称为词向量的词的多维数学表示。它们提供有关语料库中术语之间关系的信息。例如,“印度”和“新德里” 这两个词之间的距离可能与 “中国”和“北京” 这两个词之间的距离相当,因为它们是“国家-首都”向量。

Gensim 用于创建和查询语料库

之前我和大家一起学习了gensim的相关知识,本文将和大家一起动手开发第一个 gensim 词典和语料库!

这些数据结构将查看文档集中的文字趋势和其他有趣的主题。首先,我们导入了一些更混乱的 Wikipedia 文章,这些文章经过预处理,将所有单词小写、标记化并删除停用词和标点符号。然后这些文件被保存为文章,这是一个文档标记的列表。在创建 gensim 词汇和语料库之前,需要做一些初步工作。

Gensim 的词袋

现在,使用新的gensim语料库和字典来查看每个文档中和所有文档中最常使用的术语。你可以在字典里查这些术语。

可以使用 defaultdict 创建一个字典,将默认值赋给不存在的键。我们可以使用int形参确保任何不存在的键被自动分配一个默认值0。

LDA 的文档术语矩阵

创建LDA模型后,我们将在文档术语矩阵上训练LDA模型对象。必须指定主题的数量和字典。我们可能会将主题的数量限制在2到3个,因为我们有一个只有9个文档的小语料库。

当文本自身连贯时,词袋信息(LDA或TF-IDF)通过检测频繁的词来识别主题非常好。当文本不连贯时(在用词或句子意义上),就需要更多的语境信息来充分反映文本的思想。

数据集

本次案例使用可以 从 sklearn 下载的 20Newsgroup 数据集

from sklearn.datasets import fetch_20newsgroups 
newsgroups_train = fetch_20newsgroups(subset='train', shuffle = True) 
newsgroups_test = fetch_20newsgroups(subset='test', shuffle = True)

该数据集中的新闻已被分类为关键主题。

print(list(newsgroups_train.target_names))

图片

从结果中可以看到它涵盖了各种主题,例如科学、政治、体育、宗教和技术。我们看一些最近新闻的例子。

newsgroups_train.data[:2]

图片

数据预处理

具体步骤如下:

  1. 使用tokenization标记化将文本拆分为句子,将句子拆分为单词。

  2. 删除所有标点符号和将所有单词转换为小写单词。

  3. 过滤少于三个字符的单词。

  4. 删除所有停用词。

  5. 将名词进行词形还原,因此第三人称词被转换为第一人称,过去和将来时态动词被改变为现在时态。

  6. 将它们被简化成最简单的词根形式。

相关库准备

下载 nltk 停用词和必要的包。

import gensim
from gensim.utils import simple_preprocess
from gensim.parsing.preprocessing import STOPWORDS
from nltk.stem import WordNetLemmatizer, SnowballStemmer
from nltk.stem.porter import *
import numpy as np
np.random.seed(400)
import nltk
nltk.download('wordnet')

词形还原器

在开始预处理数据之前,看一个词形还原的例子。如果我们将“Gone”这个词进行词形还原,会发生什么?

以将过去时转换为现在时为例。

print(WordNetLemmatizer().lemmatize('gone', pos = 'v'))
go

词根提取示例。试着往词根分析器输入几句话,看看输出结果是什么。

import pandas as pd
stemmer = SnowballStemmer("english")
original_words = ['sings', 'classes', 'dies', 'mules', 'denied','played', 'agreement', 'owner', 'humbled', 'sized','meeting', 'stating', 'siezing', 'itemization','sensational', 'traditional', 'reference', 'colon','plotting']
singles = [stemmer.stem(plural) for plural in original_words]
pd.DataFrame(data={'original word':original_words, 'stemmed':singles })

图片

接下来编写一个函数来运行整个数据集的预处理阶段。

def lemmatize_stemming(text):return stemmer.stem(WordNetLemmatizer().lemmatize(text, pos='v'))
# Tokenize and lemmatize
def preprocess(text):result=[]for token in gensim.utils.simple_preprocess(text) :if token not in gensim.parsing.preprocessing.STOPWORDS and len(token) > 3:result.append(lemmatize_stemming(token))return resul

现在预览预处理后的文档,并得到 Tokenized 和 lemmized 文档。

document_number = 50
doc_sample = 'Sara did not like to read. She was not very good at it.'
print("Original document: ")
words = []
for word in doc_sample.split(' '):words.append(word)
print(words)
print("nnTokenized and lemmatized document: ")
print(preprocess(doc_sample))
Original document:
['Sara', 'did', 'not', 'like', 'to', 'read.',
'She', 'was', 'not', 'very', 'good', 'at', 'it.']
nnTokenized and lemmatized document: 
['sara', 'like', 'read', 'good']

开始预处理所有的新闻标题之前。需要仔细地检查训练示例中的文档列表。

processed_docs = []
for doc in newsgroups_train.data:processed_docs.append(preprocess(doc))
# Preview 'processed_docs
print(processed_docs[:2])

图片

现在将使用"processed_docs"来构建一个字典,其中包含每个单词在训练集中出现的次数。为此,将其称为"dictionary"并将处理后的文档提供给gensim.corpora.Dictionary()[1]。

创建词袋

从文本中创建一个词袋

在主题识别之前,我们将标记化和词形化的文本转换成一个词包,可以将其视为一个字典,键是单词,值是该单词在语料库中出现的次数

使用 gensim.corpora.Dictionary,从 "processed_docs" 创建一个字典,其中包含一个术语在训练集中出现的次数,并将其命名为 "dictionary"

dictionary = gensim.corpora.Dictionary(processed_docs)

首先检查字典是否被创建。

count = 0 
for k, v in dictionary.iteritems(): print(k, v) count += 1 if count > 10: break
0 addit1 bodi2 bricklin3 bring4 bumper5 
call6 colleg7 door8 earli9 engin10 enlighten

过滤极值

删除列表中出现如下所有tokens。

  • 大于没有以上文档的(绝对数量)或小于没有以下文档的(绝对数量)(总语料库大小的分数,而不是绝对数量)。

  • 只保留(1)和(2)之后的第一个保留n个最常见的标记。(如果为None则保留所有标记)。

dictionary.filter_extremes(no_below=15,no_above=0.1,keep_n= 100000)

还可以过滤掉不经常或经常出现的单词。

现在使用生成的字典对象将每个预处理页面转换成一个词袋。即为每个文档建立一个字典,存储有多少单词以及这些单词出现了多少次。

Gensim doc2bow

doc2bow(document)

将文档(单词列表)转换为word格式的2元组列表(token id token计数)。每个单词都是标准化和标记化的字符串(Unicode或utf8-encoded)。在调用此函数之前,对文档中的单词应用标记化、词干分析和其他预处理。

必须使用Bag-of-words模型为每个文档创建一个字典,在这个字典中存储有多少单词以及这些单词出现的次数。“bow corpus”用来保存该字典比较合适。

bow_corpus = [dictionary.doc2bow(doc) for doc in processed_docs]

现在,预览预处理的示例文档11的BOW。

document_num = 11
bow_doc_x = bow_corpus[document_num]for i in range(len(bow_doc_x)):print('Word {} ("{}") appears {} time.'.format(bow_doc_x[i][0],dictionary[bow_doc_x[i][0]],bow_doc_x[i][1]))

图片

执行 LDA

使用 Bag of Words

在文档语料库中,我们的目标是十个主题。为了并行化和加速模型训练,我们在所有 CPU 内核上执行 LDA。

以下是我们将要调整的一些参数:

  1. 要求从训练语料库中检索到的潜在主题个数为1个主题。

  2. id2word 映射将单词 id(整数)转换为单词(字符串)。它用于调试和主题打印,以及确定词汇量。

  3. 用于并行化的额外进程的数量是workers数量。默认情况下,使用所有可用的内核。

  4. 超参数 alpha 和 eta 分别影响文档-主题 (theta) 和主题-单词 (lambda) 分布的稀疏性。目前,这些将是默认值(默认值为 1/num 个主题)。

每个文档的主题分布是Alpha

  • 高alpha值: 每个文档都有多个主题(文档看起来彼此相似)。

  • 低alpha值: 每个文档包含一些主题。

每个主题的单词分布称为Eta

  • 高eta值: 每个主题包含各种单词(主题看起来彼此相似)。

  • 低eta值: 每个主题包含少量的单词。

因为我们可以使用gensim LDA模型,所以这是相当简单的。但必须指定数据收集中的主题数量。假设我们从八个不同的主题开始。通过该文件的培训次数称为通过次数。

gensim.models 将训练 LDA model. LdaMulticore,并将其放在"LDA model"文件夹。

lda_model = gensim.models.LdaMulticore(bow_corpus, num_topics = 8, id2word = dictionary, passes = 10,workers = 2)

训练模型后,查看该主题中出现的单词以及它们对每个单词的比例重要性。

for idx, topic in lda_model.print_topics(-1):print("Topic: {} nWords: {}".format(idx, topic ))print("n")

主题 Tokens

你能够从每个主题中的单词及其相应的权重中得出哪些类别?

  • 0: Gun Violence

  • 1: Sports

  • 2: Politics

  • 3: Space

  • 4: Encryption

  • 5: Technology

  • 6: Graphics Cards

  • 7: Religion

模型测试

对未知文档的数据进行预处理。

num = 70
unseen_document = newsgroups_test.data[num]print(unseen_document)bow_vector = dictionary.doc2bow(preprocess(unseen_document))
for index, score in sorted(lda_model[bow_vector], key=lambda tup: -1*tup[1]):print("Score: {}t Topic: {}".format(score, lda_model.print_topic(index, 5)))

图片

这里模型已经完成。现在思考下,如何解释它,看看结果是否有意义。

该模型产生八个主题的输出,每个主题都由一组单词分类。LDA 模型没有给这些词一个主题名称。

模型评估

① 该模型在提取数据集的不同主题方面表现出色,可以通过目标名称评估模型。

② 模型运行速度非常快。仅仅在几分钟内,就可以从数据集中提取主题。

③ 假设数据集包含离散的主题,如果数据集是随机推文的集合,则模型结果可能难以解释。

简单总结

  1. 通过结合 LDA 主题概率和句子嵌入,上下文主题识别模型同时利用了词袋和上下文信息。

  2. 尽管LDA在主题识别任务中表现良好,但它在处理要建模的简短文本和不能连贯地解释主题的文档时很困难。它也有局限性,因为它是基于一堆单词。

  3. 当文本内部是连贯的,词袋信息(LDA或TF-IDF)通过检测频繁的词来识别主题非常好。当文本不连贯时(在用词或句子意义上),就需要更多的信息来反映文本的思想。

推荐文章

  • 李宏毅《机器学习》国语课程(2022)来了

  • 有人把吴恩达老师的机器学习和深度学习做成了中文版

  • 上瘾了,最近又给公司撸了一个可视化大屏(附源码)

  • 如此优雅,4款 Python 自动数据分析神器真香啊

  • 梳理半月有余,精心准备了17张知识思维导图,这次要讲清统计学

  • 年终汇总:20份可视化大屏模板,直接套用真香(文末附源码)

技术交流

欢迎转载、收藏、有所收获点赞支持一下!

在这里插入图片描述

目前开通了技术交流群,群友已超过2000人,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友

  • 方式①、发送如下图片至微信,长按识别,后台回复:加群;
  • 方式②、添加微信号:dkl88191,备注:来自CSDN
  • 方式③、微信搜索公众号:Python学习与数据挖掘,后台回复:加群

长按关注


http://chatgpt.dhexx.cn/article/IW9XbXaJ.shtml

相关文章

gensim 快速入门 Word2Vec

文章目录 gensim的核心概念Word2Vec简介Word2Vec初试探将单词可视化 训练自己的Word2Vec模型 gensim的核心概念 Document: 文档。可以是一个一句话,或者一段话Corpus: 文档的集合Vector: 文档向量。将文档通过数学向量表示。Model: 模型。将文档转换为向量的模型。…

vue获得焦点事件处理函数中控制其失去焦点,但是失去焦点后该获得焦点事件一直被触发

当input获取焦点的时候需要判断另一个操作是否已完成,否则需要引导用户先去执行另一个操作,是则允许输入。 另一个操作跟当前操作是在同一个页面上,无法通过“下一步”进行控制。 解决思路是: 当input获取焦点的时候&#xff0…

div失去焦点事件onblur()无效

初学js事件&#xff0c;想做一个点击时变红&#xff0c;取消聚焦时变白的div&#xff0c;于是我这样写代码&#xff1a; <div style"width: 100px;height: 50px;border: 1px solid;"></div> <script>let div document.getElementsByTagName(&quo…

input失去焦点事件和点击事件冲突的解决思路

首先说一下应用场景 el-input框为禁用状态时&#xff0c;点击取消禁用&#xff0c;并显示后方两个按钮&#xff0c; 点击绿色按钮保存input框当前值&#xff0c;失去焦点或点击红色框时恢复改变前的值 思路就是不在input上的失去焦点方法&#xff0c;而是手动调用失去焦点方法…

input中blur失去焦点事件与点击事件冲突

场景&#xff1a; 当在输入框里输入手机号的时候&#xff0c;输入框高亮&#xff0c;并且关闭按钮显示&#xff0c;input失焦时关闭按钮隐藏 现象&#xff1a; 遇到的问题是&#xff0c;当我们点击关闭按钮清空input框数据时&#xff0c;发现只是关闭按钮隐藏了&#xff0c…

div失去焦点事件onblur()不触发解决方法

需求&#xff1a; 做一个弹出框组件&#xff0c;文字点击时会在文字下方弹出一个框&#xff0c;在vue3中监听div元素的blur事件发现事件并不会在div失去焦点时触发 解决方法 bug原因&#xff1a;在vue中div默认不触发事件,除非将元素添加tabindex"-1"属性才会触发…

JavaScript学习(二十一)——表单相关事件(焦点事件)

表单事件实际上就是对元素获得或失去焦点的动作进行控制。可以利用表单事件来改变获得或失去焦点的元素样式&#xff0c;这里所指的元素可以是同一类型&#xff0c;也可以是多个不同类型的元素。 获取焦点与失去焦点事件 获得焦点事件(onfocus) 是当某个元素获得焦点时触发事件…

特征工程 - 数据分析 - 峰度 and 偏度

特征工程 - 数据分析 - 峰度 and 偏度 偏度峰度 偏度 偏度&#xff08;Skewness&#xff09;用来描述数据分布的对称性。 当偏度 <0 时&#xff0c;称为负偏&#xff0c;数据出现左侧长尾&#xff1b;当偏度>0时&#xff0c;称为正偏&#xff0c;数据出现右侧长尾。 正态…

python金融分析小知识(6)——偏度与峰度的计算

Hello 大家好&#xff0c;我是一名新来的金融领域打工人&#xff0c;日常分享一些python知识&#xff0c;都是自己在学习生活中遇到的一些问题&#xff0c;分享给大家&#xff0c;希望对大家有一定的帮助&#xff01; 相信大家在平时的统计分析中&#xff0c;一定会用到数组偏…

使用Excel计算峰度(Kurtosis)和偏度(Skewness)

峰度&#xff08;Kurtosis&#xff09;和偏度&#xff08;Skewness&#xff09; 峰度是描述总体中所有取值分布形态陡缓程度的统计量。计算公式是&#xff1a; 在Excel中的公式是&#xff1a;KURT 因为是与标准正态分布比较&#xff0c;而标准正态分布的四阶矩为3&#xff0c;…

Resnet解读

pytorch的resnet模块在torchvision的models中。 里面可以选择的resnet类型有&#xff1a; _all_列表的每一个resnet都提供了实现的函数&#xff1a; def resnet18(pretrainedFalse, progressTrue, **kwargs):"""Constructs a ResNet-18 model.Args:pretrained …

ResNet算法

Daily learning2 Q1&#xff1a;过拟合&#xff08;overfitting&#xff09;&#xff0c;欠拟合&#xff08;underfitting&#xff09;&#xff1f; A1:欠拟合&#xff1a;根本原因是特征维度过少&#xff0c;模型过于简单&#xff0c;导致拟合的函数无法满足训练集&#xff0c…

Resnet代码详解

这篇文章是用来讲解Resnet(残差网络)代码的&#xff0c;结合代码理解残差网络结构。 目录 Bottleneck类 Conv33 Conv11 BasicBlock ResNet _make_layer代码解析 完整的ResNet代码&#xff1a; 可以直接调用torch内置的resnet官方代码。 from torchvision.models impo…

ResNet结构的pytorch实现

文章目录 1.ResNet的创新1&#xff09;亮点2&#xff09;原因 2.ResNet的结构1&#xff09;浅层的残差结构2&#xff09;深层的残差结构3&#xff09;总结 3.Batch Normalization4.参考代码 1.ResNet的创新 现在重新稍微系统的介绍一下ResNet网络结构。 ResNet结构首先通过一个…

Resnet论文解读

摘要&#xff1a; 提出了一种残差结构&#xff0c;这些残差网络的集合在ImageNet测试集上实现了3.57%的误差。该结果在ILSVRC 2015分类任务中获得第一名。 介绍&#xff1a; 主要讲述的就是针对 深度越深&#xff0c;精确度达到了一种饱和的状态&#xff0c;然后就会产生退化…

了解ResNet

产生背景 网络的层数越多&#xff0c;就能够提取更多的特征&#xff0c;但是如果只是简单的增加深度&#xff0c;就会导致梯度爆炸。也有文章提出&#xff0c;解决该问题的方法是正则化初始化和中间的正则化层&#xff0c;但是这样会导致另一个问题&#xff0c;退化,网络的层数…

ResNet网络

1.1.ResNet的提出 残差网络(ResNet) 是由来自Microsoft Research的4位学者提出的卷积神经网络&#xff0c;在2015年的ImageNet大规模视觉识别竞赛&#xff08;ImageNet Large Scale Visual Recognition Challenge, ILSVRC&#xff09;中获得了图像分类和物体识别的优胜。 网络…

ResNet详解——通俗易懂版

ResNet学习 什么是ResNet为什么要引入ResNet&#xff1f;ResNet详细解说 本篇博客主要是自己对论文的一些解读以及参考一些博客后的理解&#xff0c;如若有不对之处&#xff0c;请各位道友指出。多谢&#xff01; 2015年刚提出ResNet的Paper 2016对ResNet进行改进之后的Paper …

CNN经典网络模型(五):ResNet简介及代码实现(PyTorch超详细注释版)

目录 一、开发背景 二、网络结构 三、模型特点 四、代码实现 1. model.py 2. train.py 3. predict.py 4. spilit_data.py 五、参考内容 一、开发背景 残差神经网络(ResNet)是由微软研究院的何恺明、张祥雨、任少卿、孙剑等人提出的&#xff0c; 斩获2015年ImageNet竞赛…

ResNet详解+PyTorch实现

1.Resnet简介 深度残差网络&#xff08;Deep residual network, ResNet&#xff09;的提出是CNN图像史上的一件里程碑事件&#xff0c;由于其在公开数据上展现的优势&#xff0c;作者何凯明也因此摘得CVPR2016最佳论文奖。 Resnet是残差网络(Residual Network)的缩写&#xff…