在Python上基于Markov链生成伪随机文本的教程


Posted in Python onApril 17, 2015

 首先看一下来自Wolfram的定义

    马尔可夫链是随机变量{X_t}的集合(t贯穿0,1,...),给定当前的状态,未来与过去条件独立。

Wikipedia的定义更清楚一点儿

    ...马尔可夫链是具有马尔可夫性质的随机过程...[这意味着]状态改变是概率性的,未来的状态仅仅依赖当前的状态。

马尔可夫链具有多种用途,现在让我看一下如何用它生产看起来像模像样的胡言乱语。

算法如下,

  1.     找一个作为语料库的文本,语料库用于选择接下来的转换。
  2.     从文本中两个连续的单词开始,最后的两个单词构成当前状态。
  3.     生成下一个单词的过程就是马尔可夫转换。为了生成下一个单词,首先查看语料库,查找这两个单词之后跟着的单词。从它们中随机选择一个。
  4.     重复2,直到生成的文本达到需要的大小。

代码如下
 

import random
 
class Markov(object):
  
 def __init__(self, open_file):
  self.cache = {}
  self.open_file = open_file
  self.words = self.file_to_words()
  self.word_size = len(self.words)
  self.database()
   
  
 def file_to_words(self):
  self.open_file.seek(0)
  data = self.open_file.read()
  words = data.split()
  return words
   
  
 def triples(self):
  """ Generates triples from the given data string. So if our string were
    "What a lovely day", we'd generate (What, a, lovely) and then
    (a, lovely, day).
  """
   
  if len(self.words) < 3:
   return
   
  for i in range(len(self.words) - 2):
   yield (self.words[i], self.words[i+1], self.words[i+2])
    
 def database(self):
  for w1, w2, w3 in self.triples():
   key = (w1, w2)
   if key in self.cache:
    self.cache[key].append(w3)
   else:
    self.cache[key] = [w3]
     
 def generate_markov_text(self, size=25):
  seed = random.randint(0, self.word_size-3)
  seed_word, next_word = self.words[seed], self.words[seed+1]
  w1, w2 = seed_word, next_word
  gen_words = []
  for i in xrange(size):
   gen_words.append(w1)
   w1, w2 = w2, random.choice(self.cache[(w1, w2)])
  gen_words.append(w2)
  return ' '.join(gen_words)

为了看到一个示例结果,我们从古腾堡计划中拿了沃德豪斯的《My man jeeves》作为文本,示例结果如下。
 

In [1]: file_ = open('/home/shabda/jeeves.txt')
 
In [2]: import markovgen
 
In [3]: markov = markovgen.Markov(file_)
 
In [4]: markov.generate_markov_text()
Out[4]: 'Can you put a few years of your twin-brother Alfred,
who was apt to rally round a bit. I should strongly advocate
the blue with milk'

