文本挖掘入门课:主题模型让文本数据处理更幸福

全文共3480字,预计阅读时长7分钟

在解决自然语言处理的问题上,有一种文本挖掘的方法叫做主题模型,这是提取主题时一项极其有用的技术,那么什么是主题模型?何时使用主题模型?在Python中利用潜在语义分析来解决主题模型时,又应该注意哪些问题?读完了本文,相信你一定会有最实在的收获!

前言

你有没有去过维护得相当完善的图书馆?那些图书管理员非常让人佩服,他们把图书按照名称、内容或主题进行归类,一切都管理得井井有条。但是如果你扔给他们上千本图书,然后让他们按照书本的类型来整理好,他们可能一天都做不完,更不必说在一个小时之内了。

但是,如果这些书都是电子文本的话,整理工作可能就是几秒钟的事情,无需任何人力。自然语言处理万岁!

先来看一下下面的文本片段:

参照有底色的文本,可以看到一共有三个主题(或者概念)——主题1、主题2和主题3。一个好的主题模型能够辨别相似的词组,并把它们归为一类。上面的例子中最明显的主题是主题2,主要讲伪造影像的内容。

有意思吧?好!本文介绍了一个叫做主题模型的文本挖掘方法。这是提取主题时一项极其有用的技术,在应对自然语言处理问题的时候也非常常见。

提示:强烈建议你阅读这篇文章以对奇异值分解(SVD)和UMAP等概念进行了解(https://www.analyticsvidhya.com/blog/2018/08/dimensionality-reduction-techniques-python/)。本文是建立在这些概念之上的,因此先学习它们有利于巩固我们对基础概念的理解。

目录

什么是主题模型?

何时使用主题模型?

潜在语义分析(Latent Semantic Analysis, LSA)

在Python使用LSA

4.1 数据读取和检视

4.2 数据预处理

4.3 文本—词语矩阵

4.4主题模型

4.5 主题可视化

LSA的优缺点

主题模型的其他技术

1.什么是主题模型?

主题模型是一种无监督技术,用来发现各种文本文档中的主题。这些主题本质上是抽象的,也就是说彼此相关的单词会形成主题。 与此同时,单个文档中可以有多个主题。本文中暂时将主题模型理解为黑盒子,如下图所示:

这个黑盒子(也就是主题模型)把相关的词组划分为不同的类群,称之为主题。这些主题在文本中有特定的分布,每个主题都可以用不同比例的单词组合来定义。

2.何时使用主题模型?

回想一下之前提到的整理图书的任务。现在想象一下,你需要对电子文档来进行分类。当然,如果文档比较少的话,你可以手动完成这个任务。但是如果文档特别多的话怎么办?

这时候就要用自然语言处理技术了。而对于这个任务来说,将使用主题模型来完成。

主题模型可以帮助我们对海量的文本数据进行探索,对词组进行聚类,找到文本之间的相似性,并发现抽象的主题。如果你觉得这些任务还不够有挑战的话,主题模型还可以在搜索引擎中找到与搜索文本匹配的结果。是不是有点意思了?让我们继续深入探讨!

3.潜在语义分析(Latent Semantic Analysis, LSA)

所有语言都会有自身的复杂性和微妙特征,机器是难以捕捉这些内容的(有的时候人类自己也难以分辨)。比方说,不同的单词可能会有相同的含义,而同样的单词又可能有不同的含义。

让我们来看下面两个句子:

1. I liked his lastnovelquite a lot.

2. We would like to go for anovelmarketing campaign.

第一句话中,“novel”指代的是一本书,而第二句话中它表示新奇的、新颖的。

我们可以通过上下文轻易地推断这两个词的含义,但是机器就捕捉不到这个概念因为它不能理解单词所使用的语境。这时候就需要用到潜在语义分析了,它可以基于词组之间的上下文来揣摩背后的意思,也就是我们说的主题。

因此,单纯地把词组映射到文档中不一定有效果,我们需要的是搞懂词语背后的概念和主题。潜在语义分析就是能够找到隐藏主题的一种方法,现在让我们来深入探讨潜在语义分析的内部工作机制。

潜在语义分析的实现步骤

比方说我们有m个文档,文档中一共有n个唯一的词,我们要从所有文档中提取出k个主题。这里k表示主题的数量,是由用户自己定义的。

构造一个形如m * n的文档—词语矩阵,其中包含有TF-IDF分值。

然后,我们会把上述的矩阵用奇异值分解(SVD)的方法降到k维。

奇异值分解(SVD)把矩阵分解为三个矩阵。比如我们想要用奇异值分解(SVD)来降解矩阵A,那么我们会得到矩阵U、矩阵S和矩阵VT(矩阵V的转置矩阵)。矩阵Uk(文档—词组矩阵)的每一行都是文档的向量表示。这些向量的长度为k,也就是我们设定的主题数量。词组的向量表示可以在Vk(词语—主题矩阵)中找到。

这样一来,奇异值分解(SVD)把我们数据中的每个文档和词组都进行了向量化,每个向量的长度都是k。我们可以结合余弦相似度的方法,利用这些向量来找相似的词组和文档。

4.在Python中使用潜在语义分析

下面我们介绍如何在Python中利用潜在语义分析来解决主题模型的问题。打开Python之后,可以按照我下面提到的步骤开始运行代码。

4.1 数据读取和检视

首先要加载下面的包:

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=('headers', 'footers', 'quotes'))

documents = dataset.data

len(documents)

输出: 11,314

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

数据集包含来自20个不同新闻媒体的11,314份文本文档。

4.2 数据预处理

开始,我们要尽可能对文本数据进行清洗。基本原则就是利用正则表达式,用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 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

4.3 文本—词语矩阵

这是创建主题模型的第一步。我们会用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。如果你有足够的计算资源,我建议你可以把所有的词语都涵盖进去。

4.4 主题模型

下一步是把每个词语和文档用向量表示。我们会用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的要素(components)就是我们的主题,我们可以利用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 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

4.5 主题可视化

要知道我们的主题是否有特色,就需要进行可视化。当然,我们无法对三个维度以上的信息进行可视化。但是利用主成分分析(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的参数,看看图片会有什么变化。

文中所有代码都可以在GitHub中找到。

(https://github.com/prateekjoshi565/latent_semantic_analysis)

5.LSA的优缺点

上面的例子中我们可以看到潜在语义分析的威力,但是它还是有自身局限性的。我们需要了解LSA的优缺点,这样我们才知道什么时候选用它,什么时候应该尝试别的方法。

优点:

LSA速度快,容易实现。

效果好,比平面向量空间模型要好得多。

缺点:

它是一个线性模型,因此在非线性依赖关系的数据集中表现不佳。

LSA假设词语在文档中呈正态分布,但不是所有问题都满足这个假设。

LDA需要用到SVD,这是计算密集型的运算,在新数据加入后难以进行更新。

6.主题模型的其他技术

除了LSA之外,还有其他高级有效的主题模型技术,比如LDA和lda2Vec。我们还写过一篇介绍LDA的好文章,可以给大家提供参考。Lda2vec是一个高级得多的主题模型方法,它是基于word2vec单词嵌入的。

结束语

这篇文章中我分享了自己的学习收获。主题模型是一个非常有意思的东西,它能帮助你处理许多文本数据集。因此,我建议大家利用本文的代码来解决其他数据集的问题。享受文本挖掘吧!

留言 点赞 发个朋友圈

我们一起分享AI学习与发展的干货

编译组: 黄天元、胡婷

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181121B0R1ZU00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券