PRATEEK JOSHI作者万文菁校对李润嘉翻译

教你在Python中实现潜在语义分析

本文将通过拆解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数据派"基于清华,放眼世界",以扎实的理工功底闯荡“数据江湖”。发布全球大数据资讯,定期组织线下活动,分享前沿产业动态。了解清华大数据,敬请关注姐妹号“数据派THU”。

工程Python语义分析LSANLP文本挖掘
1
相关数据
隐含狄利克雷分布技术
Latent Dirichlet Allocation

隐含狄利克雷分布简称LDA(Latent Dirichlet allocation),是一种主题模型,它可以将文档集中每篇文档的主题按照概率分布的形式给出。同时它是一种无监督学习算法,在训练时不需要手工标注的训练集,需要的仅仅是文档集以及指定主题的数量k即可。此外LDA的另一个优点则是,对于每一个主题均可找出一些词语来描述它。LDA首先由Blei, David M.、吴恩达和Jordan, Michael I于2003年提出,目前在文本挖掘领域包括文本主题识别、文本分类以及文本相似度计算方面都有应用。

映射技术
Mapping

映射指的是具有某种特殊结构的函数,或泛指类函数思想的范畴论中的态射。 逻辑和图论中也有一些不太常规的用法。其数学定义为:两个非空集合A与B间存在着对应关系f,而且对于A中的每一个元素x,B中总有有唯一的一个元素y与它对应,就这种对应为从A到B的映射,记作f:A→B。其中,y称为元素x在映射f下的象,记作:y=f(x)。x称为y关于映射f的原象*。*集合A中所有元素的象的集合称为映射f的值域,记作f(A)。同样的,在机器学习中,映射就是输入与输出之间的对应关系。

潜在语义分析技术
Latent semantic analysis

潜在语义分析(LSA)是自然语言处理中的一种技术,特别是在分布式语义学中。传统的语义学通常研究字、词的含义以及词与词之间的关系,如同义,近义,反义等等。潜在语义分析探讨的是隐藏在字词背后的某种关系,这种关系不是以词典上的定义为基础,而是以字词的使用环境作为最基本的参考。这种思想来自于心理语言学家。他们认为,世界上数以百计的语言都应该有一种共同的简单的机制,使得任何人只要是在某种特定的语言环境下长大都能掌握那种语言。在这种思想的指导下,人们找到了一种简单的数学模型,这种模型的输入是由任何一种语言书写的文献构成的文库,输出是该语言的字、词的一种数学表达(向量)。字、词之间的关系乃至任何文章片断之间的含义的比较就由这种向量之间的运算产生。值接近1代表相似的单词,而值接近0代表非常不相似的单词。这项技术在信息检索中,被称作潜在语义索引(LSI)。

自然语言处理技术
Natural language processing

自然语言处理(英语:natural language processing,缩写作 NLP)是人工智能和语言学领域的分支学科。此领域探讨如何处理及运用自然语言;自然语言认知则是指让电脑“懂”人类的语言。自然语言生成系统把计算机数据转化为自然语言。自然语言理解系统把自然语言转化为计算机程序更易于处理的形式。

参数技术
parameter

在数学和统计学裡,参数(英语:parameter)是使用通用变量来建立函数和变量之间关系(当这种关系很难用方程来阐述时)的一个数量。

奇异值分解技术
Singular Value Decomposition

类似于特征分解将矩阵分解成特征向量和特征值,奇异值分解(singular value decomposition, SVD)将矩阵分解为奇异向量(singular vector)和奇异值(singular value)。通过分解矩阵,我们可以发现矩阵表示成数组元素时不明显的函数性质。而相比较特征分解,奇异值分解有着更为广泛的应用,这是因为每个实数矩阵都有一个奇异值分解,但未必都有特征分解。例如,非方阵型矩阵没有特征分解,这时只能使用奇异值分解。

t分布随机邻嵌入技术
t-SNE

t分布随机邻嵌入(t-SNE)是由Geoffrey Hinton和Laurens van der Maaten 开发的一种降维的机器学习算法。 这是一种非线性降维技术,特别适合将高维数据嵌入到二维或三维空间,然后可以在散点图中将其可视化。 具体来说,它通过二维或三维点对每个高维对象进行建模,使得类似的对象由附近的点建模,不相似的对象由远点建模。

反比文档频数权重评价方法技术
TF-IDF

tf-idf(英语:term frequency–inverse document frequency)是一种用于信息检索与文本挖掘的常用加权技术。tf-idf是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。tf-idf加权的各种形式常被搜索引擎应用,作为文件与用户查询之间相关程度的度量或评级。除了tf-idf以外,互联网上的搜索引擎还会使用基于链接分析的评级方法,以确定文件在搜索结果中出现的顺序。

主题模型技术
topic models

主题模型(Topic Model)在机器学习和自然语言处理等领域是用来在一系列文档中发现抽象主题的一种统计模型。直观来讲,如果一篇文章有一个中心思想,那么一些特定词语会更频繁的出现。比方说,如果一篇文章是在讲狗的,那“狗”和“骨头”等词出现的频率会高些。如果一篇文章是在讲猫的,那“猫”和“鱼”等词出现的频率会高些。而有些词例如“这个”、“和”大概在两篇文章中出现的频率会大致相等。但真实的情况是,一篇文章通常包含多种主题,而且每个主题所占比例各不相同。因此,如果一篇文章10%和猫有关,90%和狗有关,那么和狗相关的关键字出现的次数大概会是和猫相关的关键字出现次数的9倍。一个主题模型试图用数学框架来体现文档的这种特点。主题模型自动分析每个文档,统计文档内的词语,根据统计的信息来断定当前文档含有哪些主题,以及每个主题所占的比例各为多少。

word2vec技术
word2vec

Word2vec,为一群用来产生词向量的相关模型。这些模型为浅而双层的神经网络,用来训练以重新建构语言学之词文本。网络以词表现,并且需猜测相邻位置的输入词,在word2vec中词袋模型假设下,词的顺序是不重要的。 训练完成之后,word2vec模型可用来映射每个词到一个向量,可用来表示词对词之间的关系。该向量为神经网络之隐藏层。 Word2vec依赖skip-grams或连续词袋(CBOW)来建立神经词嵌入。Word2vec为托马斯·米科洛夫(Tomas Mikolov)在Google带领的研究团队创造。该算法渐渐被其他人所分析和解释。

词嵌入技术
Word embedding

词嵌入是自然语言处理(NLP)中语言模型与表征学习技术的统称。概念上而言,它是指把一个维数为所有词的数量的高维空间嵌入到一个维数低得多的连续向量空间中,每个单词或词组被映射为实数域上的向量。

文本挖掘技术
Text Mining

文本挖掘有时也被称为文字探勘、文本数据挖掘等,大致相当于文字分析,一般指文本处理过程中产生高质量的信息。高质量的信息通常通过分类和预测来产生,如模式识别。文本挖掘通常涉及输入文本的处理过程,产生结构化数据,并最终评价和解释输出。'高品质'的文本挖掘通常是指某种组合的相关性,新颖性和趣味性。

矩阵分解技术
Matrix Factorization

矩阵分解 (decomposition, factorization)是将矩阵拆解为数个矩阵的乘积,可分为三角分解、满秩分解、QR分解、Jordan分解和SVD(奇异值)分解等,常见的有三种:1)三角分解法 (Triangular Factorization),2)QR 分解法 (QR Factorization),3)奇异值分解法 (Singular Value Decomposition)。