Python探索之pLSA实现代码


Posted in Python onOctober 25, 2017

pLSA(probabilistic Latent Semantic Analysis),概率潜在语义分析模型,是1999年Hoffman提出的一个被称为第一个能解决一词多义问题的模型,通过在文档与单词之间建立一层主题(Topic),将文档与单词的直接关联转化为文档与主题的关联以及主题与单词的关联。这里采用EM算法进行估计,可能存在差错,望积极批评指正。

# -*- coding: utf-8 -*-
import math
import random
import jieba
import codecs
import datetime

class pLSA_lph():
  def __init__(self, ntopic = 5):
    self.n_doc = 0
    self.n_word = 0
    self.n_topic = ntopic
    self.corpus = None
    self.p_z_dw = None
    self.p_w_z = None
    self.p_z_d = None
    self.likelihood = 0
    self.vocab = None
    self.stop_words = [u',', u'。', u'、', u'(', u')', u'·', u'!', u' ', u':', u'“', u'”', u'\n']
  # 每行和为1的正实数,概率分布;
  def _rand_mat(self, sizex, sizey):
    ret = []
    for i in xrange(sizex):
      ret.append([])
      for _ in xrange(sizey):
        ret[-1].append(random.random())
      norm = sum(ret[-1])
      for j in xrange(sizey):
        ret[-1][j] /= norm
    return ret
  #从文本中计算词频稀疏矩阵,这里存储模型仿照LDA
  def loadCorpus(self, fn):
    # 中文分词
    f = open(fn, 'r')
    text = f.readlines()
    text = r' '.join(text)
    seg_generator = jieba.cut(text)
    seg_list = [i for i in seg_generator if i not in self.stop_words]
    seg_list = r' '.join(seg_list)
    # 切割统计所有出现的词纳入词典
    seglist = seg_list.split(" ")
    self.vocab = []
    for word in seglist:
      if (word != u' ' and word not in self.vocab):
        self.vocab.append(word)
    self.n_word =len(self.vocab)
    CountMatrix = []
    f.seek(0, 0)
    # 统计每个文档中出现的词频
    for line in f:
      # 置零
      count = [0 for i in range(len(self.vocab))]
      text = line.strip()
      # 但还是要先分词
      seg_generator = jieba.cut(text)
      seg_list = [i for i in seg_generator if i not in self.stop_words]
      seg_list = r' '.join(seg_list)
      seglist = seg_list.split(" ")
      # 查询词典中的词出现的词频
      for word in seglist:
        if word in self.vocab:
          count[self.vocab.index(word)] += 1
      CountMatrix.append(count)
    f.close()
    self.corpus = CountMatrix
    self.n_doc = len(CountMatrix)
    #初始化
    self.p_z_d = self._rand_mat(self.n_topic, self.n_doc)
    self.p_w_z = self._rand_mat(self.n_word, self.n_topic)
    self.p_z_dw =[]
    for k in range(self.n_topic):
      self.p_z_dw.append(self._rand_mat(self.n_doc, self.n_word))

  def _e_step(self):
    for k in range(self.n_topic):
      for d in range(self.n_doc):
        for j in range(self.n_word):
          _d_wz_zd = 0
          for kk in range(self.n_topic):
            _d_wz_zd += self.p_w_z[j][kk]*self.p_z_d[kk][d]
          if _d_wz_zd <= 0:
            _d_wz_zd = 1e-6
          self.p_z_dw[k][d][j] = self.p_w_z[j][k]*self.p_z_d[k][d]/_d_wz_zd
  def _m_step(self):
    print "updating Pn(Wj|Zk)...\r"
    for j in range(self.n_word):
      for k in range(self.n_topic):
        _d_dw_zdw = 0
        for d in range(self.n_doc):
          _d_dw_zdw += self.corpus[d][j]*self.p_z_dw[k][d][j]
        _d_dw_zdw_sum = 0
        for jj in range(self.n_word):
          _d_dw_zdw_i = 0
          for d in range(self.n_doc):
            _d_dw_zdw_i += self.corpus[d][jj]*self.p_z_dw[k][d][jj]
          _d_dw_zdw_sum += _d_dw_zdw_i
        if _d_dw_zdw_sum <= 0:
          _d_dw_zdw_sum = 1e-6
        self.p_w_z[j][k] = _d_dw_zdw/_d_dw_zdw_sum
    print "updating Pn(Zk|Di)...\r"
    for k in range(self.n_topic):
      for d in range(self.n_doc):
        _d_dw_zdw = 0
        for j in range(self.n_word):
          _d_dw_zdw += self.corpus[d][j]*self.p_z_dw[k][d][j]
        _d_dw_zdw_sum = 0
        for kk in range(self.n_topic):
          _d_dw_zdw_i = 0
          for j in range(self.n_word):
            _d_dw_zdw_i += self.corpus[d][j]*self.p_z_dw[kk][d][j]
          _d_dw_zdw_sum += _d_dw_zdw_i
        if _d_dw_zdw_sum <= 0:
          _d_dw_zdw_sum = 1e-6
        self.p_z_d[k][d] = _d_dw_zdw/_d_dw_zdw_sum
  #计算最大似然值
  def _cal_max_likelihood(self):
    self.likelihood = 0
    for d in range(self.n_doc):
      for j in range(self.n_word):
        _dP_wjdi = 0
        for k in range(self.n_topic):
          _dP_wjdi += self.p_w_z[j][k]*self.p_z_d[k][d]
        _dP_wjdi = 1.0/self.n_doc*_dP_wjdi
        self.likelihood += self.corpus[d][j]*math.log(_dP_wjdi)
  #迭代训练
  def train(self, n_iter = 100, d_delta = 1e-6,log_fn = "log.log"):
    itr = 0
    delta =10e9
    _likelihood = 0
    f = open(log_fn, 'w')
    while itr < n_iter and delta > d_delta:
      _likelihood = self.likelihood
      self._e_step()
      self._m_step()
      self._cal_max_likelihood()
      itr += 1
      delta = abs(self.likelihood - _likelihood)
      t1 = datetime.datetime.now().strftime('%Y-%m-%d-%y %H:%M:%S');
      f.write("%s iteration %d, max-likelihood = %.6f\n"%(t1, itr, self.likelihood))
      print "%s iteration %d, max-likelihood = %.6f"%(t1, itr, self.likelihood)
    f.close()

  def printVocabulary(self):
    print "vocabulary:"
    for word in self.vocab:
      print word,
    print
  def saveVocabulary(self, fn):
    f = codecs.open(fn, 'w', 'utf-8')
    for word in self.vocab:
      f.write("%s\n"%word)
    f.close()
  def printWordOfTopic(self):
    for k in range(self.n_topic):
      print "Topic %d"%k,
      for j in range(self.n_word):
        print self.p_w_z[j][k],
      print
  def saveWordOfTopic(self,fn):
    f = open(fn, 'w')
    for j in range(self.n_word):
      f.write(", w%d"%j)
    f.write("\n")
    for k in range(self.n_topic):
      f.write("topic %d"%k)
      for j in range(self.n_word):
        f.write(", %.6f"%self.p_w_z[j][k])
      f.write("\n")
    f.close()
  def printTopicOfDoc(self):
    for d in range(self.n_doc):
      print "Doc %d"%d,
      for k in range(self.n_topic):
        print self.p_z_d[k][d],
      print
  def saveTopicOfDoc(self, fn):
    f = open(fn, 'w')
    for k in range(self.n_topic):
      f.write(", z%d" % k)
    f.write("\n")
    for d in range(self.n_doc):
      f.write("doc %d" % d)
      for k in range(self.n_topic):
        f.write(", %.6f" % self.p_z_d[k][d])
      f.write("\n")
    f.close()

