教你在Python中实现潜在语义分析(附代码)

2018 年 12 月 6 日 数据派THU

作者:PRATEEK JOSHI

翻译:李润嘉

校对:万文菁

本文约3400字,建议阅读15分钟。

本文将通过拆解LSA的原理及代码实例来讲解如何运用LSA进行潜在语义分析。


介绍


你有没有去过那种运营良好的图书馆?我总是对图书馆馆员通过书名、内容或其他主题保持一切井井有条的方式印象深刻。但是如果你给他们数千本书,要求他们根据书的种类整理出来,他们很难在一天内完成这项任务,更不用说一小时!

 

但是,如果这些书以电子的形式出现,就难不倒你了,对吧?所有的整理会在几秒之间完成,并且不需要任何人工劳动。自然语言处理(NLP)万岁!

 

看看下面这段话:



你可以从高亮的词语中总结出,这段话有三个主题(或概念)——主题1、主题2和主题3。一个良好的主题模型可以识别出相似的词语并将它们放在一组或一个主题下。上述示例中最主要的主题是主题2,表明这段文字主要关于虚假视频。

 

是不是很好奇?太好了!在本文中,我们将学习一种叫做主题建模的文本挖掘方法。这是一种非常有用的提取主题的技术,在面对NLP挑战时你会经常使用到它。

 

注意:我强烈建议您通读这篇文章了解SVD和UMAP等定义。它们在本文中经常出现,因此对它们有基本的理解有助于巩固这些概念。

 

目录


1. 什么是主题模型?

2. 何时使用主题建模?

3. 潜在语义分析(LSA)概述

4. 在Python中实现LSA

  • 数据读取和检查

  • 数据预处理

  • 文档-词项矩阵(Document-Term Matrix)

  • 主题建模

  • 主题可视化

5.  LSA的优缺点

6.  其他主题建模技术

 

什么是主题模型?


主题模型可定义为一种在大量文档中发现其主题的无监督技术。这些主题本质上十分抽象,即彼此相关联的词语构成一个主题。同样,在单个文档中可以有多个主题。我们暂时将主题模型理解为一个如下图所示的黑盒子:



这个黑盒子(主题模型)将相似和相关的词语聚集成簇,称为主题。这些主题在文档中具有特定的分布,每个主题都根据它包含的不同单词的比例来定义。

 

何时使用主题建模?


回想一下刚才提到的将相似的书籍整理到一起的例子。现在假设你要对一些电子文档执行类似的任务。只要文档的数量不太多,你就可以手动完成。但是如果这些文档的数量非常多呢?

 

这就是NLP技术脱颖而出的地方。对于这个任务而言,主题建模非常适用。



主题建模有助于挖掘海量文本数据,查找词簇,文本之间的相似度以及发现抽象主题。如果这些理由还不够引人注目,主题建模也可用于搜索引擎,判断搜索字段与结果的匹配程度。越来越有趣了,是不是?那么,请继续阅读!

 

潜在语义分析(LSA)概述


所有语言都有自己的错综复杂和细微差别,比如一义多词和一词多义,这对机器而言很难捕捉(有时它们甚至也被人类误解了!)。

 

例如,如下两个句子:


1. I liked his last novel quite a lot.

2. We would like to go for a novel marketing campaign.

 

在第一个句子中,'novel' 指一本书,而在第二个句子中,它的含义是新奇的、新颖的。

 

我们能够轻松地区分这些单词,是因为我们可以理解这些词背后的语境。但是,机器并不能捕捉到这个概念,因为它不能理解单词的上下文。这就是潜在语义分析(LSA)发挥作用的地方,它可以利用单词所在的上下文来捕捉隐藏的概念,即主题。

 

因此,简单地将单词映射到文档并没有什么用。我们真正需要的是弄清楚单词背后的隐藏概念或主题。LSA是一种可以发现这些隐藏主题的技术。现在我们来深入探讨下LSA的内部工作机制。


LSA的实施步骤

 

假设我们有m篇文档,其中包含n个唯一词项(单词)。我们希望从所有文档的文本数据中提取出k个主题。主题数k,必须由用户给定。

 

  • 生成一个m×n维的文档-词项矩阵(Document-Term Matrix),矩阵元素为TF-IDF分数

  • 然后,我们使用奇异值分解(SVD)把上述矩阵的维度降到k(预期的主题数)维

  • SVD将一个矩阵分解为三个矩阵。假设我们利用SVD分解矩阵A,我们会得到矩阵U,矩阵S和矩阵VT(矩阵V的转置)


