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实现简易Web爬虫详解
Jan 03 Python
基于pandas将类别属性转化为数值属性的方法
Jul 25 Python
解决python 自动安装缺少模块的问题
Oct 22 Python
pandas使用apply多列生成一列数据的实例
Nov 28 Python
Python面向对象程序设计之私有变量,私有方法原理与用法分析
Mar 23 Python
Python爬虫HTPP请求方法有哪些
Jun 03 Python
基于PyTorch的permute和reshape/view的区别介绍
Jun 18 Python
Python 常用日期处理 -- calendar 与 dateutil 模块的使用
Sep 02 Python
python 如何区分return和yield
Sep 22 Python
python将下载到本地m3u8视频合成MP4的代码详解
Nov 24 Python
Python爬虫+Tkinter制作一个翻译软件的示例
Feb 20 Python
python实现简单文件读写函数
Feb 25 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
VOLVO车载收音机
2021/03/02 无线电
php+ajax制作无刷新留言板
2015/10/27 PHP
PHP支付系统设计与典型案例分享
2016/08/02 PHP
详解PHP数据压缩、加解密(pack, unpack)
2016/12/17 PHP
php指定长度分割字符串str_split函数用法示例
2017/01/30 PHP
Laravel Eloquent分表方法并使用模型关联的实现
2019/11/25 PHP
javascript function、指针及内置对象
2009/02/19 Javascript
jquery图片延迟加载 前端开发技能必备系列
2012/06/18 Javascript
javascript检查表单数据是否改变的方法
2013/07/30 Javascript
js动态创建、删除表格示例代码
2013/08/07 Javascript
JavaScript中window、doucment、body的解释
2013/08/14 Javascript
js获取html页面节点方法(递归方式)
2013/12/13 Javascript
AngularJS表单和输入验证实例
2016/11/02 Javascript
详解从Node.js的child_process模块来学习父子进程之间的通信
2017/03/27 Javascript
VUE利用vuex模拟实现新闻点赞功能实例
2017/06/28 Javascript
Vue Spa切换页面时更改标题的实例代码
2017/07/15 Javascript
Vue iview-admin框架二级菜单改为三级菜单的方法
2018/07/03 Javascript
Vue实现左右菜单联动实现代码
2018/08/12 Javascript
JS使用百度地图API自动获取地址和经纬度操作示例
2019/04/16 Javascript
js图片查看器插件用法示例
2019/06/22 Javascript
JavaScript Window浏览器对象模型原理解析
2020/05/30 Javascript
python删除文本中行数标签的方法
2018/05/31 Python
python 获取一个值在某个区间的指定倍数的值方法
2018/11/12 Python
selenium+python自动化测试之使用webdriver操作浏览器的方法
2019/01/23 Python
关于PyTorch 自动求导机制详解
2019/08/18 Python
python openCV获取人脸部分并存储功能
2019/08/28 Python
Python使用matplotlib绘制三维参数曲线操作示例
2019/09/10 Python
python filecmp.dircmp实现递归比对两个目录的方法
2020/05/22 Python
Sam’s Club山姆会员商店:沃尔玛旗下高端会员制商店
2017/01/16 全球购物
澳大利亚香水在线:Price Rite Mart
2017/12/28 全球购物
童装店创业计划书
2014/01/09 职场文书
学生思想表现的评语
2014/01/30 职场文书
班队活动设计方案
2014/01/30 职场文书
个人银行贷款担保书
2014/04/01 职场文书
2015年医院后勤工作总结
2015/05/20 职场文书
vue首次渲染全过程
2021/04/21 Vue.js