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遍历zip文件输出名称时出现乱码问题的解决方法
Apr 08 Python
如何在python中使用selenium的示例
Dec 26 Python
对pandas的行列名更改与数据选择详解
Nov 12 Python
PyTorch 1.0 正式版已经发布了
Dec 13 Python
python pyinstaller 加载ui路径方法
Jun 10 Python
win8.1安装Python 2.7版环境图文详解
Jul 01 Python
python中with语句结合上下文管理器操作详解
Dec 19 Python
python base64库给用户名或密码加密的流程
Jan 02 Python
pycharm内无法import已安装的模块问题解决
Feb 12 Python
keras中epoch,batch,loss,val_loss用法说明
Jul 02 Python
Python RabbitMQ实现简单的进程间通信示例
Jul 02 Python
python自动生成sql语句的脚本
Feb 24 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
Drupal读取Excel并导入数据库实例
2014/03/02 PHP
CodeIgniter框架URL路由总结
2014/09/03 PHP
Windows下编译PHP5.4和xdebug全记录
2015/04/03 PHP
thinkPHP2.1自定义标签库的导入方法详解
2016/07/20 PHP
PHP中number_format()函数的用法讲解
2019/04/08 PHP
javascript 小数取整简单实现方式
2014/05/30 Javascript
jquery处理json对象
2014/11/03 Javascript
JS实现仿google、百度搜索框输入信息智能提示的实现方法
2015/04/20 Javascript
Java Mybatis框架入门基础教程
2015/09/21 Javascript
jQuery实现ctrl+enter(回车)提交表单
2015/10/19 Javascript
基于jquery编写的放大镜插件
2016/03/23 Javascript
HTML5+jQuery插件Quicksand实现超酷的星际争霸2兵种分类展示效果(附demo源码下载)
2016/05/25 Javascript
PHP实现记录代码运行时间封装类实例教程
2017/05/08 Javascript
EasyUI实现下拉框多选功能
2017/11/07 Javascript
详解Vue改变数组中对象的属性不重新渲染View的解决方案
2018/09/21 Javascript
VueCli3构建TS项目的方法步骤
2018/11/07 Javascript
node.js 基于cheerio的爬虫工具的实现(需要登录权限的爬虫工具)
2019/04/10 Javascript
JS实现骰子3D旋转效果
2019/10/24 Javascript
如何使用webpack打包一个库library的方法步骤
2019/12/18 Javascript
Vue父子传递实例讲解
2020/02/14 Javascript
解决vue安装less报错Failed to compile with 1 errors的问题
2020/10/22 Javascript
python base64 decode incorrect padding错误解决方法
2015/01/08 Python
python中的计时器timeit的使用方法
2017/10/20 Python
PyCharm+PySpark远程调试的环境配置的方法
2018/11/29 Python
使用Django连接Mysql数据库步骤
2019/01/15 Python
解决Keras的自定义lambda层去reshape张量时model保存出错问题
2020/07/01 Python
如何开启linux的ssh服务
2013/06/03 面试题
什么是servlet
2012/05/08 面试题
银行柜员应聘推荐信范文
2013/11/24 职场文书
运动会100米解说词
2014/01/23 职场文书
小班开学寄语
2014/04/04 职场文书
党在我心中演讲稿
2014/09/02 职场文书
幼儿园教师师德师风承诺书
2015/04/28 职场文书
七一慰问简报
2015/07/20 职场文书
Pytorch DataLoader shuffle验证方式
2021/06/02 Python
Python pandas求方差和标准差的方法实例
2021/08/04 Python