基於LDA的文本主題聚類Python實現

LDA簡介

LDA(Latent Dirichlet Allocation)是一種文檔主題生成模型,也稱爲一個三層貝葉斯概率模型,包含詞、主題和文檔三層結構。所謂生成模型,就是說,我們認爲一篇文章的每個詞都是通過“以一定概率選擇了某個主題,並從這個主題中以一定概率選擇某個詞語”這樣一個過程得到。文檔到主題服從多項式分佈,主題到詞服從多項式分佈。
在這裏插入圖片描述

LDA是一種非監督機器學習技術,可以用來識別大規模文檔集(document collection)或語料庫(corpus)中潛藏的主題信息。它採用了詞袋(bag of words)的方法,這種方法將每一篇文檔視爲一個詞頻向量,從而將文本信息轉化爲了易於建模的數字信息。但是詞袋方法沒有考慮詞與詞之間的順序,這簡化了問題的複雜性,同時也爲模型的改進提供了契機。每一篇文檔代表了一些主題所構成的一個概率分佈,而每一個主題又代表了很多單詞所構成的一個概率分佈。

關鍵詞:文檔主題生成模型,無監督學習,概率模型,NLP


生成過程

對於語料庫中的每篇文檔,LDA定義瞭如下生成過程(generativeprocess):

1.對每一篇文檔,從主題分佈中抽取一個主題;

2.從上述被抽到的主題所對應的單詞分佈中抽取一個單詞;

3.重複上述過程直至遍歷文檔中的每一個單詞。

語料庫中的每一篇文檔與T(通過反覆試驗等方法事先給定)個主題的一個多項分佈 (multinomialdistribution)相對應,將該多項分佈記爲θ。每個主題又與詞彙表(vocabulary)中的V個單詞的一個多項分佈相對應,將這個多項分佈記爲φ。

具體推導可以參考:https://zhuanlan.zhihu.com/p/31470216

Python範例

使用到的庫:jieba, gensim
爲了使生成結果更精確,需要構造新詞,停用詞和同義詞詞典。

import jieba
import jieba.posseg as jp
from gensim import corpora, models

# Global Dictionary
new_words = ['奧預賽', '摺疊屏']  # 新詞
stopwords = {' ', '再', '的', '們', '爲', '時', ':'}  # 停用詞
synonyms = {'韓國': '南朝鮮', '傳言': '流言'}  # 同義詞
words_nature = ('n', 'nr', 'ns', 'nt', 'eng', 'v', 'd')  # 可用的詞性


def add_new_words():  # 增加新詞
    for i in new_words:
        jieba.add_word(i)


def remove_stopwords(ls):  # 去除停用詞
    return [word for word in ls if word not in stopwords]


def replace_synonyms(ls):  # 替換同義詞
    return [synonyms[i] if i in synonyms else i for i in ls]


documents = [
    '足協申請取消女足奧預賽韓國主場比賽 公平原則保障安全',
    '芬森發聲再回應傳言:想念遼寧隊友 爲中國的球迷們祈福',
    '電商圍剿涉疫商家進行時:哄擡物價,就這麼罰你',
    '今晚視頻直播華爲新品發佈會:全新摺疊屏手機亮相']
add_new_words()
words_ls = []
for text in documents:
    words = replace_synonyms(remove_stopwords([w.word for w in jp.cut(text)]))
    words_ls.append(words)

# 生成語料詞典
dictionary = corpora.Dictionary(words_ls)
# 生成稀疏向量集
corpus = [dictionary.doc2bow(words) for words in words_ls]
# LDA模型,num_topics設置聚類數,即最終主題的數量
lda = models.ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=2)
# 展示每個主題的前5的詞語
for topic in lda.print_topics(num_words=5):
    print(topic)
# 推斷每個語料庫中的主題類別
print('推斷:')
for e, values in enumerate(lda.inference(corpus)[0]):
    topic_val = 0
    topic_id = 0
    for tid, val in enumerate(values):
        if val > topic_val:
            topic_val = val
            topic_id = tid
    print(topic_id, '->', documents[e])

在這裏插入圖片描述
可以看到,一共分成了兩類,文本庫中的標題分別分成了0,1兩類,即一個是體育類,一個是科技類。

需要注意的是,LDA模型是個無監督的聚類,每次生成的結果可能不同。

參考

  • https://www.jianshu.com/p/fa97454c9ffd
  • https://zhuanlan.zhihu.com/p/31470216

更多內容訪問 omegaxyz.com
網站所有代碼採用Apache 2.0授權
網站文章採用知識共享許可協議BY-NC-SA4.0授權
© 2020-2025 • OmegaXYZ-版權所有 轉載請註明出處

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章