lda主题模型python实现篇

个人博客地址:http://xurui.club/
最近在做一个动因分析的项目,自然想到了主题模型LDA。这次先把模型流程说下,原理后面再讲。
lda实现有很多开源库,这里用的是gensim.

1 文本预处理

大概说下文本的样子,LDA是无监督模型,也就是说不需要标签,只要传入文本就好。LDA要学习文档-主题分布和主题-词分布,所以我们把一个人的数据join在一起作为一条文档。对文档进行分词,使用的jieba分词工具包。注意,这里要做去停用词处理,包括标点和一些没用的词,如“呵呵”,“哈哈”。做项目时,第一版没有去无用词,最后提出的主题都是“你”“我”“他”“你好”这样的东西,去掉之后可以较好提高结果质量。

2 将上步处理的结果进行格式化表示

即将所有文档数表示成m*n的矩阵D,m表示有m篇文档,n表示这篇文档有n个词,n不定长。

3 生成词典

用gensim.corpora.Dictionary包
这个包讲下吧

from gensim.corpora import Dictionary
text = [['我', '想吃', '大龙虾', '和', '烤猪蹄']]
dictionary = Dictionary(text)
print((dictionary))
doc = dictionary.doc2bow(['我', '想吃', '大龙虾', '和', '我','你','烤猪蹄'])
print(doc)

#####output#####
Dictionary(5 unique tokens: ['我', '大龙虾', '想吃', '和', '烤猪蹄'])
[(0, 1), (1, 1), (2, 2), (3, 1), (4, 1)]

可以看出,我们把我想吃大龙虾和烤猪蹄编成字典,共五个词,这里输出结果里看不出是个字典,其实是有下标的,0对应我,1对应大龙虾,…4对应烤猪蹄。
然后我们在下一步将文本变成词袋,这里用的文本是[‘我’, ‘想吃’, ‘大龙虾’, ‘和’, ‘我’,’你’,’烤猪蹄’],注意文本格式也是词为元素的列表。这句话是我自己构造的,只是为了说两点,语法请忽略。第一点:“我”这个词出现了两次,所以下标为2的地方,值为2;第二点,“你”这个词出现了1次,可是在词典中没有,所有直接被忽略。

这样就可以用字典,将文本表示成词袋模型,词袋模型不懂的,见我另一篇文章,自然语言处理NLP的词如何表示。当我们做完了LDA模型后,对于新的文本,我们想看下它所在的主题分布,就要使用该字典再进行词袋编码,也就是说这个字典,我们以后也会用到,所以,我们在这里把词典保存起来。
保存词典可以用pickle,很好用。不懂的见我另一篇文章,神奇的pickle。

4 训练LDA模型

这里用的是gensim.models.ldamodel包
ldamodel = LdaModel(text, num_topics=10, id2word=dictionary, passes=20)
使用这句话就可以直接训练LDA模型了,讲一下参数吧。
text:文本,已经表示成词袋了。
num_topics: 提取的主题数
id2word:词典
passes:类似于在机器学习中常见的epoch,也就是训练了多少轮。

然后我们得到了训练好的ldamodel.用这个模型可以做哪些事情呢?

5 ldamodel使用

可以输出这个模型的各个主题下的主题词

print(ldamodel.print_topics(num_topics=10, num_words=10))
###output###
[(0, '0.015*"说" + 0.011*"吃" + 0.008*"想" + 0.007*"睡" + 0.005*"\u2005" + 0.005*"做" + 0.005*"明天" + 0.005*"买" + 0.005*"干嘛" + 0.005*"玩"'),
 (1, '0.017*" " + 0.010*"说" + 0.004*"吃" + 0.004*"许华升" + 0.004*"\x14" + 0.004*"想" + 0.003*"做" + 0.003*"买" + 0.003*"ÿ" + 0.003*"钱"'),
 (2, '0.008*"com" + 0.007*" " + 0.004*"手机" + 0.003*"女" + 0.003*"说" + 0.003*"www" + 0.003*"cc" + 0.002*"号" + 0.002*"qq" + 0.002*"视频"'), 
 (3, '0.007*"com" + 0.006*" " + 0.005*"38" + 0.004*"号" + 0.004*"贷" + 0.003*"3000" + 0.003*"10" + 0.003*"做" + 0.003*"说" + 0.002*"111"'), 
 (4, '0.017*" " + 0.007*"说" + 0.006*"做" + 0.005*"你好" + 0.005*"吃" + 0.004*"号" + 0.004*"\u2005" + 0.004*"想" + 0.003*"钱" + 0.003*"明天"'), 
 (5, '0.013*" " + 0.012*"说" + 0.007*"吃" + 0.006*"想" + 0.005*"睡" + 0.005*"做" + 0.004*"钱" + 0.004*"买" + 0.004*"回来" + 0.004*"干嘛"'), 
 (6, '0.010*" " + 0.005*"买大单" + 0.005*"贷" + 0.004*"说" + 0.004*"贷款" + 0.004*"钱" + 0.003*"com" + 0.003*"号" + 0.003*"奥特曼" + 0.003*"吃"'),
 (7, '0.022*" " + 0.010*"说" + 0.008*"做" + 0.007*"吃" + 0.005*"想" + 0.004*"钱" + 0.003*"\u2005" + 0.003*"买" + 0.003*"谢谢" + 0.003*"明天"'),
 (8, '0.017*" " + 0.015*"com" + 0.006*"www" + 0.005*"说" + 0.004*"号" + 0.004*"\u2005" + 0.003*"手机" + 0.003*"钱" + 0.003*"吃" + 0.003*"https"'), 
 (9, '0.011*"\u2005" + 0.011*"说" + 0.010*"做" + 0.009*" " + 0.004*"钱" + 0.004*"买" + 0.004*"发" + 0.003*"谢谢" + 0.003*"吃" + 0.003*"玩"')]

这里随便找了些数据,效果不是太明显,这里主要讲处理流程,不要被这结果干扰心情,不过工业应用中很多时候,实际结果和你理想的结果有很大差距。用一些正常的数据,是可以看出一些信息的。上次用汽车之家的评论数据做lda,主题信息就比较明显,有关于油耗的,有关于买车的等等。
也可以对新文本,找出其所在的主题分布。

def to_lda_vec(model, dictionary, text_list=None):
    '''
    :param model: lda model
    :param dictionary: Dictionary for toBow
    :param text_list: texts
    :return: texts about one topic
    '''
    lda_list = []
    for texts in text_list:
        doc_bow = dictionary.doc2bow(texts)
        doc_lda = model[doc_bow]
    lda_list.append(doc_lda)

    return lda_list

这个方法中的参数加了注释,这里可以看到有个参数是dictionary,这里就是我们前面训练lda时用的词典,前面保存的词典派上用场了。最后输出的lda_list是一个列表,列表中元素为每句话的doc_lda,doc_lda是这样子的[(5,0.342345),(6,0.1111)…],也就是个list,无素为元组,元组包括两个值,第一个值表示主题id,第二个值表示属于该主题的概率。

扫描二维码关注公众号,回复: 1532271 查看本文章

也可以用于新文本数据的向量化,即将新的文本映射成主题向量,然后可以做分类,做聚类,做推荐。

猜你喜欢

转载自blog.csdn.net/u010976347/article/details/80619008