第 7 章 主题模型

不论 DTM 还是 TF-IDF 矩阵都以词频为基础作为文档的特征表示,而一词多义或多词一义的情况并不能通过词频反映出来,也就是说忽略了文本中的语意信息,导致进一步文本分析的精度较低,本章介绍的主题模型就是为了解决这一问题而提出的,主题模型可以将文档映射到指定维度的语义空间,利用各个文档在语意空间的分布可以计算文档的相似度,也可以进一步进行文档分类或聚类处理。本章内容安排如下:7.1 节和 7.2 节分别介绍 LSI 模型和 LDA 模型的原理及构建方式,7.3 节则利用主题模型得到的主题分布结果,对已经标注的文本数据进行相似度计算。

7.1 LSI

7.1.1 LSI 简介

LSI 是 Latent Semantic Indexing 的缩写,可以译为潜在语意索引,也常被称为 Latent Semantic Analysis(LSA)。Scott Deerwester 等在 1988 年提出了 LSI,其核心思路为将文档或词矩阵进行奇异值分解(Singular Value Decomposition, SVD),使得文档和文档或者文档和查询之间的相似性在简化的潜在语义空间中得以表达。由于奇异值分解的方法本身是对文档特征的排序,可以通过限制奇异值的个数对数据进行降噪和降维,可以较好的挖掘文档的语义信息。

奇异值分解:对于 mxn 阶矩阵 $M$ ,存在矩阵分解使得 $M=U\Sigma V^$ ,其中,矩阵 $V$ 和 $U$ 的列分别为 $M^M$ 与 $MM^$ 的特征向量,矩阵 $\Sigma$ 对角线上的元素为 $M^M$ 及 $MM^*$ 的特征值的非零平方根,这些元素也被称为奇异值。

在文本数据分析中,LSI 的处理对象通常为文档数据集在空间向量模型中的矩阵映射,或者是经过计算得到的 TF-IDF 矩阵,根据奇异值分解结果,LSI 会将文档样本投射到对应维数的潜在语义空间中,是我们能够在较低的维度下判断文档样本的类型特征,对于文本的分类与聚类有明显的帮助。

7.1.2 利用 gensim 构建 LSI 模型

gensim 库 models 包中的 lsimodel 模块中定义了 LsiModel 类及相关方法,实现快速的 SDV 分解,将文档映射到潜在语义空间,LsiModel 类的实例化方式为:实例=LsiModel(corpus=None, num_topics=200, id2word=None, chunksize=20000, decay=1.0, distributed=False, onepass=True, power_iters=2, extra_samples=100)

参数说明:

corpus:用该参数传入的文档语料将会被用来训练模型

id2word:用于设置构建矩阵的词典

num_topics:潜在语义空间维度

chunksize:一次训练过程中使用的文件块大小,该值较大有利于提高训练速度,但是会占用较大的内存

distributed:是否开启分布式计算

onepass:是否使用多次随机算法,取值为 True 时,使用多次随机算法,否则使用前端算法

power_iters 和 extra_samples:这两个参数都会影响算法的准确性,迭代参数 ower_iters 的增加会增强算法的准确性,更详细的参数影响关系请参见 6.6.4 提供的深度阅读材料。

相关方法及属性如下:

(1)show_topic 方法

show_topic 方法用于返回指定的主题,调用方式为:实例.show_topic(topicno, topn=10)

参数说明:

topicno:待返回的主题序号

topn:返回的词汇数,默认取值为 10,按对主题贡献度(正值、负值均有)从大到小排序

(2)show_topics 方法

show_topics 方法可以同时返回多个主题,调用方式为:实例.show_topics(num_topics=-1, num_words=10, log=False, formatted=True)

参数说明:

num_topics:控制返回的主题数,默认取值为-1,表示返回全部主题

num_words:每个主题包含的词汇数,默认取值为 10

formatted:取值为 True 时以字符串形式返回词汇及相应概率,取值为 False 时返回词汇和相应概率组成的元组

log:取值为 True 时,同时将结果输出到日志中

(3)“[]” 方法

“[]” 方法可以返回文档在各个主题的分布,调用方式为:实例[document]

(4) add_documents 方法

add_documents 方法可以使用新的文本语料更新已有的 SDV 分解结果,调用方式为:实例.add_documents(corpus, chunksize=None, decay=None),其中参数 corpus 即为新增文本,当参数 decay 取值小于 1 时,侧重于使用新的语料进行语意定向,而不是原有语料

(5)print_debug 方法

print_debug 方法用于输出不同主题的重要词汇,与 show_topics() 方法不同,该方法输出的词汇更能突出不同主题之间的差异,结果更易于解释,调用方式为:实例.print_debug(num_topics=5, num_words=10)

