在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 相关文章推荐
Python md5与sha1加密算法用法分析
Jul 14 Python
Python图像处理之图像的缩放、旋转与翻转实现方法示例
Jan 04 Python
Python简单I/O操作示例
Mar 18 Python
微信公众号token验证失败解决方案
Jul 22 Python
Django错误:TypeError at / 'bool' object is not callable解决
Aug 16 Python
关于Python核心框架tornado的异步协程的2种方法详解
Aug 28 Python
django-rest-swagger的优化使用方法
Aug 29 Python
基于python3监控服务器状态进行邮件报警
Oct 19 Python
python文件操作的简单方法总结
Nov 07 Python
opencv3/C++实现视频背景去除建模(BSM)
Dec 11 Python
Python3 字典dictionary入门基础附实例
Feb 10 Python
聊聊python中的循环遍历
Sep 07 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
使用 MySQL Date/Time 类型
2008/03/26 PHP
php中计算程序运行时间的类代码
2012/11/03 PHP
thinkphp中session和cookie无效的解决方法
2014/12/19 PHP
php curl 上传文件代码实例
2015/04/27 PHP
如何在标题栏显示框架内页面的标题
2007/02/03 Javascript
js获取div高度的代码
2008/08/09 Javascript
web 页面分页打印的实现
2009/06/22 Javascript
jQuery实现表单input中提示文字value随鼠标焦点移进移出而显示或隐藏的代码
2010/03/21 Javascript
JS字符串处理实例代码
2013/08/05 Javascript
jquery等待效果示例
2014/05/01 Javascript
5个数组Array方法: indexOf、filter、forEach、map、reduce使用实例
2015/01/29 Javascript
一道常被人轻视的web前端常见面试题(JS)
2016/02/15 Javascript
JavaScript实现跑马灯抽奖活动实例代码解析与优化(二)
2016/02/16 Javascript
jquery通过name属性取值的简单实现方法
2016/06/20 Javascript
如何以Angular的姿势打开Font-Awesome详解
2018/04/22 Javascript
浅析Vue中拆分视图层代码的5点建议
2019/08/15 Javascript
Cordova(ionic)项目实现双击返回键退出应用
2019/09/17 Javascript
[07:31]DOTA2卡尔工作室 英雄介绍主宰篇
2013/06/25 DOTA
Python扫描IP段查看指定端口是否开放的方法
2015/06/09 Python
Python 用Redis简单实现分布式爬虫的方法
2017/11/23 Python
python 获取utc时间转化为本地时间的方法
2018/12/31 Python
python调用自定义函数的实例操作
2019/06/26 Python
如何安装并使用conda指令管理python环境
2019/07/10 Python
python实现PDF中表格转化为Excel的方法
2020/06/16 Python
python中np是做什么的
2020/07/21 Python
详解如何修改python中字典的键和值
2020/09/29 Python
python list等分并从等分的子集中随机选取一个数
2020/11/16 Python
CSS3基础(RGBa、text-shadow、box-shadow、border-radius)
2012/11/13 HTML / CSS
laravel使用redis队列实例讲解
2021/03/23 PHP
资产经营总监岗位职责
2013/12/04 职场文书
2014年辅导员工作总结
2014/11/18 职场文书
领导欢迎词范文
2015/01/26 职场文书
队名及霸气口号大全
2015/12/25 职场文书
Angular CLI发布路径的配置项浅析
2021/03/29 Javascript
python脚本框架webpy模板赋值实现
2021/11/20 Python
详细介绍Java中的CyclicBarrier
2022/04/13 Java/Android