[如果想执行这个例子,请下载jeeves.txt和markovgen.py
马尔可夫算法怎样呢?

  •     最后两个单词是当前状态。
  •     接下来的单词仅仅依赖最后两个单词,也就是当前状态。
  •     接下来的单词是从语料库的统计模型中随机选择的。

这是一个示例文本。

"The quick brown fox jumps over the brown fox who is slow jumps over the brown fox who is dead."

这个文本对应的语料库像这样,
 

{('The', 'quick'): ['brown'],
 ('brown', 'fox'): ['jumps', 'who', 'who'],
 ('fox', 'jumps'): ['over'],
 ('fox', 'who'): ['is', 'is'],
 ('is', 'slow'): ['jumps'],
 ('jumps', 'over'): ['the', 'the'],
 ('over', 'the'): ['brown', 'brown'],
 ('quick', 'brown'): ['fox'],
 ('slow', 'jumps'): ['over'],
 ('the', 'brown'): ['fox', 'fox'],
 ('who', 'is'): ['slow', 'dead.']}

现在如果我们从"brown fox"开始,接下来的单词可以是"jumps"或者"who"。如果我们选择"jumps",然后当前的状态就变成了"fox jumps",再接下的单词就是"over",之后依此类推。

提示

  •     我们选择的文本越大,每次转换的选择更多,生成的文本更好看。
  •     状态可以设置为依赖一个单词、两个单词或者任意数量的单词。随着每个状态的单词数的增加,生成的文本更不随机。
  •     不要去掉标点符号等。它们会使语料库更具代表性,随机文本更好看。
Python 相关文章推荐
Django在Win7下的安装及创建项目hello word简明教程
Jul 14 Python
基于Python如何使用AIML搭建聊天机器人
Jan 27 Python
Python中的FTP通信模块ftplib的用法整理
Jul 08 Python
python enumerate函数的使用方法总结
Nov 15 Python
Python简单实现socket信息发送与监听功能示例
Jan 03 Python
python中matplotlib的颜色及线条控制的示例
Mar 16 Python
python smtplib模块自动收发邮件功能(二)
May 22 Python
Tensorflow 训练自己的数据集将数据直接导入到内存
Jun 19 Python
flask应用部署到服务器的方法
Jul 12 Python
图解python全局变量与局部变量相关知识
Nov 02 Python
浅析Python 字符编码与文件处理
Sep 24 Python
Pandas搭配lambda组合使用详解
Jan 22 Python
基于scrapy实现的简单蜘蛛采集程序
Apr 17 #Python
在Python的Django框架中实现Hacker News的一些功能
Apr 17 #Python
由Python运算π的值深入Python中科学计算的实现
Apr 17 #Python
在Python中实现贪婪排名算法的教程
Apr 17 #Python
在Linux下调试Python代码的各种方法
Apr 17 #Python
Python脚本在Appium库上对移动应用实现自动化测试
Apr 17 #Python
Python中生成器和yield语句的用法详解
Apr 17 #Python
You might like
可以在线执行PHP代码包装修正版
2008/03/15 PHP
PHP Directory 函数的详解
2013/03/07 PHP
php根据操作系统转换文件名大小写的方法
2014/02/24 PHP
PHP二维数组排序的3种方法和自定义函数分享
2014/04/09 PHP
Yii框架安装简明教程
2020/05/15 PHP
不同编码的页面表单数据乱码问题解决方法
2015/02/15 Javascript
详解JavaScript中的自定义事件编写
2016/05/10 Javascript
JS重载实现方法分析
2016/12/16 Javascript
Angular实现表单验证功能
2017/11/13 Javascript
基于jquery实现左右上下移动效果
2018/05/02 jQuery
浅谈js闭包理解
2019/03/28 Javascript
详解Vue、element-ui、axios实现省市区三级联动
2019/05/07 Javascript
Vue父子组件传值的一些坑
2020/09/16 Javascript
在Vue中使用Echarts实例图的方法实例
2020/10/10 Javascript
[01:45]典藏宝瓶2+祈求者身心——这就是DOTA2TI9总奖金突破3000万美元的秘密
2019/07/21 DOTA
django自定义Field实现一个字段存储以逗号分隔的字符串
2014/04/27 Python
python实现将pvr格式转换成pvr.ccz的方法
2015/04/28 Python
Python中的random()方法的使用介绍
2015/05/15 Python
Python OS模块实例详解
2019/04/15 Python
python正则表达式实例代码
2020/03/03 Python
Jupyter Notebook 文件默认目录的查看以及更改步骤
2020/04/14 Python
CSS3 box-sizing属性详解
2016/11/15 HTML / CSS
HTML5 canvas基本绘图之文字渲染
2016/06/27 HTML / CSS
StubHub墨西哥:购买和出售您的门票
2016/09/17 全球购物
介绍JAVA 中的Collection FrameWork(及如何写自己的数据结构)
2014/10/31 面试题
园长自我鉴定
2013/10/06 职场文书
会计实习生工作总结的自我评价
2013/10/07 职场文书
微信营销策划方案
2014/02/24 职场文书
林肯就职演讲稿
2014/05/19 职场文书
上班离岗检讨书
2014/09/10 职场文书
公司收款委托书范本
2014/09/20 职场文书
李白故里导游词
2015/02/12 职场文书
初中英语教学反思范文
2016/02/15 职场文书
残联2016年全国助残日活动总结
2016/04/01 职场文书
SpringBoot中获取profile的方法详解
2022/04/08 Java/Android
Redis实战之Lettuce的使用技巧详解
2022/12/24 Redis