依旧采用上一篇文章中的两个政治新闻作为语料库:

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">新华社北京11月26日电中共中央总书记、国家主席习近平26日向古巴共产党中央委员会第一书记、国务委员会主席兼部长会议主席劳尔·卡斯特罗致唁电,代表中国党、政府、人民并以个人名义,对菲德尔·卡斯特罗同志逝世表示最沉痛的哀悼,向其家属致以最诚挚的慰问。全文如下:惊悉古巴革命领导人菲德尔·卡斯特罗同志不幸逝世,我谨代表中国共产党、政府、人民,并以我个人的名义,向你并通过你向古巴共产党、政府、人民,对菲德尔·卡斯特罗同志的逝世表示最沉痛的哀悼,向其家属致以最诚挚的慰问。菲德尔·卡斯特罗同志是古巴共产党和古巴社会主义事业的缔造者,是古巴人民的伟大领袖。他把毕生精力献给了古巴人民争取民族解放、维护国家主权、建设社会主义的壮丽事业,为古巴人民建立了不朽的历史功勋,也为世界社会主义发展建立了不朽的历史功勋。菲德尔·卡斯特罗同志是我们这个时代的伟大人物,历史和人民将记住他。我多次同菲德尔·卡斯特罗同志见面,促膝畅谈,他的真知灼见令我深受启发,他的音容笑貌犹在眼前。我深深怀念他,中国人民深深怀念他。菲德尔·卡斯特罗同志生前致力于中古友好,密切关注和高度评价中国发展进程,在他亲自关心和支持下,古巴成为第一个同新中国建交的拉美国家。建交56年来,中古关系长足发展,各领域务实合作成果丰硕,两国人民友谊与日俱增,这都与菲德尔·卡斯特罗同志的关怀和心血密不可分。菲德尔·卡斯特罗同志的逝世是古巴和拉美人民的重大损失,不仅使古巴和拉美人民失去了一位优秀儿子,也使中国人民失去了一位亲密的同志和真诚的朋友。他的光辉形象和伟大业绩将永载史册。我相信,在主席同志坚强领导下,古巴党、政府、人民必将继承菲德尔·卡斯特罗同志的遗志,化悲痛为力量,在社会主义建设事业中不断取得新的成绩。中古两党、两国、两国人民友谊必将得到巩固和发展。伟大的菲德尔·卡斯特罗同志永垂不朽!(完)</span>

