LDA(Latent Dirichlet Allocation):潛在狄利克雷分布始绍,是一種非監(jiān)督機器學(xué)習(xí)技術(shù)。它認為一篇文檔是有多個主題的,而每個主題又對應(yīng)著不同的詞抑片。一篇文檔的構(gòu)造過程,首先是以一定的概率選擇某個主題杨赤,然后再在這個主題下以一定的概率選出某一個詞敞斋,這樣就生成了這篇文檔的第一個詞。不斷重復(fù)這個過程疾牲,就生成了整篇文章(當然這里假定詞與詞之間是沒有順序的渺尘,即所有詞無序的堆放在一個大袋子中,稱之為詞袋说敏,這種方式可以使算法相對簡化一些)鸥跟。
LDA的使用是上述文檔生成過程的逆過程,即根據(jù)一篇得到的文檔盔沫,去尋找出這篇文檔的主題医咨,以及這些主題所對應(yīng)的詞。LDA是NLP領(lǐng)域一個非常重要的非監(jiān)督算法架诞。
白話解釋:比如document的內(nèi)容為:[自從喬布斯去世之后拟淮,iPhone再難以產(chǎn)生革命性的創(chuàng)新了]
通過上述的方法,document將對應(yīng)兩個主題topic1谴忧,topic2很泊,進而,主題topic1會對應(yīng)一些詞:[蘋果創(chuàng)始人][蘋果手機],主題topic2會對應(yīng)一些詞:[重大革新][技術(shù)突破]沾谓。于是LDA模型的好處顯而易見委造,就是可以挖掘文檔中的潛在詞或者找到兩篇沒有相同詞的文檔之間的聯(lián)系。
我們的目標是找到每一篇文檔的主題分布和每一個主題中詞的分布均驶。
在LDA模型中昏兆,我們需要先假定一個主題數(shù)K,這樣所有的分布就都基于K個主題展開妇穴。那么具體LDA模型是怎么樣的呢爬虱?具體如下圖:
詳細模型原理見CSDN博主蠡1204
原文鏈接:https://blog.csdn.net/qq_40006058/article/details/85865695
解釋了這么多隶债,下面就看看詳細代碼。
# -*- coding:utf-8 -*-
"
Created on Mon Aug 19 14:56:19 2019
@author: Luxuriant
"
import numpy as np
from gensim import corpora, models, similarities
from pprint import pprint
import time
# import logging
# logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
def load_stopword():
'''
加載停用詞表
:return: 返回停用詞的列表
'''
f_stop = open('stopwords.txt', encoding='utf-8')
sw = [line.strip() for line in f_stop]
f_stop.close()
return sw
if __name__ == '__main__':
print('1.初始化停止詞列表 ------')
# 開始的時間
t_start = time.time()
# 加載停用詞表
stop_words = load_stopword()
print('2.開始讀入語料數(shù)據(jù) ------ ')
# 讀入語料庫
f = open('鄉(xiāng)賢形象文本-cutfile.txt', encoding='utf-8')
# 語料庫分詞并去停用詞
texts = [[word for word in line.strip().lower().split() if word not in stop_words] for line in f]
print('讀入語料數(shù)據(jù)完成死讹,用時%.3f秒' % (time.time() - t_start))
f.close()
M = len(texts)
print('文本數(shù)目:%d個' % M)
print('3.正在建立詞典 ------')
# 建立字典
dictionary = corpora.Dictionary(texts)
V = len(dictionary)
print('4.正在計算文本向量 ------')
# 轉(zhuǎn)換文本數(shù)據(jù)為索引曲梗,并計數(shù)
corpus = [dictionary.doc2bow(text) for text in texts]
print('5.正在計算文檔TF-IDF ------')
t_start = time.time()
# 計算tf-idf值
corpus_tfidf = models.TfidfModel(corpus)[corpus]
print('建立文檔TF-IDF完成,用時%.3f秒' % (time.time() - t_start))
print('6.LDA模型擬合推斷 ------')
# 訓(xùn)練模型
num_topics = 30
t_start = time.time()
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)
print('LDA模型完成稀并,訓(xùn)練時間為\t%.3f秒' % (time.time() - t_start))
# 隨機打印某10個文檔的主題
num_show_topic = 10 # 每個文檔顯示前幾個主題
print('7.結(jié)果:10個文檔的主題分布:--')
doc_topics = lda.get_document_topics(corpus_tfidf) # 所有文檔的主題分布
idx = np.arange(M)
np.random.shuffle(idx)
idx = idx[:10]
for i in idx:
topic = np.array(doc_topics[i])
topic_distribute = np.array(topic[:, 1])
# print topic_distribute
topic_idx = topic_distribute.argsort()[:-num_show_topic - 1:-1]
print('第%d個文檔的前%d個主題:' % (i, num_show_topic)), topic_idx
print(topic_distribute[topic_idx])
num_show_term = 10 # 每個主題顯示幾個詞
print('8.結(jié)果:每個主題的詞分布:--')
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', )
for t in term_id:
print(dictionary.id2token[t], )
print('\n概率:\t', term_distribute[:, 1])
最后讓我們來看看處理的結(jié)果碘举!(由于分詞中忘瓦,一些無用詞沒被全部去除,導(dǎo)致效果并理想引颈。大家再用之前一定要處理好停用詞蝙场。)
由于我的文本比較長售滤,分的主題也比較多,就不全部展示給大家了赐俗,上面的兩張圖給大家看一下效果弊知。
今天第一次用markDown插入代碼秩彤,發(fā)現(xiàn)簡書的一些標題版式都沒了,所以布局不怎么好看瓜富,大家多擔(dān)待蜻底,喜歡的請點贊趋惨。