zoukankan      html  css  js  c++  java
  • 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,和超参数的设置要靠人工输入,自动计算的版本会在以后研究。

  • 相关阅读:
    编译安装redis-3.2.9(latest stable version)
    MySQL之从忘记密码到重置密码
    Linux时间和时区设定
    java.net.UnknownHostException 异常处理(转)
    制作FastDFS的RPM包
    RPM包安装MySQL 5.7.18
    白鹭http请求post
    iframe嵌套页面 跨域
    git 配置 https和ssh 免密码登录 常用操作命令
    php 错误提示开启
  • 原文地址:https://www.cnblogs.com/guapeng/p/4720590.html
Copyright © 2011-2022 走看看