据韩联社报道,当地时间29日下午2时30分,韩国总统朴槿惠发表“亲信门”事件后的第3次对国民谈话。据报道,朴槿惠在谈话中表示,“我没有管理好周围的人,导致出现了一些失误。这次事件的过程将尽快向大家说明具体情况。”朴槿惠表示,之前因考虑到国内外各种困难,为了国家和人民,如何才是正确的选择,每晚都辗转反侧,难以入睡。朴槿惠指出,将把总统任期相关问题交给国会和朝野两党决定,将遵守相应规定,辞去总统职务,放下一切。朴槿惠表示,希望韩国尽快摆脱混乱局面,步入正轨。并再次向国民衷心表示道歉。希望两党能尽快齐心协力,解决当前局面,此前,在“亲信门”事件曝光后,朴槿惠曾分别于10月25日和11月4日两次发表讲话,向民众表示歉意。10月25日在青瓦台发表对国民谈话时,朴槿惠承认大选时及就任总统后曾就部分资料征求过亲信崔顺实意见,并就此事向全体国民道歉。11月4日上午,朴槿惠在青瓦台召开记者招待会,就亲信干政事件发表第二次对国民讲话, 称愿意接受特别检察组的调查。韩联社称,依据宪法享有刑事检控豁免特权的在任总统表明接受检方调查的立场,为韩国68年宪政史所仅见。

主函数入口:

if __name__=="__main__":

  _plsa = pLSA_lph(2)
  _plsa.loadCorpus(u"C:\\Users\Administrator\Desktop\\zhongwen.txt")
  _plsa.train()
  _plsa.printTopicOfDoc()
  _plsa.printWordOfTopic()
  _plsa.saveTopicOfDoc(u"C:\\Users\Administrator\Desktop\\topic_doc.txt")
  _plsa.saveWordOfTopic(u"C:\\Users\Administrator\Desktop\\word_topic.txt")

输出每个文档中的主题分布如下:

Doc 0 0.999999999627 3.72945076781e-10
Doc 1 3.52196229806e-11 0.999999999965

总结

