首页 技术 正文
技术 2022年11月14日
0 收藏 385 点赞 2,954 浏览 7222 个字
#-*- coding:utf-8 -*-import loggingimport logging.configimport ConfigParserimport numpy as npimport randomimport codecsimport osfrom collections import OrderedDict#获取当前路径path = os.getcwd()#导入日志配置文件logging.config.fileConfig("logging.conf")#创建日志对象logger = logging.getLogger()# loggerInfo = logging.getLogger("TimeInfoLogger")# Consolelogger = logging.getLogger("ConsoleLogger")#导入配置文件conf = ConfigParser.ConfigParser()conf.read("setting.conf")#文件路径trainfile = os.path.join(path,os.path.normpath(conf.get("filepath", "trainfile")))wordidmapfile = os.path.join(path,os.path.normpath(conf.get("filepath","wordidmapfile")))thetafile = os.path.join(path,os.path.normpath(conf.get("filepath","thetafile")))phifile = os.path.join(path,os.path.normpath(conf.get("filepath","phifile")))paramfile = os.path.join(path,os.path.normpath(conf.get("filepath","paramfile")))topNfile = os.path.join(path,os.path.normpath(conf.get("filepath","topNfile")))tassginfile = os.path.join(path,os.path.normpath(conf.get("filepath","tassginfile")))#模型初始参数K = int(conf.get("model_args","K"))alpha = float(conf.get("model_args","alpha"))beta = float(conf.get("model_args","beta"))iter_times = int(conf.get("model_args","iter_times"))top_words_num = int(conf.get("model_args","top_words_num"))class Document(object):    def __init__(self):        self.words = []        self.length = 0class DataPreProcessing(object):    def __init__(self):        self.docs_count = 0        self.words_count = 0        self.docs = []        self.word2id = OrderedDict()    def cachewordidmap(self):        with codecs.open(wordidmapfile, 'w','utf-8') as f:            for word,id in self.word2id.items():                f.write(word +"\t"+str(id)+"\n")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)])    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    def est(self):        # Consolelogger.info(u"迭代次数为%s 次" % self.iter_times)        for x in xrange(self.iter_times):            for i in xrange(self.dpre.docs_count):                for j in xrange(self.dpre.docs[i].length):                    topic = self.sampling(i,j)                    self.Z[i][j] = topic        logger.info(u"迭代完成。")        logger.debug(u"计算文章-主题分布")        self._theta()        logger.debug(u"计算词-主题分布")        self._phi()        logger.debug(u"保存模型")        self.save()    def _theta(self):        for i in xrange(self.dpre.docs_count):            self.theta[i] = (self.nd[i]+self.alpha)/(self.ndsum[i]+self.K * self.alpha)    def _phi(self):        for i in xrange(self.K):            self.phi[i] = (self.nw.T[i] + self.beta)/(self.nwsum[i]+self.dpre.words_count * self.beta)    def save(self):        #保存theta文章-主题分布        logger.info(u"文章-主题分布已保存到%s" % self.thetafile)        with codecs.open(self.thetafile,'w') as f:            for x in xrange(self.dpre.docs_count):                for y in xrange(self.K):                    f.write(str(self.theta[x][y]) + '\t')                f.write('\n')        #保存phi词-主题分布        logger.info(u"词-主题分布已保存到%s" % self.phifile)        with codecs.open(self.phifile,'w') as f:            for x in xrange(self.K):                for y in xrange(self.dpre.words_count):                    f.write(str(self.phi[x][y]) + '\t')                f.write('\n')        #保存参数设置        logger.info(u"参数设置已保存到%s" % self.paramfile)        with codecs.open(self.paramfile,'w','utf-8') as f:            f.write('K=' + str(self.K) + '\n')            f.write('alpha=' + str(self.alpha) + '\n')            f.write('beta=' + str(self.beta) + '\n')            f.write(u'迭代次数  iter_times=' + str(self.iter_times) + '\n')            f.write(u'每个类的高频词显示个数  top_words_num=' + str(self.top_words_num) + '\n')        #保存每个主题topic的词        logger.info(u"主题topN词已保存到%s" % self.topNfile)        with codecs.open(self.topNfile,'w','utf-8') as f:            self.top_words_num = min(self.top_words_num,self.dpre.words_count)            for x in xrange(self.K):                f.write(u'第' + str(x) + u'类:' + '\n')                twords = []                twords = [(n,self.phi[x][n]) for n in xrange(self.dpre.words_count)]                twords.sort(key = lambda i:i[1], reverse= True)                for y in xrange(self.top_words_num):                    word = OrderedDict({value:key for key, value in self.dpre.word2id.items()})[twords[y][0]]                    f.write('\t'*2+ word +'\t' + str(twords[y][1])+ '\n')        #保存最后退出时,文章的词分派的主题的结果        logger.info(u"文章-词-主题分派结果已保存到%s" % self.tassginfile)        with codecs.open(self.tassginfile,'w') as f:            for x in xrange(self.dpre.docs_count):                for y in xrange(self.dpre.docs[x].length):                    f.write(str(self.dpre.docs[x].words[y])+':'+str(self.Z[x][y])+ '\t')                f.write('\n')        logger.info(u"模型训练完成。")def preprocessing():    logger.info(u'载入数据......')    with codecs.open(trainfile, 'r','utf-8') as f:        docs = f.readlines()    logger.debug(u"载入完成,准备生成字典对象和统计文本数据...")    dpre = DataPreProcessing()    items_idx = 0    for line in docs:        if line != "":            tmp = line.strip().split()            #生成一个文档对象            doc = Document()            for item in tmp:                if dpre.word2id.has_key(item):                    doc.words.append(dpre.word2id[item])                else:                    dpre.word2id[item] = items_idx                    doc.words.append(items_idx)                    items_idx += 1            doc.length = len(tmp)            dpre.docs.append(doc)        else:            pass    dpre.docs_count = len(dpre.docs)    dpre.words_count = len(dpre.word2id)    logger.info(u"共有%s个文档" % dpre.docs_count)    dpre.cachewordidmap()    logger.info(u"词与序号对应关系已保存到%s" % wordidmapfile)    return dpredef run():    dpre = preprocessing()    lda = LDAModel(dpre)    lda.est()if __name__ == '__main__':    run()    

