LDA模型伪代码块

Gensim的基本用法

Gensim非常适合用来实现各种文本模型、主题模型,包括tf-idf模型、LSI模型以及LDA模型。本节简单介绍一下Gensim中核心的三个数据结构、必须要掌握的一些基础用法,有了这些基本上可以快速编程实现LDA等主题模型。关于Gensim的一些特性,比如内存不依赖性、存储中间结果等本文本介绍了,感兴趣的小伙伴可以去看Gensim的官方文档。

Gensim的用法主要围绕着三个核心的概念而展开:corpus(语料库)model(模型)vector(向量)

假设我们现在有一个语料库,里面包括着9篇文档,每篇文档里面有若干单词:

image

现在我们要通过Gensim里面的一些API将其数字化,以便后续的计算处理。首先我们引入corpora模块里面的dictionary类,对这个语料库建立字典。在Gensim里面,对语料库建立字典是指把语料库中所有的词语统计并存在一个Python的字典中,如下所示:

image

之后我们调用dictionary类下面的doc2bow函数,将这个语料库转化为gensim里面 corpus,这是语料库中每篇文档都变成了一个list(从形状上看就是一个vetcor),list的每个元素是一个元组,元组的第一个元素代表词在字典中的编号,第二个元素代表这个词在这篇文档中出现的次数,注意,如果某个词在这篇文档中出现了0次,则不被记录到corpus中,以节省空间,所以这样的list也被称为稀疏向量(sparse vector)。所以这个语料库对应着如下的corpus:

image

以下是导入语料库、去掉stop word、建立字典、建立corpus对应的代码:

from gensim import corpora, models, similarities
from collections import defaultdict

# remove stop words and split each document, then we get texts
f = open('test-doc.txt')
stop_list = set('for a of the and to in'.split())
texts = [[word for word in line.strip().lower().split() if word not in stop_list] for line in f]
print('Text = ', texts)

# build the dictionary, a dict of (question, answer) pair

#建立一个词语字典对
dictionary = corpora.Dictionary(texts)
print(dictionary.token2id)

# transform the whole texts to vector(sparse)

#利用doc2bow把之前存好的字典转换成一个词频统计
corpus = [dictionary.doc2bow(text) for text in texts]
print(corpus)

现在,这个corpus可以认为是“原始的模型(model)”,因为它就是单纯的词的计数统计结果。现在,我们利用model模块下的TfidfModel方法以我们刚建立的corpus作为参数,初始化一个tfidf model,这样我们就得到了一个模型,这个模型可以把任何其他形式的的corpus转化为tfidf形式的corpus,即每个词对应的数值是这个词的tf-idf值,不再是单纯的词频计数了。是不是很方便呢?如果想转化为其他模型,按照同样的方式转化即可,目前,Gensim里面常用的基础文本模型还有LSI模型、LDA模型。将一个原始的模型转化为tf-idf模型的代码如下:

# create a transformation, from initial model to tf-idf model、

# 初始化tfidf模型
tfidf = models.TfidfModel(corpus)     # step 1 -- initialize a model
# "tfidf" is treated as a read-only object that can be used to convert any vector from the old representation
# (bag-of-words integer counts) to the new representation (TfIdf real-valued weights):
doc_bow = [(0, 1), (1, 1)]
print(tfidf[doc_bow])   # step 2 -- use the model to transform vectors
# apply a transformation to a whole corpus

# 传入之前的词频统计结果,应用这个模型
corpus_tfidf = tfidf[corpus]
for doc in corpus_tfidf:
    print(doc)

上述就是gensim包最最基础的几个用法了。下面我们就利用这些方法来实现一下LDA。

LDA编程实现

def load_stopword():
    f_stop = open('sw.txt')
    sw = [line.strip() for line in f_stop]
    f_stop.close()
    return sw

# remove the stop words
sw = load_stopword()
f = open('news_cn.dat', encoding='utf-8')    # load the text data
texts = [[word for word in line.strip().lower().split() if word not in sw] for line in f]
f.close()

接下来我们对这个语料库建立对应的字典,再把其从原始的corpus转为tf-idf模型corpus(其实直接转成LDA模型的corpus也可以,只是回顾一下上面的知识而已)。然后,我们调用model模块下面的Ldamodel方法将其转化为LDA模型的corpus,调用的时候有几个参数解释一下:

