热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

用隐藏语义分析(LSA)进行主题建模(附Python代码)

作者:PRATEEKJOSHI编译:Bing简介你是否曾去过一家管理完善的图书馆?在那儿,我常被它们井然有序的书籍管理所震撼,他们会根据书名、内容或者其他主题把所有书排列整齐。我不

作者:PRATEEK JOSHI

编译:Bing

简介

你是否曾去过一家管理完善的图书馆?在那儿,我常被它们井然有序的书籍管理所震撼,他们会根据书名、内容或者其他主题把所有书排列整齐。我不清楚每个管理员要经手的书有多少,也许是几千本,也许有上万本,如果以纯手动的方式按类别对图书进行管理,他们一定会累到吐血。

但是,如果我们有这些书的电子版,整件事做起来似乎就简单的多了,可能只用几秒钟就能完成。NLP万岁!

《用隐藏语义分析(LSA)进行主题建模(附Python代码)》
《用隐藏语义分析(LSA)进行主题建模(附Python代码)》

请看下面一小段话:

《用隐藏语义分析(LSA)进行主题建模(附Python代码)》
《用隐藏语义分析(LSA)进行主题建模(附Python代码)》

从三种颜色的高亮处我们可以知道,这些书一共有三个主题(或者概念)。一个好的主题模型可以分辨出相似的单词,并把它们归到一个群组中。在上面这段话中,最主要的主题就是绿色的主题2,通过它,我们可以了解到这段话的主要意思是有关假视频的。

在这篇文章中,我们将学习一种文本挖掘方法——主题建模(topic modeling)。这是提取主题的一种非常有用的技术,在NLP问题中会经常用到。

注:在阅读这篇文章前,我强烈推荐我们此前的另一篇文章:《12种降维方法终极指南(含Python代码)》,从中可以了解SVD、UMAP等概念,这些概念会在本文出现。

什么是主题模型?

主题模型可以看作是一种无监督技术,用于在多个文本文件中发现主题。但这些主题在自然中是抽象的,而且一段文本中可能含有多种主题。就目前来说,我们暂且将主题模型理解成一个黑箱,如下图所示:

《用隐藏语义分析(LSA)进行主题建模(附Python代码)》
《用隐藏语义分析(LSA)进行主题建模(附Python代码)》

黑箱(主题模型)将很多相似相关的词语聚集起来,称为主题。这些主题在文本中有特定的分布形态,每种主题都是通过它包含的不同单词比例确定的。

什么时候会用到主题建模?

回到我们开头说到的图书馆的例子,现在假设你要对几个数字化文本进行管理,如果数量不多,完全可以手动完成,但如果电子文本数量很大该怎么办?

这就需要用到NLP技术,对于这项任务,主题建模是必须用到的。

《用隐藏语义分析(LSA)进行主题建模(附Python代码)》

主题建模可以帮助使用者处理大量文本数据,找到文本中相似的多个词语,确定抽象的主题。除此之外,主题模型还可以用于搜索引擎,让搜索结果与搜索字符相匹配。

隐藏语义分析(LSA)概览

所有语言都有自己细小的特征,机器难以分辨(有时连人类都会认错)。比如有时不同的单词却表达相同含义,或者同一个单词却表达不同意思。

例如,看以下两个句子:

  • I liked his last novel quite a lot.
  • We would like to go for a novel marketing campaign.

在第一句话中,“novel”指的是一本书、小说,而在第二句话中它是形容词,意为“新的”。

我们可以轻易地分辨二者,因为我们理解了“novel”前后词语的意思。但是,机器无法理解这些概念,所以也不能理解词语所处的语境。这就需要用到隐藏语义分析(LSA)了,它通过分析词语周围的语境捕捉其中的隐藏概念,即主题。

所以,仅仅将词语映射到文本中并不能起到太大帮助,我们真正要做的是弄清楚词语背后隐藏的概念或主题,这就是LSA的目的。

实施LSA的步骤

假设我们有m个文本文档,总共有n个不同的词语,我们想从文档中所有文本数据中提取出k个主题,而k是由用户决定的。

  • 生成一个文本-单词矩阵,计算TF-IDF分数。

