lda模型的python實現


  • LDA(Latent Dirichlet Allocation)是一種文檔主題生成模型,最近看了點資料,准備使用python實現一下。至於數學模型相關知識,某度一大堆,這里也給出之前參考過的一個挺詳細的文檔lda算法漫游指南
  • 這篇博文只講算法的sampling方法python實現。
  • 完整實現項目開源python-LDA

 


  • lda模型變量申請及初始化

#
#偽代碼
#
輸入:文章集合(分詞處理后),K(類的個數)
輸出:已經隨機分派了一次的lda模型
begin
    申請幾個統計量:
        p 概率向量 維度:K
        nw 詞在類上的分布 維度:M*K 其中M為文章集合的詞的總個數
        nwsum 每個類上的詞的總數 維度:K
        nd 每篇文章中,各個類的詞個數分布 維度:V*K 其中V為文章的總個數
        ndsum 每篇文章中的詞的總個數 維度:V
        Z 每個詞分派一個類 維度:V*每篇文章詞的個數
        theta 文章->類的概率分布 維度:V*K
        phi 類->詞的概率分布 維度:K*M

    #初始化隨機分配類
    for x in 文章數:
        統計ndsum[文章id][詞的個數]
        for y in 每篇文章的詞個數:
            給所有詞隨機分派一個類
            詞在此類上的分布數目+1
            此文章中此類的詞的個數+1
            此類的總詞數 +1

end
#
#實現代碼片段,更詳細看github項目
#
class LDAModel(object):
    
    def __init__(self,dpre):

        self.dpre = dpre #獲取預處理參數

        #
        #模型參數
        #聚類個數K,迭代次數iter_times,每個類特征詞個數top_words_num,超參數α(alpha) β(beta)
        #
        self.K = K
        self.beta = beta
        self.alpha = alpha
        self.iter_times = iter_times
        self.top_words_num = top_words_num 
        #
        #文件變量
        #分好詞的文件trainfile
        #詞對應id文件wordidmapfile
        #文章-主題分布文件thetafile
        #詞-主題分布文件phifile
        #每個主題topN詞文件topNfile
        #最后分派結果文件tassginfile
        #模型訓練選擇的參數文件paramfile
        #
        self.wordidmapfile = wordidmapfile
        self.trainfile = trainfile
        self.thetafile = thetafile
        self.phifile = phifile
        self.topNfile = topNfile
        self.tassginfile = tassginfile
        self.paramfile = paramfile
        # p,概率向量 double類型,存儲采樣的臨時變量
        # nw,詞word在主題topic上的分布
        # nwsum,每各topic的詞的總數
        # nd,每個doc中各個topic的詞的總數
        # ndsum,每各doc中詞的總數
        self.p = np.zeros(self.K)        
        self.nw = np.zeros((self.dpre.words_count,self.K),dtype="int")       
        self.nwsum = np.zeros(self.K,dtype="int")    
        self.nd = np.zeros((self.dpre.docs_count,self.K),dtype="int")       
        self.ndsum = np.zeros(dpre.docs_count,dtype="int")    
        self.Z = np.array([ [0 for y in xrange(dpre.docs[x].length)] for x in xrange(dpre.docs_count)])        # M*doc.size(),文檔中詞的主題分布

        #隨機先分配類型
        for x in xrange(len(self.Z)):
            self.ndsum[x] = self.dpre.docs[x].length
            for y in xrange(self.dpre.docs[x].length):
                topic = random.randint(0,self.K-1)
                self.Z[x][y] = topic
                self.nw[self.dpre.docs[x].words[y]][topic] += 1
                self.nd[x][topic] += 1
                self.nwsum[topic] += 1

        self.theta = np.array([ [0.0 for y in xrange(self.K)] for x in xrange(self.dpre.docs_count) ])
        self.phi = np.array([ [ 0.0 for y in xrange(self.dpre.words_count) ] for x in xrange(self.K)]) 
  • sampling抽樣過程

#
#偽代碼
#
輸入:初始化后的lda_model,迭代次數iter_times,超參數α、β,聚類個數K
輸出:theta(文章對應類的分布概率),phi(類對應詞的分布概率),tassgin(文章中每個詞的分派類結果),twords(每個類topN個高頻詞)
begin
    for i in 迭代次數:
        for m in 文章個數: 
            for v in 文章中詞:
                取topic = Z[m][v]
                令nw[v][topic]、nwsum[topic]、nd[m][topic]的統計量均-1
                計算概率p[] #p[]為此詞屬於每個topic的概率
                for k in (1,類的個數-1):
                    p[k] += p[k-1]
                再隨機分派一次,記錄被分派的新的topic
                令nw[v][new_topic]、nwsum[new_topic]、nd[m][new_topic]的統計量均+1

    #迭代完成后
    輸出模型
end
#代碼片段
    def sampling(self,i,j):

        topic = self.Z[i][j]
        word = self.dpre.docs[i].words[j]
        self.nw[word][topic] -= 1
        self.nd[i][topic] -= 1
        self.nwsum[topic] -= 1
        self.ndsum[i] -= 1

        Vbeta = self.dpre.words_count * self.beta
        Kalpha = self.K * self.alpha
        self.p = (self.nw[word] + self.beta)/(self.nwsum + Vbeta) * \
                 (self.nd[i] + self.alpha) / (self.ndsum[i] + Kalpha)
        for k in xrange(1,self.K):
            self.p[k] += self.p[k-1]

        u = random.uniform(0,self.p[self.K-1])
        for topic in xrange(self.K):
            if self.p[topic]>u:
                break

        self.nw[word][topic] +=1
        self.nwsum[topic] +=1
        self.nd[i][topic] +=1
        self.ndsum[i] +=1

        return topic

 


此實現為最基礎的LDA模型實現,聚類個數K,和超參數的設置要靠人工輸入,自動計算的版本會在以后研究。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM