python实现lda聚类_LDA之主题模型原理解析与python实现

1 #-*- coding:utf-8 -*-

2 importlogging3 importlogging.config4 importConfigParser5 importnumpy as np6 importrandom7 importcodecs8 importos9

10 from collections importOrderedDict11 #获取当前路径

12 path =os.getcwd()13 #导入日志配置文件

14 logging.config.fileConfig("logging.conf")15 #创建日志对象

16 logger =logging.getLogger()17 #loggerInfo = logging.getLogger("TimeInfoLogger")

18 #Consolelogger = logging.getLogger("ConsoleLogger")

19

20 #导入配置文件

21 conf =ConfigParser.ConfigParser()22 conf.read("setting.conf")23 #文件路径

24 trainfile = os.path.join(path,os.path.normpath(conf.get("filepath", "trainfile")))25 wordidmapfile = os.path.join(path,os.path.normpath(conf.get("filepath","wordidmapfile")))26 thetafile = os.path.join(path,os.path.normpath(conf.get("filepath","thetafile")))27 phifile = os.path.join(path,os.path.normpath(conf.get("filepath","phifile")))28 paramfile = os.path.join(path,os.path.normpath(conf.get("filepath","paramfile")))29 topNfile = os.path.join(path,os.path.normpath(conf.get("filepath","topNfile")))30 tassginfile = os.path.join(path,os.path.normpath(conf.get("filepath","tassginfile")))31 #模型初始参数

32 K = int(conf.get("model_args","K"))33 alpha = float(conf.get("model_args","alpha"))34 beta = float(conf.get("model_args","beta"))35 iter_times = int(conf.get("model_args","iter_times"))36 top_words_num = int(conf.get("model_args","top_words_num"))37 classDocument(object):38 def __init__(self):39 self.words =[]40 self.length =041 #把整个文档及真的单词构成vocabulary(不允许重复)

42 classDataPreProcessing(object):43 def __init__(self):44 self.docs_count =045 self.words_count =046 #保存每个文档d的信息(单词序列,以及length)

47 self.docs =[]48 #建立vocabulary表,照片文档的单词

49 self.word2id =OrderedDict()50 defcachewordidmap(self):51 with codecs.open(wordidmapfile, 'w','utf-8') as f:52 for word,id inself.word2id.items():53 f.write(word +"\t"+str(id)+"\n")54 classLDAModel(object):55 def __init__(self,dpre):56 self.dpre = dpre #获取预处理参数

57 #

58 #模型参数

59 #聚类个数K,迭代次数iter_times,每个类特征词个数top_words_num,超参数α(alpha) β(beta)

60 #

61 self.K =K62 self.beta =beta63 self.alpha =alpha64 self.iter_times =iter_times65 self.top_words_num =top_words_num66 #

67 #文件变量

68 #分好词的文件trainfile

69 #词对应id文件wordidmapfile

70 #文章-主题分布文件thetafile

71 #词-主题分布文件phifile

72 #每个主题topN词文件topNfile

73 #最后分派结果文件tassginfile

74 #模型训练选择的参数文件paramfile

75 #

76 self.wordidmapfile =wordidmapfile77 self.trainfile =trainfile78 self.thetafile =thetafile79 self.phifile =phifile80 self.topNfile =topNfile81 self.tassginfile =tassginfile82 self.paramfile =paramfile83 #p,概率向量 double类型,存储采样的临时变量

84 #nw,词word在主题topic上的分布

85 #nwsum,每各topic的词的总数

86 #nd,每个doc中各个topic的词的总数

87 #ndsum,每各doc中词的总数

88 self.p =np.zeros(self.K)89 #nw,词word在主题topic上的分布

90 self.nw = np.zeros((self.dpre.words_count,self.K),dtype="int")91 #nwsum,每各topic的词的总数

92 self.nwsum = np.zeros(self.K,dtype="int")93 #nd,每个doc中各个topic的词的总数

94 self.nd = np.zeros((self.dpre.docs_count,self.K),dtype="int")95 #ndsum,每各doc中词的总数

96 self.ndsum = np.zeros(dpre.docs_count,dtype="int")97 self.Z = np.array([ [0 for y in xrange(dpre.docs[x].length)] for x in xrange(dpre.docs_count)]) #M*doc.size(),文档中词的主题分布

98

99 #随机先分配类型,为每个文档中的各个单词分配主题

100 for x inxrange(len(self.Z)):101 self.ndsum[x] =self.dpre.docs[x].length102 for y inxrange(self.dpre.docs[x].length):103 topic = random.randint(0,self.K-1)#随机取一个主题

104 self.Z[x][y] = topic#文档中词的主题分布

105 self.nw[self.dpre.docs[x].words[y]][topic] += 1

106 self.nd[x][topic] += 1

107 self.nwsum[topic] += 1

108

109 self.theta = np.array([ [0.0 for y in xrange(self.K)] for x inxrange(self.dpre.docs_count) ])110 self.phi = np.array([ [ 0.0 for y in xrange(self.dpre.words_count) ] for x inxrange(self.K)])111 defsampling(self,i,j):112 #换主题

113 topic =self.Z[i][j]114 #只是单词的编号,都是从0开始word就是等于j

115 word =self.dpre.docs[i].words[j]116 #if word==j:

117 #print 'true'

118 self.nw[word][topic] -= 1

119 self.nd[i][topic] -= 1

120 self.nwsum[topic] -= 1

121 self.ndsum[i] -= 1

122

123 Vbeta = self.dpre.words_count *self.beta124 Kalpha = self.K *self.alpha125 self.p = (self.nw[word] + self.beta)/(self.nwsum + Vbeta) *\126 (self.nd[i] + self.alpha) / (self.ndsum[i] +Kalpha)127

