Python20行实现马尔科夫链的鸡汤生成器

原文地址:
https://codeburst.io/how-i-generated-inspirational-quotes-with-less-than-20-lines-of-code-38273623c905 作者:Ramtin Alami

马尔科夫链

本文是我的一些简单翻译和理解(删了很多趣味性的话,为了少打字。。。。),如果翻译引起的对于作者猫的不尊重请与我联系。
非常推荐直接阅读原文

我有一只猫, 每天吃了吃喝玩乐睡(幸福呀~~),醒了就直接去玩那是几乎不可能,但是吃了饭那很有可能就要开始闹腾了。下面这个图:这里写图片描述
每一个圈表示状态,箭头上的数字表示到下一个状态的概率在重点在于:
转移的概率只依赖与先前的状态

基于马尔科夫链的文字生成器

I like to eat apples.
You eat oranges.

这两个句子就是训练集,你会发现I like to 和You总是和eat的一起,eat后面跟apples还是oranges概率是平等的。概率转移图如下:
这里写图片描述
用这个模型,我们能产生两个新句子:

I like to eat oranges.
You eat apples.

但是我用下面这几个句子去训练,结果就很不一样了。

my friend makes the best raspberry pies in town
i think apple pies are the best pies
steve thinks apple makes the best computers in the world
I own two computers and they’re not apple because I am not steve or rich

尽管复杂了一些,但是原理还是一样的,从start节点开始随机到下一个节点知道终止,图示如下:
这里写图片描述
尽管只有四句化,却能产生几百句话:
这里写图片描述

代码

很简单,就用python的random module就好了,包括两部分,一个训练,一个生成句子

Training

代码构建的model是一个字典,字典的key是一个节点,对应的vaule是key的那个节点相连的可能节点,
比如之前两个句子‘I like to eat oranges’, ‘You eat apples’ 构建的字典大概是这样的:

{'START': ['i', 'you'], 'i': ['like'], 'like': ['to'], 'to': ['eat'], 
'you': ['eat'], 'eat': ['apples', 'oranges'], 'END': ['apples', 'oranges']}

不需要去统计概率,如果出现了多次,就在字典里面添加两个就好了,比如在了一个句子‘we eat apples,那么自己就变成:

{'START': ['i', 'we', 'you'], 'i': ['like'], 'like': ['to'], 'to': ['eat'], 
'you': ['eat'], 'we': ['eat'], 'eat': ['apples', 'oranges', 'apples'], 
'END': ['apples', 'oranges', 'apples']}

有两个额外的节点START和END是为了让我们只让哪里开始什么时候结合

for line in dataset_file:
    line = line.lower().split()
    for i, word in enumerate(line):
        if i == len(line)-1:   
            model['END'] = model.get('END', []) + [word]
        else:    
            if i == 0:
                model['START'] = model.get('START', []) + [word]
            model[word] = model.get(word, []) + [line[i+1]] 

Generation

从start的单词随机选一个,加到list里面,然后在这个单词的相连的下个单词在随机选一个加到list,一直循环直到end

import random 

generated = []
while True:
    if not generated:
        words = model['START']
    elif generated[-1] in model['END']:
        break
    else:
        words = model[generated[-1]]
    generated.append(random.choice(words))

猜你喜欢

转载自blog.csdn.net/renhaofan/article/details/82191387