例 1 本例中 corpus 包含的文本是两类新闻标题:环境和教育,利用 LSI 模型将语料映射到二维主题空间


In [1]:from gensim import corpora,models
       from gensim.models.lsimodel import LsiModel
       title = ['Beijing lifts red alert with smog set to disperse',
                 'Source of major pollutant in China smog revealed',
                 'Xi stresses clean energy use to reduce smoggy days',
                 'New Zealand university to open innovation center in China',
                 'School combines soccer with kung fu to train players']
       # 简单分词处理
       texts = [[word for word in document.lower().split()] for document in corpus]
       # 构建词典
       dictionary = corpora.Dictionary(texts)
       # 得到词汇词频
       corpus = [dictionary.doc2bow(text) for text in texts]
       # 构建 TF-IDF 矩阵
       tfidf_model = models.TfidfModel(corpus) 
       corpus_tfidf = tfidf_model[corpus]
       # 以 TF-IDF 矩阵构建 2 个主题的 LSI
       lsi = LsiModel(corpus=corpus_tfidf,id2word=dictionary,num_topics=2)
       # 查看主题关键词
       lsi.show_topics (num_topics=-1, num_words=10)
Out[1]:[(0,
         u'0.275*"in" + 0.275*"china" + 0.264*"of" + 0.264*"major" + 0.264*"source" + 0.264*"revealed" + 0.264*"pollutant" + 0.229*"smog" + 0.220*"new" + 0.220*"zealand"'),
        (1,
         u'-0.270*"with" + -0.251*"school" + -0.251*"soccer" + -0.251*"kung" + -0.251*"train" + -0.251*"players" + -0.251*"combines" + -0.251*"fu" + -0.224*"beijing" + -0.224*"lifts"')]
In [2]:# 返回各个文档在两个主题上的分布
       for i in corpus_tfidf:
           print lsi[i]
Out[2]:[(0, 0.40112933717769061), (1, -0.60176390850417838)]
       [(0, 0.72129310654139789), (1, 0.18444288880409218)]
       [(0, 0.026674205908750175), (1, -0.058666737715942399)]
       [(0, 0.63620409768707431), (1, 0.37352685238560701)]
       [(0, 0.18038797936342355), (1, -0.70806631562713807)]

利用各个文档在不同主题上的分布可以计算文档间的相似度,也可以采用不同的聚类方法进行文档聚类。

7.1.3 利用 sklearn 构建 LSI 模型

sklearn 库 decomposition 包也提供了 truncated_svd(截断奇异值分解)模块构建 LSI 模型,主要利用其下定义的类 TruncatedSVD 对文档矩阵进行处理,支持随机规划求解以及使用 ARPACK (http://www.caam.rice.edu/software/ARPACK/)的朴素算法,更多细节可以阅读官方文档(http://scikit-learn.org/stable/modules/decomposition.html#lsa)。该类的初始化方式为:实例=TruncatedSVD(n_components=2, algorithm='randomized', n_iter=5, random_state=None, tol=0.0)

参数说明:

n_components:待输出的语意空间的维度,一定小于原始数据的特征项数目,默认取值为 2,便于可视化展示,在构建 LSI 模型时,建议取值 100

algorithm:用于求解的算法,支持 “arpack” 和 “randomized” 两种,默认取值为 “randomized”。

n_iter:当算法为 “randomized” 时,用该参数设置算法迭代次数,默认取值为 5

random_state:伪随机数生成器

tol:当算法为 “arpack” 时,用该参数设置残差容忍下限

相关方法及属性如下:

@补充方法属性列表

例 2 利用上例 title 构建 LSI 模型


In [3]:import sklearn
       from sklearn.decomposition import TruncatedSVD
       from sklearn.feature_extraction.text import TfidfVectorizer
       # 利用 TfidfVectorizer 计算 TF-IDF 矩阵
       vectorizer = TfidfVectorizer()
       corpus_tfidf=vectorizer.fit_transform(title).toarray()
       # 构建二维语义空间
       svd = TruncatedSVD(n_components=2)
       svd.fit(corpus_tfidf) 
Out[3]:TruncatedSVD(algorithm='randomized', n_components=2, n_iter=5,
       random_state=None, tol=0.0)
In [4]:svd.fit_transform(corpus_tfidf)
Out[4]:array([[ 0.53998204,  0.41174044],
              [ 0.614138  , -0.48422793],
              [ 0.23842791,  0.32792508],
              [ 0.61358726, -0.40925992],
              [ 0.39402097,  0.62935865]])

results matching ""

    No results matching ""