128 #随机更新主题的吗

129 #for k in xrange(1,self.K):

130 #self.p[k] += self.p[k-1]

131 #u = random.uniform(0,self.p[self.K-1])

132 #for topic in xrange(self.K):

133 #if self.p[topic]>u:

134 #break

135

136 #按这个更新主题更好理解,这个效果还不错

137 p = np.squeeze(np.asarray(self.p/np.sum(self.p)))138 topic = np.argmax(np.random.multinomial(1, p))139

140 self.nw[word][topic] +=1

141 self.nwsum[topic] +=1

142 self.nd[i][topic] +=1

143 self.ndsum[i] +=1

144 returntopic145 defest(self):146 #Consolelogger.info(u"迭代次数为%s 次" % self.iter_times)

147 for x inxrange(self.iter_times):148 for i inxrange(self.dpre.docs_count):149 for j inxrange(self.dpre.docs[i].length):150 topic =self.sampling(i,j)151 self.Z[i][j] =topic152 logger.info(u"迭代完成。")153 logger.debug(u"计算文章-主题分布")154 self._theta()155 logger.debug(u"计算词-主题分布")156 self._phi()157 logger.debug(u"保存模型")158 self.save()159 def_theta(self):160 for i in xrange(self.dpre.docs_count):#遍历文档的个数词

161 self.theta[i] = (self.nd[i]+self.alpha)/(self.ndsum[i]+self.K *self.alpha)162 def_phi(self):163 for i inxrange(self.K):164 self.phi[i] = (self.nw.T[i] + self.beta)/(self.nwsum[i]+self.dpre.words_count *self.beta)165 defsave(self):166 #保存theta文章-主题分布

167 logger.info(u"文章-主题分布已保存到%s" %self.thetafile)168 with codecs.open(self.thetafile,'w') as f:169 for x inxrange(self.dpre.docs_count):170 for y inxrange(self.K):171 f.write(str(self.theta[x][y]) + '\t')172 f.write('\n')173 #保存phi词-主题分布

174 logger.info(u"词-主题分布已保存到%s" %self.phifile)175 with codecs.open(self.phifile,'w') as f:176 for x inxrange(self.K):177 for y inxrange(self.dpre.words_count):178 f.write(str(self.phi[x][y]) + '\t')179 f.write('\n')180 #保存参数设置

181 logger.info(u"参数设置已保存到%s" %self.paramfile)182 with codecs.open(self.paramfile,'w','utf-8') as f:183 f.write('K=' + str(self.K) + '\n')184 f.write('alpha=' + str(self.alpha) + '\n')185 f.write('beta=' + str(self.beta) + '\n')186 f.write(u'迭代次数 iter_times=' + str(self.iter_times) + '\n')187 f.write(u'每个类的高频词显示个数 top_words_num=' + str(self.top_words_num) + '\n')188 #保存每个主题topic的词

189 logger.info(u"主题topN词已保存到%s" %self.topNfile)190

191 with codecs.open(self.topNfile,'w','utf-8') as f:192 self.top_words_num =min(self.top_words_num,self.dpre.words_count)193 for x inxrange(self.K):194 f.write(u'第' + str(x) + u'类:' + '\n')195 twords =[]196 twords = [(n,self.phi[x][n]) for n inxrange(self.dpre.words_count)]197 twords.sort(key = lambda i:i[1], reverse=True)198 for y inxrange(self.top_words_num):199 word = OrderedDict({value:key for key, value inself.dpre.word2id.items()})[twords[y][0]]200 f.write('\t'*2+ word +'\t' + str(twords[y][1])+ '\n')201 #保存最后退出时,文章的词分派的主题的结果

202 logger.info(u"文章-词-主题分派结果已保存到%s" %self.tassginfile)203 with codecs.open(self.tassginfile,'w') as f:204 for x inxrange(self.dpre.docs_count):205 for y inxrange(self.dpre.docs[x].length):206 f.write(str(self.dpre.docs[x].words[y])+':'+str(self.Z[x][y])+ '\t')207 f.write('\n')208 logger.info(u"模型训练完成。")209 #数据预处理,即:生成d()单词序列,以及词汇表

210 defpreprocessing():211 logger.info(u'载入数据......')212 with codecs.open(trainfile, 'r','utf-8') as f:213 docs =f.readlines()214 logger.debug(u"载入完成,准备生成字典对象和统计文本数据...")215 #大的文档集

216 dpre =DataPreProcessing()217 items_idx =0218 for line indocs:219 if line != "":220 tmp =line.strip().split()221 #生成一个文档对象:包含单词序列(w1,w2,w3,,,,,wn)可以重复的

222 doc =Document()223 for item intmp:224 if dpre.word2id.has_key(item):#已有的话,只是当前文档追加

225 doc.words.append(dpre.word2id[item])226 else: #没有的话,要更新vocabulary中的单词词典及wordidmap

227 dpre.word2id[item] =items_idx228 doc.words.append(items_idx)229 items_idx += 1

230 doc.length =len(tmp)231 dpre.docs.append(doc)232 else:233 pass

234 dpre.docs_count = len(dpre.docs) #文档数

235 dpre.words_count = len(dpre.word2id) #词汇数

236 logger.info(u"共有%s个文档" %dpre.docs_count)237 dpre.cachewordidmap()238 logger.info(u"词与序号对应关系已保存到%s" %wordidmapfile)239 returndpre240 defrun():241 #处理文档集,及计算文档数,以及vocabulary词的总个数,以及每个文档的单词序列

242 dpre =preprocessing()243 lda =LDAModel(dpre)244 lda.est()245 if __name__ == '__main__':246 run()

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值