《用隐藏语义分析(LSA)进行主题建模(附Python代码)》
《用隐藏语义分析(LSA)进行主题建模(附Python代码)》

  • 之后,我们会将上述矩阵的维度降至k,利用奇异值分解(SVD)。
  • SVD将一个矩阵分解成三个其他的矩阵,假设我们想用SVD分解矩阵A,它就会将其分成矩阵U、S和VT(矩阵V的转置矩阵)。

《用隐藏语义分析(LSA)进行主题建模(附Python代码)》

《用隐藏语义分析(LSA)进行主题建模(附Python代码)》
《用隐藏语义分析(LSA)进行主题建模(附Python代码)》

矩阵UK的每一行都是对应文本的向量表示,这些向量的长度是k,即目标主题的数量。我们数据中的词语的向量表示可以在矩阵VK中找到。

通过SVD,我们得到了我们的数据中每个文本和词语的向量表示,然后用这些向量,我们可以找到相似的单词,利用余弦相似性找到相似的文本。

用Python实现LSA

首先下载所需要的库。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
pd.set_option("display.max_colwidth", 200)

在这篇文章中,我们会用到sklearn中的“20 Newsgroup”,下载地址:archive.ics.uci.edu/ml/datasets/Twenty+Newsgroups。代码如下:

from sklearn.datasets import fetch_20newsgroups
dataset = fetch_20newsgroups(shuffle=True, random_state=1, remove=('headers', 'footers', 'quotes'))
documents = dataset.data
len(documents)

输出:11314。

dataset.target_names
['alt.atheism',
'comp.graphics',
'comp.os.ms-windows.misc',
'comp.sys.ibm.pc.hardware',
'comp.sys.mac.hardware',
'comp.windows.x',
'misc.forsale',
'rec.autos',
'rec.motorcycles',
'rec.sport.baseball',
'rec.sport.hockey',
'sci.crypt',
'sci.electronics',
'sci.med',
'sci.space',
'soc.religion.christian',
'talk.politics.guns',
'talk.politics.mideast',
'talk.politics.misc',
'talk.religion.misc']

数据及共有11314个文本文档,分布在20各不同的newsgroup中。

数据预处理

开始之前,我们先尝试着清理文本数据。主要思想就是清除其中的标点、数字和特殊字符。之后,我们需要删除较短的单词,因为通常它们不会包含什么有用的信息。最后,我们将文本变为不区分大小写。

news_df = pd.DataFrame({'document':documents})
# removing everything except alphabets`
news_df['clean_doc'] = news_df['document'].str.replace("[^a-zA-Z#]", " ")
# removing short words
news_df['clean_doc'] = news_df['clean_doc'].apply(lambda x: ' '.join([w for w in x.split() if len(w)>3]))
# make all text lowercase
news_df['clean_doc'] = news_df['clean_doc'].apply(lambda x: x.lower())

之后我们要删除没有特别意义的停止词,例如“it”、“they”、“am”、“been”、“about”、“because”、“while”等等。为了实现这一目的,我们要对文本进行标记化,也就是将一串文本分割成独立的标记或单词。删除停止词之后,再把这些标记组合在一起。

from nltk.corpus import stopwords
stop_words = stopwords.words('english')
# tokenization
tokenized_doc = news_df['clean_doc'].apply(lambda x: x.split())
# remove stop-words
tokenized_doc = tokenized_doc.apply(lambda x: [item for item in x if item not in stop_words])
# de-tokenization
detokenized_doc = []
for i in range(len(news_df)):
t = ' '.join(tokenized_doc[i])
detokenized_doc.append(t)
news_df['clean_doc'] = detokenized_doc

文本-词语矩阵

这是通向主题建模的第一步。我们要用sklearn的TfidfVectorizer给1000个词语创造一个文本-词语矩阵。如果你有足够的计算力,可以增加更多数据。

