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 break语句详解
Mar 11 Python
基于Python实现的扫雷游戏实例代码
Aug 01 Python
web.py中调用文件夹内模板的方法
Aug 26 Python
Python构造函数及解构函数介绍
Feb 26 Python
Djang中静态文件配置方法
Jul 30 Python
python3操作mysql数据库的方法
Jun 23 Python
Python常见的pandas用法demo示例
Mar 16 Python
python使用 zip 同时迭代多个序列示例
Jul 06 Python
Pycharm激活方法及详细教程(详细且实用)
May 12 Python
python3爬虫中引用Queue的实例讲解
Nov 24 Python
Django权限控制的使用
Jan 07 Python
python控制台打印log输出重复的解决方法
May 14 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
PHP使用php-resque库配合Redis实现MQ消息队列的教程
2016/06/29 PHP
Yii2创建表单(ActiveForm)方法详解
2016/07/23 PHP
使用laravel和ajax实现整个页面无刷新的操作方法
2019/10/03 PHP
PHP Ajax跨域问题解决方案代码实例
2020/08/01 PHP
分享JavaScript获取网页关闭与取消关闭的事件
2013/12/13 Javascript
5种处理js跨域问题方法汇总
2014/12/04 Javascript
2种jQuery 实现刮刮卡效果
2015/02/01 Javascript
javascript实现的固定位置悬浮窗口实例
2015/04/30 Javascript
javascript实现确定和取消提示框效果
2015/07/10 Javascript
Javascript技术栈中的四种依赖注入小结
2016/02/27 Javascript
JavaScript高级程序设计(第三版)学习笔记1~5章
2016/03/11 Javascript
1秒50万字!js实现关键词匹配
2016/08/01 Javascript
javascript简单进制转换实现方法
2016/11/24 Javascript
JQuery实现table中tr上移下移的示例(超简单)
2018/01/08 jQuery
详解Angular系列之变化检测(Change Detection)
2018/02/26 Javascript
微信小程序左滑删除功能开发案例详解
2018/11/12 Javascript
VSCode插件安装完成后的配置(常用配置)
2020/08/24 Javascript
利用Python实现网络测试的脚本分享
2017/05/26 Python
Python多进程写入同一文件的方法
2019/01/14 Python
Python对象转换为json的方法步骤
2019/04/25 Python
Python单元测试工具doctest和unittest使用解析
2019/09/02 Python
如何使用python代码操作git代码
2020/02/29 Python
Python常驻任务实现接收外界参数代码解析
2020/07/21 Python
区分python中的进程与线程
2020/08/13 Python
python如何实现DES加密
2020/09/21 Python
Python全局变量与global关键字常见错误解决方案
2020/10/05 Python
结合CSS3的新特性来总结垂直居中的实现方法
2016/05/30 HTML / CSS
文职个人求职信范文
2013/09/23 职场文书
毕业生求职找工作的自我评价范文
2013/11/27 职场文书
俄罗斯商务邀请函
2014/01/26 职场文书
学雷锋月活动总结
2014/04/25 职场文书
赢在执行观后感
2015/06/16 职场文书
Oracle 区块链表创建过程详解
2021/05/15 Oracle
Go调用Rust方法及外部函数接口前置
2022/06/14 Golang
Windows Server 2022 超融合部署(图文教程)
2022/06/25 Servers
微信小程序实现轮播图指示器
2022/06/25 Javascript