在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 sqlobject(mysql)中文乱码解决方法
Nov 14 Python
详解Python中的正则表达式的用法
Apr 09 Python
Python随机数random模块使用指南
Sep 09 Python
flask使用session保存登录状态及拦截未登录请求代码
Jan 19 Python
python+ffmpeg批量去视频开头的方法
Jan 09 Python
pandas实现将dataframe满足某一条件的值选出
Jun 12 Python
Python获取命令实时输出-原样彩色输出并返回输出结果的示例
Jul 11 Python
Python zip函数打包元素实例解析
Dec 11 Python
python实现UDP协议下的文件传输
Mar 20 Python
Django 解决由save方法引发的错误
May 21 Python
Python3中对json格式数据的分析处理
Jan 28 Python
pandas时间序列之pd.to_datetime()的实现
Jun 16 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抽象类用法实例分析
2015/07/07 PHP
详解PHP编码转换函数应用技巧
2016/10/22 PHP
swoole和websocket简单聊天室开发
2017/11/18 PHP
PHP变量的作用范围实例讲解
2020/12/22 PHP
jQuery 页面 Mask实现代码
2010/01/09 Javascript
jQeury淡入淡出需要注意的问题
2010/09/08 Javascript
探讨jQuery的ajax使用场景(c#)
2013/12/03 Javascript
js 判断图片是否加载完以及实现图片的预下载
2014/08/14 Javascript
Javascript实现飞动广告效果的方法
2015/05/25 Javascript
适用于javascript开发者的Processing.js入门教程
2016/02/24 Javascript
jquery.cookie.js实现用户登录保存密码功能的方法
2016/04/15 Javascript
JS数组操作(数组增加、删除、翻转、转字符串、取索引、截取(切片)slice、剪接splice、数组合并)
2016/05/20 Javascript
js实现微信/QQ直接跳转到支付宝APP打开口令领红包功能
2018/01/09 Javascript
js动态添加表格逐行添加、删除、遍历取值的实例代码
2018/01/25 Javascript
web前端页面生成exe可执行文件的方法
2018/02/08 Javascript
redux-saga 初识和使用
2018/03/10 Javascript
JS双向链表实现与使用方法示例(增加一个previous属性实现)
2019/01/31 Javascript
ES6模板字符串和标签模板的应用实例分析
2019/06/25 Javascript
angular *Ngif else用法详解
2020/12/15 Javascript
原生JavaScript实现留言板
2021/01/10 Javascript
[07:25]DOTA2-DPC中国联赛2月5日Recap集锦
2021/03/11 DOTA
浅谈django开发者模式中的autoreload是如何实现的
2017/08/18 Python
Ubuntu下使用Python实现游戏制作中的切分图片功能
2018/03/30 Python
浅析Django中关于session的使用
2019/12/30 Python
python3通过subprocess模块调用脚本并和脚本交互的操作
2020/12/05 Python
应用化学专业本科生求职信
2013/09/29 职场文书
捐赠仪式主持词
2014/03/19 职场文书
工商管理专业毕业生求职信
2014/05/26 职场文书
2014年国庆标语
2014/06/30 职场文书
幼儿园植树节活动总结
2014/07/04 职场文书
镇创先争优活动总结
2014/08/28 职场文书
抗洪救灾感谢信
2015/01/22 职场文书
商务司机岗位职责
2015/04/10 职场文书
话题作文之成长
2019/12/09 职场文书
Python爬虫基础初探selenium
2021/05/31 Python
Python实现日志实时监测的示例详解
2022/04/06 Python