image

至此,通过我们导入的语料库,一个LDA模型已经训练完成,我们想要的信息都在这个模型里面了。这部分代码如下:
1 做成字典表,2 做词频统计,3 做tfidf,4把tfidf和字典表放到models.LdaModel训练

# build the dictionary for texts
dictionary = corpora.Dictionary(texts)
dict_len = len(dictionary)
# transform the whole texts to sparse vector
corpus = [dictionary.doc2bow(text) for text in texts]
# create a transformation, from initial model to tf-idf model
corpus_tfidf = models.TfidfModel(corpus)[corpus]
num_topics = 9
# create a transformation, from tf-idf model to lda model
lda = models.LdaModel(corpus_tfidf, num_topics=num_topics, id2word=dictionary,
      alpha=0.01, eta=0.01, minimum_probability=0.001, update_every = 1, chunksize = 100, passes = 1)

LDA主题提取效果图展示

这个语料库中一共有2043篇文档,我们提取出了9中主题,每个主题我们展示了其概率最大的7个词语以及对应的概率,同时我们输出了前9个文档分别属于这九个主题的概率。

首先,我们打印出来了前9个文档分别属于这九个主题的概率,代码如下:
1 使用lda.get_document_topic(tfidf)

# 打印前9个文档的主题
num_show_topic = 9  # 每个文档显示前几个主题
print('下面,显示前9个文档的主题分布:')
doc_topics = lda.get_document_topics(corpus_tfidf)  # 所有文档的主题分布
for i in range(9):
    topic = np.array(doc_topics[i])
    topic_distribute = np.array(topic[:, 1])
    topic_idx = list(topic_distribute)
    print('第%d个文档的 %d 个主题分布概率分别为:' % (i, num_show_topic))
    print(topic_idx)

输出结果如图所示:

image

接下来,我们打印出每个主题其概率最大的7个词语以及对应的概率,代码如下:??

num_show_term = 7   # 每个主题下显示几个词
for topic_id in range(num_topics):
    print('第%d个主题的词与概率如下:\t' % topic_id)
    term_distribute_all = lda.get_topic_terms(topicid=topic_id)
    term_distribute = term_distribute_all[:num_show_term]
    term_distribute = np.array(term_distribute)
    term_id = term_distribute[:, 0].astype(np.int) 
    print('词:\t', end='  ')
    for t in term_id:
        print(dictionary.id2token[t], end=' ')
    print('\n概率:\t', term_distribute[:, 1])

输出结果如图所示:

image

在可视化部分,我们首先画出了九个主题的7个词的概率分布图,代码如下:

mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
for i, k in enumerate(range(num_topics)):
    ax = plt.subplot(3, 3, i+1)
    item_dis_all = lda.get_topic_terms(topicid=k)
    item_dis = np.array(item_dis_all[:num_show_term])
    ax.plot(range(num_show_term), item_dis[:, 1], 'b*')
    item_word_id = item_dis[:, 0].astype(np.int)
    word = [dictionary.id2token[i] for i in item_word_id]
    ax.set_ylabel(u"概率")
    for j in range(num_show_term):
        ax.text(j, item_dis[j, 1], word[j], bbox=dict(facecolor='green',alpha=0.1))
plt.suptitle(u'9个主题及其7个主要词的概率', fontsize=18)
plt.show()

效果图如下所示:

image

接着我们画出了前9篇文档分别属于这9个主题的概率分布图,代码如下:

for i in range(9):
    ax = plt.subplot(3, 3, i + 1)
    doc_item = np.array(doc_topics[i])
    doc_item_id = np.array(doc_item[:, 0])
    doc_item_dis = np.array(doc_item[:, 1])
    ax.plot(doc_item_id, doc_item_dis, 'r*')
    for j in range(doc_item.shape[0]):
        ax.text(doc_item_id[j], doc_item_dis[j], '%.3f' % doc_item_dis[j])
plt.suptitle(u'前9篇文档的主题分布图', fontsize=18)
plt.show()

效果图如下所示:

image

好了,以上就是这篇文章要讲解的三大主要内容了。利用Gensim实现了一个LDA模型后,对LDA应该会有更加直观清晰的认识。

你可能感兴趣的:(LDA模型伪代码块)