矩阵Uk(document-term matrix)的每个行向量代表相应的文档。这些向量的长度是k,是预期的主题数。代表数据中词项的向量可以在矩阵Vk(term-topic matrix)中找到。


  • 因此,SVD为数据中的每篇文档和每个词项都提供了向量。每个向量的长度均为k。我们可以使用余弦相似度的方法通过这些向量找到相似的单词和文档。


在Python中实现LSA

 

是时候启动Python并了解如何在主题建模问题中应用LSA了。开启Python环境后,请按照如下步骤操作。


数据读取和检查


在开始之前,先加载需要的库。


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"数据集,可从这里下载,然后按照代码继续操作。


from sklearn.datasets import fetch_20newsgroups

dataset = fetch_20newsgroups(shuffle=True, random_state=1, remove=('header','footers',quotes'))

documents = dataset.data

len(documents)


Output: 11,314


Dataset.target_names


 ['alt.atheism',

'comp.graphics',

'comp.os.ms-windows.misc',

'comp.sys.ibm.pc.hardware',

'comp.sys.mac.hardware',

'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']


该数据集包含分布在20个不同新闻组中的11314篇文档。

 

数据预处理

 

首先,我们尝试尽可能地清理文本数据。我们的想法是,使用正则表达式replace("[^a-zA-Z#]", " ")一次性删除所有标点符号、数字和特殊字符,这个正则表达式可以替换除带空格的字母之外的所有内容。然后删除较短的单词,因为它们通常并不包含有用的信息。最后,将全部文本变为小写,使得大小写敏感失效。


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 the 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 ifitem 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


文档-词项矩阵(Document-Term Matrix)

 

这是主体建模的第一步。我们将使用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)


我们也可以使用全部词项来创建这个矩阵,但这回需要相当长的计算时间,并占用很多资源。因此,我们将特征的数量限制为1000。如果你有计算能力,建议尝试使用所有词项。

 

主题建模

 

下一步是将每个词项和文本表示为向量。我们将使用文本-词项矩阵,并将其分解为多个矩阵。我们将使用sklearn的TruncatedSVD来执行矩阵分解任务。

 

由于数据来自20个不同的新闻组,所以我们打算从文本数据中提取出20个主题。可以使用n_components参数来制定主题数量。


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的组成部分即是我们的主题,我们可以通过svd_model.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 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


主题可视化

 

为了找出主题之间的不同,我们将其可视化。当然,我们无法可视化维度大于3的数据,但有一些诸如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()



如上所示,结果非常漂亮。每个点代表一个文档,颜色代表20个新闻组。我们的LSA模型做得很好。可以任意改变UMAP的参数来观察其对图像的影响。

 

可在此找到本文的完整代码。

 

LSA的优缺点

 

如上所述,潜在语义分析非常有用,但是确实有其局限性。因此,对LSA的优缺点都有充分的认识十分重要,这样你就知道何时需要使用LSA,以及何时需要尝试其他方法。

 

优点:


  • LSA快速且易于实施。

  • 它的结果相当好,比简单的向量模型强很多。

 

缺点:


  • 因为它是线性模型,因此在具有非线性依赖性的数据集上可能效果不佳。

  • LSA假设文本中的词项服从正态分布,这可能不适用于所有问题。

  • LSA涉及到了SVD,它是计算密集型的,当新数据出现时难以更新。

 

其他主题建模技术

 

除了LSA,还有其他一些先进并有效的主题建模技术,如LDA(Latent Dirichlet Allocation)和Ida2Vec。我们有一篇关于LDA的精彩文章,你可以在这里查看。Ida2vec是一个基于word2vec单词嵌入的更先进的主题建模技术。如果你想对它有更多了解,可以在下方的评论中留言,我们很乐意回答你的问题。

 

尾记

 

本文意于与大家分享我的学习经验。主题建模是个非常有趣的话题,当你在处理文本数据集时会用到许多技巧和方法。因此,我敦促大家使用本文中的代码,并将其应用于不同的数据集。如果您对本文有任何疑问或反馈,请与我们联系。快乐地去挖掘文本吧!


原文标题:

Text Mining 101: A Stepwise Introduction to Topic Modeling using Latent Semantic Analysis (using Python)

原文链接:

https://www.analyticsvidhya.com/blog/2018/10/stepwise-guide-topic-modeling-latent-semantic-analysis/


译者简介

李润嘉,首都师范大学应用统计硕士在读。对数据科学和机器学习兴趣浓厚,语言学习爱好者。立志做一个有趣的人,学想学的知识,去想去的地方,敢想敢做,不枉岁月。

翻译组招募信息

工作内容:需要一颗细致的心,将选取好的外文文章翻译成流畅的中文。如果你是数据科学/统计学/计算机类的留学生,或在海外从事相关工作,或对自己外语水平有信心的朋友欢迎加入翻译小组。

你能得到:定期的翻译培训提高志愿者的翻译水平,提高对于数据科学前沿的认知,海外的朋友可以和国内技术应用发展保持联系,THU数据派产学研的背景为志愿者带来好的发展机遇。

其他福利:来自于名企的数据科学工作者,北大清华以及海外等名校学生他们都将成为你在翻译小组的伙伴。


点击文末“阅读原文”加入数据派团队~

转载须知

如需转载,请在开篇显著位置注明作者和出处(转自:数据派ID:datapi),并在文章结尾放置数据派醒目二维码。有原创标识文章,请发送【文章名称-待授权公众号名称及ID】至联系邮箱,申请白名单授权并按要求编辑。

发布后请将链接反馈至联系邮箱(见下方)。未经许可的转载以及改编者,我们将依法追究其法律责任。



点击“阅读原文”拥抱组织

登录查看更多
8

相关内容

【实用书】学习用Python编写代码进行数据分析,103页pdf
专知会员服务
190+阅读 · 2020年6月29日
【干货书】用于概率、统计和机器学习的Python,288页pdf
专知会员服务
280+阅读 · 2020年6月3日
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
223+阅读 · 2020年3月22日
【干货书】机器学习Python实战教程,366页pdf
专知会员服务
330+阅读 · 2020年3月17日
机器学习速查手册,135页pdf
专知会员服务
335+阅读 · 2020年3月15日
《深度学习》圣经花书的数学推导、原理与Python代码实现
算法与数据结构Python,369页pdf
专知会员服务
160+阅读 · 2020年3月4日
【新书】Pro 机器学习算法Python实现,379页pdf
专知会员服务
195+阅读 · 2020年2月11日
基于句子嵌入的无监督文本摘要(附代码实现)
机器学习领域必知必会的12种概率分布(附Python代码实现)
算法与数学之美
21+阅读 · 2019年10月18日
Github项目推荐 | gensim - Python中的主题建模
AI研习社
15+阅读 · 2019年3月16日
教你用Python进行自然语言处理(附代码)
数据派THU
6+阅读 · 2018年3月28日
快乐的迁移到 Python3
Python程序员
5+阅读 · 2018年3月25日
一文读懂FM算法优势,并用python实现!(附代码)
一文学会最常见的10种NLP处理技术(附资源&代码)
一文详解聚类和降维(附实例、代码)
数据派THU
7+阅读 · 2017年9月3日
Neural Image Captioning
Arxiv
5+阅读 · 2019年7月2日
Arxiv
12+阅读 · 2019年4月9日
VIP会员
相关VIP内容
【实用书】学习用Python编写代码进行数据分析,103页pdf
专知会员服务
190+阅读 · 2020年6月29日
【干货书】用于概率、统计和机器学习的Python,288页pdf
专知会员服务
280+阅读 · 2020年6月3日
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
223+阅读 · 2020年3月22日
【干货书】机器学习Python实战教程,366页pdf
专知会员服务
330+阅读 · 2020年3月17日
机器学习速查手册,135页pdf
专知会员服务
335+阅读 · 2020年3月15日
《深度学习》圣经花书的数学推导、原理与Python代码实现
算法与数据结构Python,369页pdf
专知会员服务
160+阅读 · 2020年3月4日
【新书】Pro 机器学习算法Python实现,379页pdf
专知会员服务
195+阅读 · 2020年2月11日
相关资讯
基于句子嵌入的无监督文本摘要(附代码实现)
机器学习领域必知必会的12种概率分布(附Python代码实现)
算法与数学之美
21+阅读 · 2019年10月18日
Github项目推荐 | gensim - Python中的主题建模
AI研习社
15+阅读 · 2019年3月16日
教你用Python进行自然语言处理(附代码)
数据派THU
6+阅读 · 2018年3月28日
快乐的迁移到 Python3
Python程序员
5+阅读 · 2018年3月25日
一文读懂FM算法优势,并用python实现!(附代码)
一文学会最常见的10种NLP处理技术(附资源&代码)
一文详解聚类和降维(附实例、代码)
数据派THU
7+阅读 · 2017年9月3日
Top
微信扫码咨询专知VIP会员