from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer(stop_words='english',
max_features= 1000, # keep top 1000 terms
max_df = 0.5,
smooth_idf=True)
X = vectorizer.fit_transform(news_df['clean_doc'])
X.shape # check shape of the document-term matrix
(11314, 1000)

主题建模

下一步是将每个词语和文本用向量表示,我们会用到文本-词语矩阵并对他们降维。这里会用到TruncatedSVD执行矩阵的分解。

由于数据来自20个不同的分组,我们就假设文本数据有20个不同主题。

from sklearn.decomposition import TruncatedSVD
# SVD represent documents and terms in vectors
svd_model = TruncatedSVD(n_compOnents=20, algorithm='randomized', n_iter=100, random_state=122)
svd_model.fit(X)
len(svd_model.components_)
20

svd_model中的元素就是我们的主题,我们可以用svdmodel.components查看。最后,在20个主题中输入几个重要单词,看模型会做出什么反应。

terms = vectorizer.get_feature_names()
for i, comp in enumerate(svd_model.components_):
terms_comp = zip(terms, comp)
sorted_terms = sorted(terms_comp, key= lambda x:x[1], reverse=True)[:7]
print("Topic "+str(i)+": ")
for t in sorted_terms:
print(t[0])
print(" ")
Topic 0: like know people think good time thanks
Topic 1: thanks windows card drive mail file advance
Topic 2: game team year games season players good
Topic 3: drive scsi disk hard card drives problem
Topic 4: windows file window files program using problem
Topic 5: government chip mail space information encryption data
Topic 6: like bike know chip sounds looks look
Topic 7: card sale video offer monitor price jesus
Topic 8: know card chip video government people clipper
Topic 9: good know time bike jesus problem work
Topic 10: think chip good thanks clipper need encryption
Topic 11: thanks right problem good bike time window
Topic 12: good people windows know file sale files
Topic 13: space think know nasa problem year israel
Topic 14: space good card people time nasa thanks
Topic 15: people problem window time game want bike
Topic 16: time bike right windows file need really
Topic 17: time problem file think israel long mail
Topic 18: file need card files problem right good
Topic 19: problem file thanks used space chip sale

主题可视化

为了更方便地探索主题,我们应该对其可视化。当然,可是话不能大于三维,但是PCA或t-SNE等技术可以帮我们将高维数据降成低维进行可视化。这里,我们用另一种相对较新的技术,称作UMAP(Uniform Manifold Approximation and Projection)。

import umap
X_topics = svd_model.fit_transform(X)
embedding = umap.UMAP(n_neighbors=150, min_dist=0.5, random_state=12).fit_transform(X_topics)
plt.figure(figsize=(7,5))
plt.scatter(embedding[:, 0], embedding[:, 1],
c = dataset.target,
s = 10, # size
edgecolor='none'
)
plt.show()

《用隐藏语义分析(LSA)进行主题建模(附Python代码)》
《用隐藏语义分析(LSA)进行主题建模(附Python代码)》

如上所示,结果非常明显,每个点代表一段文本,不同的颜色表示20个分组。

完整代码地址:github.com/prateekjoshi565/latent_semantic_analysis

LSA的优缺点

如上所示,隐藏语义分析非常有用,但是它也有自己的缺点。在使用它之前,还需要了解它的优缺点。

优点:

  • LSA非常快,并且易于实施。
  • 结果很清晰,比单一的向量空间模型好得多。

缺点:

  • 由于它是一个线性模型,可能在非线性数据集上表现的不是很好。
  • LSA假设文本中的词语是高斯分布,可能不适用于所有问题。
  • LSA中涉及SVD,可能在出现新数据或更新时需要大量计算力。

推荐阅读
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Givenasinglylinkedlist,returnarandomnode'svaluefromthelinkedlist.Eachnodemusthavethe s ... [详细]
  • 图像因存在错误而无法显示 ... [详细]
  • 本文介绍了一个React Native新手在尝试将数据发布到服务器时遇到的问题,以及他的React Native代码和服务器端代码。他使用fetch方法将数据发送到服务器,但无法在服务器端读取/获取发布的数据。 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
author-avatar
2013丶峰峰最逆天_192
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有