一、前述
LDA是一種 非監督機器學習 技術,可以用來識別大規模文件集(document collection)或語料庫(corpus)中潛藏的主題資訊。它採用了詞袋(bag of words)的方法,這種方法將每一篇文件視為一個詞頻向量,從而將文字資訊轉化為了易於建模的數字資訊。但是詞袋方法沒有考慮詞與詞之間的順序,這簡化了問題的複雜性,同時也為模型的改進提供了契機。每一篇文件代表了一些主題所構成的一個概率分佈,而每一個主題又代表了很多單詞所構成的一個概率分佈。由於 Dirichlet分佈隨機向量各分量間的弱相關性(之所以還有點“相關”,是因為各分量之和必須為1),使得我們假想的潛在主題之間也幾乎是不相關的,這與很多實際問題並不相符,從而造成了LDA的又一個遺留問題。
二、具體過程
語料庫中的每一篇文件與T(通過反覆試驗等方法事先給定)個主題的一個多項分佈 (multinomialdistribution)相對應,將該多項分佈記為θ。每個主題又與詞彙表(vocabulary)中的V個單詞的一個多項分佈相對應,將這個多項分佈記為φ。
三、案例
假設文章1開始有以下單詞:
高斯分為主題二,是因為有一定的概率。
如此反覆,當各個概率分佈不再發生變化時,即完成了收斂和訓練過程
訓練思想仍然是EM演算法(摁住一個,去計算另一個)
對比K-means
實際工程過程中:
每一個主題對每一個詞都有一個基本出現次數(人工設定)
每一篇文章在各個主題上都有一個基本出現詞數
步驟:
新來一片文章,需要確定它的主題分佈:
先隨機化主題分佈
1.根據主題分佈和主題-單詞模型,找尋每個
單詞所對應的主題
2.根據單詞主題重新確定主題分佈
1,2反覆,直到主題分佈穩定 最終得到兩個模型:
1.每篇文章的主題分佈
2.每個主題產生詞的概率
用途:
1.根據文章的主題分佈,計算文章之間的相似性
2.計算各個詞語之間的相似度
四、程式碼
# -*- coding: utf-8 -*- import jieba from sklearn.feature_extraction.text import CountVectorizer from sklearn.decomposition import LatentDirichletAllocation for i in range(4): with open('./data/nlp_test%d.txt' % i, encoding='UTF-8') as f: document = f.read() document_cut = jieba.cut(document) result = ' '.join(document_cut) print(result) with open('./data/nlp_test%d.txt' % (i+10), 'w', encoding='UTF-8') as f2: f2.write(result) f.close() f2.close() # 從檔案匯入停用詞表 stpwrdpath = "./data/stop_words.txt" stpwrd_dic = open(stpwrdpath, 'r', encoding='UTF-8') stpwrd_content = stpwrd_dic.read() # 將停用詞表轉換為list stpwrdlst = stpwrd_content.splitlines() stpwrd_dic.close() print(stpwrdlst) # 向量化 不需要tf_idf corpus = [] for i in range(4): with open('./data/nlp_test%d.txt' % (i+10), 'r', encoding='UTF-8') as f: res = f.read() corpus.append(res) print(res) cntVector = CountVectorizer(stop_words=stpwrdlst) cntTf = cntVector.fit_transform(corpus) print(cntTf) # 列印輸出對應關係 # 獲取詞袋模型中的所有詞 wordlist = cntVector.get_feature_names() # 元素a[i][j]表示j詞在i類文字中的權重 weightlist = cntTf.toarray() # 列印每類文字的詞語權重,第一個for遍歷所有文字,第二個for便利某一類文字下的詞語權重 for i in range(len(weightlist)): print("-------第", i, "段文字的詞語權重------") for j in range(len(wordlist)): print(wordlist[j], weightlist[i][j]) lda = LatentDirichletAllocation(n_components=3,#3個話題 learning_method='batch', random_state=0) docres = lda.fit_transform(cntTf) print("文章的主題分佈如下:") print(docres) print("主題的詞分佈如下:") print(lda.components_)