【機器學習】--LDA初始和應用

LHBlog發表於2018-04-04

一、前述

LDA是一種 非監督機器學習 技術,可以用來識別大規模文件集(document collection)或語料庫(corpus)中潛藏的主題資訊。它採用了詞袋(bag of words)的方法,這種方法將每一篇文件視為一個詞頻向量,從而將文字資訊轉化為了易於建模的數字資訊。但是詞袋方法沒有考慮詞與詞之間的順序,這簡化了問題的複雜性,同時也為模型的改進提供了契機。每一篇文件代表了一些主題所構成的一個概率分佈,而每一個主題又代表了很多單詞所構成的一個概率分佈。由於 Dirichlet分佈隨機向量各分量間的弱相關性(之所以還有點“相關”,是因為各分量之和必須為1),使得我們假想的潛在主題之間也幾乎是不相關的,這與很多實際問題並不相符,從而造成了LDA的又一個遺留問題。

二、具體過程

對於語料庫中的每篇文件,LDA定義瞭如下生成過程(generativeprocess):
1.對每一篇文件,從主題分佈中抽取一個主題
2.從上述被抽到的主題所對應的單詞分佈中抽取一個單詞;
3.重複上述過程直至遍歷文件中的每一個單詞。

語料庫中的每一篇文件與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_)

 

相關文章