以上就是本文关于Python探索之pLSA实现代码的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:python正则表达式re之compile函数解析、python+mongodb数据抓取详细介绍、Python_LDA实现方法详解等,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

Python 相关文章推荐
Python的Bottle框架的一些使用技巧介绍
Apr 08 Python
在Python的Django框架中实现Hacker News的一些功能
Apr 17 Python
jupyter安装小结
Mar 13 Python
django将图片上传数据库后在前端显式的方法
May 25 Python
Python对CSV、Excel、txt、dat文件的处理
Sep 18 Python
Python Image模块基本图像处理操作小结
Apr 13 Python
Python 20行简单实现有道在线翻译的详解
May 15 Python
python 使用opencv 把视频分割成图片示例
Dec 12 Python
python+selenium+Chrome options参数的使用
Mar 18 Python
python:HDF和CSV存储优劣对比分析
Jun 08 Python
Python使用Pygame绘制时钟
Nov 29 Python
python 机器学习的标准化、归一化、正则化、离散化和白化
Apr 16 Python
python正则表达式re之compile函数解析
Oct 25 #Python
Python2和Python3中print的用法示例总结
Oct 25 #Python
Python_LDA实现方法详解
Oct 25 #Python
python+mongodb数据抓取详细介绍
Oct 25 #Python
python装饰器实例大详解
Oct 25 #Python
Python3 模块、包调用&amp;路径详解
Oct 25 #Python
Python探索之创建二叉树
Oct 25 #Python
You might like
Yii学习总结之数据访问对象 (DAO)
2015/02/22 PHP
使用jQuery实现dropdownlist的联动效果(sharepoint 2007)
2011/03/30 Javascript
js实现双向链表互联网机顶盒实战应用实现
2011/10/28 Javascript
js给页面加style无效果的解决方法
2014/01/20 Javascript
node.js中的fs.createReadStream方法使用说明
2014/12/17 Javascript
Javascript基础教程之关键字和保留字汇总
2015/01/18 Javascript
JavaScript中的依赖注入详解
2015/03/18 Javascript
js调用百度地图及调用百度地图的搜索功能
2015/09/07 Javascript
基于JQuery的$.ajax方法进行异步请求导致页面闪烁的解决办法
2016/05/10 Javascript
js实现将json数组显示前台table中
2017/01/10 Javascript
详解angularJs指令的3种绑定策略
2017/04/13 Javascript
JS条形码(一维码)插件JsBarcode用法详解【编码类型、参数、属性】
2017/04/19 Javascript
Node.js环境下Koa2添加travis ci持续集成工具的方法
2017/06/19 Javascript
vue技术分享之你可能不知道的7个秘密
2018/04/09 Javascript
Vue实现购物车详情页面的方法
2019/08/20 Javascript
JavaScript读取本地文件常用方法流程解析
2020/10/12 Javascript
python optparse模块使用实例
2015/04/09 Python
Python解析、提取url关键字的实例详解
2018/12/17 Python
Python XlsxWriter模块Chart类用法实例分析
2019/03/11 Python
对python3 Serial 串口助手的接收读取数据方法详解
2019/06/12 Python
Django框架 信号调度原理解析
2019/09/04 Python
解决Pytorch训练过程中loss不下降的问题
2020/01/02 Python
Django日志及中间件模块应用案例
2020/09/10 Python
css3 border-image使用说明
2010/06/23 HTML / CSS
Reebonz中国官网:新加坡奢侈品购物网站
2017/03/17 全球购物
澳大利亚男士西服品牌:M.J.Bale
2018/02/06 全球购物
Hello Molly美国:女性时尚在线
2019/08/26 全球购物
几个Shell Script面试题
2014/04/18 面试题
管理站站长岗位职责
2013/11/27 职场文书
服务员自我评价
2014/01/25 职场文书
2014年五一活动策划方案
2014/03/15 职场文书
市场部经理岗位职责
2015/02/02 职场文书
社会实践活动总结
2015/02/05 职场文书
企业工会工作总结2015
2015/05/13 职场文书
党支部对转正的意见
2015/06/02 职场文书
springboot入门 之profile设置方式
2022/04/04 Java/Android