python-LDA
===
### lda模型的python实现,算法采用sampling抽样

* 项目基于python2.7.10如果发现计算概率为0,可能是python的兼容性问题,暂时没时间修复(发现python3.0以上版本会出现此问题)


### 训练和输出文本格式说明
#### 模型训练文件
    `train.dat` 用其他软件or算法分词后,再剔除停用词的最后结果文件,显示格式如下:(一行表示一篇文档)
>1. 康小姐 寮步镇 莞樟路 石井 附近 嘉湖山庄 小区 连续 半夜 停电 已有 居民 咨询 供电公司 小区 电路 正常 咨询 小区 管理处 工作人员 线路 借口 推托<br>
>2. 许小姐 来电反映 寮步镇 莞樟路 汽车东站 附近 嘉湖山庄 小区 最近 一周 都 从 凌晨 3点 早上 8点 停电 昨晚 凌晨 来电 都 没 通电 已有 居民 致电 供电公司 答复 说 该 小区 电路 正常 小区 故意 停电 <br>
>3. 虎门 百佳商场 楼下 乘坐 出租车 虎门 电子城 车牌 粤SLE857 司机 要求 不 打表 需要 20元 要求 打表 司机 拒载<br>
>4. 东城中心 乘坐 粤SM643M  东城 主山高田坊芳桂园 平时 行驶 路线 是 东城 中路 今天 司机 行驶 路线 是 东城大道 东纵大道 温南路 此 车 到了 温南路口车费 是  16元 认为 司机 绕路<br>

#### 模型输出文件
>        `model_parameter.dat` 保存模型训练时选择的参数
>        `wordidmap.dat` 保存词与id的对应关系,主要用作topN时查询
>        `model_twords.dat` 输出每个类高频词topN个
>        `model_tassgin.dat` 输出文章中每个词分派的结果,文本格式为词id:类id
>        `model_theta.dat` 输出文章与类的分布概率,文本一行表示一篇文章,概率1   概率2 …表示文章属于类的概率
>        `model_phi.dat` 输出词与类的分布概率,是一个K*M的矩阵,其中K为设置分类的个数,M为所有文章的词的总数,


### 使用说明
* 用分好词的文本替换掉`data/train.dat`,更详细文档路径查看`setting.conf`
* cd 到lda.py所在目录,执行命令:python lda.py


        此为lda模型的基础版本,所有参数均由人为设定,更复杂的自动生成算法将在下个版本更新。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,962
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,486
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,331
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,114
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,747
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,781