在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中的CURL PycURL使用例子
Jun 01 Python
python进阶教程之异常处理
Aug 30 Python
基于scrapy实现的简单蜘蛛采集程序
Apr 17 Python
python实现随机森林random forest的原理及方法
Dec 21 Python
使用python和Django完成博客数据库的迁移方法
Jan 05 Python
Python操作Oracle数据库的简单方法和封装类实例
May 07 Python
python使用knn实现特征向量分类
Dec 26 Python
在python下读取并展示raw格式的图片实例
Jan 24 Python
python将时分秒转换成秒的实例
Dec 07 Python
Python3实现个位数字和十位数字对调, 其乘积不变
May 03 Python
使用python求斐波那契数列中第n个数的值示例代码
Jul 26 Python
Python 中 Shutil 模块详情
Nov 11 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 ci框架验证码实例分析
2013/06/26 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(三)
2014/06/23 PHP
PHP中配置IIS7实现基本身份验证的方法
2015/09/24 PHP
PHP实现的一致性哈希算法完整实例
2015/11/14 PHP
thinkPHP框架实现的短信接口验证码功能示例
2018/06/20 PHP
laravel 框架配置404等异常页面
2019/01/07 PHP
通用javascript脚本函数库 方便开发
2009/10/13 Javascript
JavaScript中的prototype和constructor简明总结
2014/04/05 Javascript
javascript中的括号()用法小结
2014/04/14 Javascript
javascript实现信息增删改查的方法
2015/07/25 Javascript
node.js使用cluster实现多进程
2016/03/17 Javascript
jQuery获取父元素节点、子元素节点及兄弟元素节点的方法
2016/04/14 Javascript
Bootstrap栅格系统简单实现代码
2017/03/06 Javascript
vue组件中点击按钮后修改输入框的状态实例代码
2017/04/14 Javascript
vue路由拦截及页面跳转的设置方法
2018/05/24 Javascript
微信小程序dom操作的替代思路实例分析
2018/12/06 Javascript
使用Vue实现移动端左滑删除效果附源码
2019/05/16 Javascript
Element ui 下拉多选时新增一个选择所有的选项
2019/08/21 Javascript
vue柱状进度条图像的完美实现方案
2019/08/26 Javascript
vue实现分页加载效果
2019/12/24 Javascript
[46:48]DOTA2上海特级锦标赛A组小组赛#2 Secret VS CDEC第三局
2016/02/25 DOTA
[01:03:59]2018DOTA2亚洲邀请赛3月30日 小组赛B组VGJ.T VS Secret
2018/03/31 DOTA
python操作日期和时间的方法
2014/03/11 Python
使用Python脚本zabbix自定义key监控oracle连接状态
2019/08/28 Python
python实现飞机大战项目
2020/03/11 Python
Python Matplotlib绘图基础知识代码解析
2020/08/31 Python
任意一块网页内容实现“活”的背景(目前火狐浏览器专有)
2014/05/07 HTML / CSS
用纯CSS3实现网页中常见的小箭头
2017/10/16 HTML / CSS
css3 transform过渡抖动问题解决
2020/10/23 HTML / CSS
HTML5 虚拟键盘出现挡住输入框的解决办法
2017/02/14 HTML / CSS
教室标语大全
2014/06/21 职场文书
2014财务年度工作总结
2014/11/11 职场文书
2014年幼儿园园务工作总结
2014/12/05 职场文书
Laravel中获取IP的真实地理位置
2021/04/01 PHP
浅谈Redis存储数据类型及存取值方法
2021/05/08 Redis
Python用any()函数检查字符串中的字母以及如何使用all()函数
2022/04/14 Python