#import modulesimport os.path
from gensim import corpora
from gensim.models import LsiModel
from nltk.tokenize import RegexpTokenizer
from nltk.corpus import stopwords
from nltk.stem.porter import PorterStemmer
from gensim.models.coherencemodel import CoherenceModel
import matplotlib.pyplot as plt
技术支持
defload_data(path,file_name):"""
Input : path and file_name
Purpose: loading text file
Output : list of paragraphs/documents and
title(initial 100 words considred as title of document)
"""
documents_list =[]
titles=[]withopen( os.path.join(path, file_name),"r")as fin:for line in fin.readlines():
text = line.strip()
documents_list.append(text)print("Total Number of Documents:",len(documents_list))
titles.append( text[0:min(len(text),100)])return documents_list,titles
技术支持
预处理数据
有了数据加载函数后,您需要对文本进行预处理。预处理包含以下步骤:
对文章进行分词
去除停用词
对文本进行词干提取
defpreprocess_data(doc_set):"""
Input : docuemnt list
Purpose: preprocess text (tokenize, removing stopwords, and stemming)
Output : preprocessed text
"""# initialize regex tokenizer
tokenizer = RegexpTokenizer(r'\w+')# create English stop words list
en_stop =set(stopwords.words('english'))# Create p_stemmer of class PorterStemmer
p_stemmer = PorterStemmer()# list for tokenized documents in loop
texts =[]# loop through document listfor i in doc_set:# clean and tokenize document string
raw = i.lower()
tokens = tokenizer.tokenize(raw)# remove stop words from tokens
stopped_tokens =[i for i in tokens ifnot i in en_stop]# stem tokens
stemmed_tokens =[p_stemmer.stem(i)for i in stopped_tokens]# add tokens to list
texts.append(stemmed_tokens)return texts
技术支持
准备语料
下一步是准备语料。在这里,您需要创建文档-词项矩阵以及词典。
defprepare_corpus(doc_clean):"""
Input : clean document
Purpose: create term dictionary of our courpus and Converting list of documents (corpus) into Document Term Matrix
Output : term dictionary and Document Term Matrix
"""# Creating the term dictionary of our courpus, where every unique term is assigned an index. dictionary = corpora.Dictionary(doc_clean)
dictionary = corpora.Dictionary(doc_clean)# Converting list of documents (corpus) into Document Term Matrix using dictionary prepared above.
doc_term_matrix =[dictionary.doc2bow(doc)for doc in doc_clean]# generate LDA modelreturn dictionary,doc_term_matrix
技术支持
使用 Gensim 创建 LSA 模型
创建好语料后,您可以用 LSA 生成模型。
defcreate_gensim_lsa_model(doc_clean,number_of_topics,words):"""
Input : clean document, number of topics and number of words associated with each topic
Purpose: create LSA model using gensim
Output : return LSA model
"""
dictionary,doc_term_matrix=prepare_corpus(doc_clean)# generate LSA model
lsamodel = LsiModel(doc_term_matrix, num_topics=number_of_topics, id2word = dictionary)# train modelprint(lsamodel.print_topics(num_topics=number_of_topics, num_words=words))return lsamodel
技术支持
确定主题数量
要想优化结果,还需要额外一步来确定最佳的主题数量。在这里,您将计算一致性分数来确定最佳主题数。
defcompute_coherence_values(dictionary, doc_term_matrix, doc_clean, stop, start=2, step=3):"""
Input : dictionary : Gensim dictionary
corpus : Gensim corpus
texts : List of input texts
stop : Max num of topics
purpose : Compute c_v coherence for various number of topics
Output : model_list : List of LSA topic models
coherence_values : Coherence values corresponding to the LDA model with respective number of topics
"""
coherence_values =[]
model_list =[]for num_topics inrange(start, stop, step):# generate LSA model
model = LsiModel(doc_term_matrix, num_topics=number_of_topics, id2word = dictionary)# train model
model_list.append(model)
coherencemodel = CoherenceModel(model=model, texts=doc_clean, dictionary=dictionary, coherence='c_v')
coherence_values.append(coherencemodel.get_coherence())return model_list, coherence_values技术支持
我们来绘制一致性分数的曲线。
defplot_graph(doc_clean,start, stop, step):
dictionary,doc_term_matrix=prepare_corpus(doc_clean)
model_list, coherence_values = compute_coherence_values(dictionary, doc_term_matrix,doc_clean,
stop, start, step)# Show graph
x =range(start, stop, step)
plt.plot(x, coherence_values)
plt.xlabel("Number of Topics")
plt.ylabel("Coherence score")
plt.legend(("coherence_values"), loc='best')
plt.show()
start,stop,step=2,12,1
plot_graph(clean_text,start,stop,step)技术支持
主题发现在多种场景中都很有用,例如对文档进行聚类、为信息检索与推荐而组织在线内容。许多内容平台和新闻机构使用主题模型向读者推荐文章。同样,招聘公司也用它来抽取职位描述并与候选人的技能进行匹配。以数据科学家为例,其工作核心就是从大量收集的数据中提取“知识”。而这些数据通常是非结构化的。您需要强大的工具与技术来分析并理解海量的非结构化数据。
主题建模是一种文本挖掘技术,它通过识别共现关键词来概括大规模文本信息集合。它有助于发现文档中的隐藏主题,用这些主题为文档加注,并组织大量非结构化数据。
主题建模
主题建模会自动从给定文档中发现隐藏的主题。它是一种无监督的文本分析算法,用于在给定文档中寻找一组词语,这些词语集合代表一个主题。一个文档可能同时关联多个主题。例如,一组词如“patient”“doctor”“disease”“cancer”“health”将代表“医疗健康”主题。与使用正则表达式的基于规则的文本检索不同,主题建模是另一种方法。
文本分类与主题建模的比较
文本分类是一个有监督的机器学习问题,即将文本文档或文章划分到预先定义的一组类别中。主题建模的过程是发现文本中共现词语的集合,这些彼此相关且共现的词语构成“主题”。它是一种无监督学习,因而可能的主题集合未知。主题建模也可用于解决文本分类问题:主题建模会识别文档中“出现的主题”,而文本分类则将文本划入某个单一类别。
潜在语义分析
LSA(Latent Semantic Analysis,潜在语义分析)亦称 LSI(Latent Semantic Index,潜在语义索引)。LSA 使用词袋(BoW)模型,生成词项-文档矩阵(词项在文档中的出现情况)。行表示词项,列表示文档。LSA 通过对文档-词项矩阵进行奇异值分解来学习潜在主题。LSA 通常用作降维或降噪技术。
奇异值分解(SVD)
SVD 是一种矩阵分解方法,将一个矩阵表示为两个(更准确地说,三个)矩阵的乘积。它在信号处理、心理学、社会学、气候与大气科学、统计学和天文学中都有广泛应用。
单位矩阵:主对角线元素全为 1,其余元素全为 0 的方阵。
对角矩阵:主对角线以外的元素全为 0 的矩阵。
奇异矩阵:行列式为 0 的矩阵,或不可逆的方阵。
确定最佳主题数
在主题建模中,如何确定 k(主题数)是最佳的?在给定语料中识别最佳主题数是一项挑战。我们可以采用以下方法来确定最佳主题数:
主题一致性是评估主题模型的常用指标。它基于潜变量模型。每个生成的主题对应一组词。在一致性度量中,您需要计算该主题内词语两两相似度得分的平均值/中位数。主题一致性分数越高,模型越好。
使用 Gensim 实现 LSA
导入所需库
加载数据
我们先创建一个数据加载函数来读取 articles.csv。您可以在此处下载数据。
预处理数据
有了数据加载函数后,您需要对文本进行预处理。预处理包含以下步骤:
准备语料
下一步是准备语料。在这里,您需要创建文档-词项矩阵以及词典。
使用 Gensim 创建 LSA 模型
创建好语料后,您可以用 LSA 生成模型。
确定主题数量
要想优化结果,还需要额外一步来确定最佳的主题数量。在这里,您将计算一致性分数来确定最佳主题数。
我们来绘制一致性分数的曲线。
这张图很好解读。横轴是主题数量,纵轴是一致性分数。在这些主题数量中,7 对应的分数最高,因此最佳主题数是 7。
运行上述所有函数
这里,我们用潜在语义分析发现了 7 个主题,其中部分主题有重叠。若要以更高准确度捕捉多重语义,我们需要尝试 LDA(潜在狄利克雷分配)。这部分留给您作为练习,试着用 Gensim 实现并分享您的看法。
LSA 的优缺点
LSA 算法最为简单,易于理解与实现。与向量空间模型相比,它通常能给出更好的结果。由于只涉及对文档-词项矩阵的分解,它也比其他算法更快。
潜在主题维度受矩阵秩的限制,无法随意扩展。LSA 分解得到的矩阵非常稠密,难以对单个维度进行索引。LSA 也难以捕捉词语的多重含义。与 LDA(潜在狄利克雷分配)相比,实现起来并不更容易,且准确率低于 LDA。
主题建模的应用场景
该技术的简单应用包括文本分析中的文档聚类、推荐系统与信息检索。更具体的用例包括:
结论
在本教程中,您了解了大量关于主题建模的内容。您学习了什么是主题建模、什么是潜在语义分析、如何构建相应模型、以及如何使用 LSA 生成主题。此外,您还回顾了奇异值分解与主题一致性分数等基础概念。
希望您现在可以将主题建模应用到自己的数据集上。感谢阅读!
如果您想进一步学习 Python,欢迎参与 DataCamp 的统计思维案例研究课程。