Frame of 42yeah

Site Defunct

注意!截止到 16/9/2019 ,这个博客已经被搬迁到了 这里 。以后我的东西都会发在那里。拜拜啦!

用马尔可夫链生成各种文本

马尔可夫链 (Markov Chain) ,也可以叫他离散时间马尔可夫链或者别的东西(别看我,我不是专业学概率论和数理统计的好吧),是由俄国数学家安德烈·马尔可夫(Андрей Андреевич Марков)发现的。他是描述空间从一个状态到另一个状态转换的随机过程。

废话结束!

Markov chain

马尔可夫链本身其实一点都不好玩。但是有趣的地方就是因为他的特性,我们可以用它来脑作各种很傻逼的故事!这玩意不需要知道什么机器学习,神经网络之类的玩意儿,只要知道他最简单的原理就可以了。那么我们就马上来看看怎么用这个名字看起来很高端的东西来做各种奇奇怪怪的东西吧!

原理

我不是数学老师,所以很明显我是不会好好的说这个东西的;我直接用实例来开始说,好吧:

The cat asked the dog: "What is true love?" Answered the dog: "Loving the cat."

这是一段很简单的文字,或者叫 corpus (文集)。不用从网上找是从哪来的,这是我为了举个例子瞎掰的。那么马可夫链是怎么工作的呢?

走文集

首先,我们会进行一个叫做 ”走文集“ 的操作:

你可能会疑惑。为什么值是一个数组呢?因为仔细观察上面的那个文集。在里面,the dog: 这个组合出现了两次。于是在走到那里的时候,这个数组关于 the dog 的那部分就会变成这样:

{
    ...
    "the dog": [ "\"What", "\"Loving" ],
    ...
}

分别出自于 ...asked the dog: "What is t......Answered the dog: "Loving th...

因此,走完文集之后,集合应该长这样:

{ "The cat": [ "asked" ],
  "cat asked": [ "the" ],
  "asked the": [ "dog:" ],
  "the dog:": [ "\"What", "\"Loving" ],
  "dog: \"What": [ "is" ],
  "\"What is": [ "true" ],
  "is true": [ "love?\"" ],
  "true love?\"": [ "Answered" ],
  "love?\" Answered": [ "the" ],
  "Answered the": [ "dog:" ],
  "dog: \"Loving": [ "the" ],
  "\"Loving the": [ "cat.\"" ],
  "the cat.\"": [ null ] }

可以看到,最后那里结尾处就是 null ,也被叫做 suffix 。从我刚刚说的话可以推断出,第一句话(也就是第一个词和第二个词的组合),当然也就叫做 prefix 了。

prefix 自己应该自成一个数组,这样程序就知道应该从什么开始脑作了: [ "The cat" ] 。因为我给的文集太小(只有一句话),所以当然只有一个词了。当文集变大之后,就不是这么简单了。具体的会在后面说。

那么既然文集已经走完了,并且我们已经有了整个这个集合和一个 prefix 的集合了,我们就可以开始生成文本了!我们先从 prefix 开始,一句句的生成吧:

生成文本

生成文本的过程非常简单。先从 prefix 开始,不断检查这句话目前的最后两个单词对应集合内哪个键位,有什么元素,然后就把元素加上去(有点像链表):

  1. The cat
  2. [The cat] -> asked
  3. The cat asked
  4. The [cat asked] -> the
  5. The cat asked the
  6. The cat [asked the] -> dog:
  7. The cat asked the dog:
  8. The cat asked [the dog:] -> "What, "Loving

现在这里停一下。很明显这里出现了分叉!这就是马尔可夫链的美妙之处了:现在我们假设我们完全随机的选了后面那个。好了继续:

  1. The cat asked the dog: "Loving

再停一下。这里出现了些很丑陋的情况,譬如这个引号开了不一定会有的关(这里的确有的关,但在别的情况里就不一定了)。这个就你们自己去解决吧,我就算了,毕竟年纪大了:

  1. The cat asked the [dog: "Loving] -> the
  2. The cat asked the dog: "Loving the
  3. The cat asked the dog: ["Loving the] -> cat."
  4. The cat asked the dog: "Loving the cat."

至此,一段由马尔可夫链生成的废话完成。在这种情况下,这就是很符合语法的废话:对面完全没有感受到上下文,并且其实本身的意义也好像没有。但是管啥呢!从此,你可以用马尔可夫链生成废话和别人聊天了!

文集能大一点吗?有很多句话怎么办?

很简单,我们只要把这个大的文集用句号分割:

let paras = corpus.split(".");

然后对于 para 里面的每一段,都把它走一次就行了!(记得在句尾把句号加回去!)假如你想要,也能根据叹号逗号诸如此类的来分割,完全没问题:

for (let i = 0; i < paras.length; i++) {
    walk(paras[i] + ".");
}

对于你自己来说,假如要生成多个段落的话,只要重复执行几次生成那个步骤就可以了!

写作手法

我们都知道,不同的作者有不同的写作手法。挑选的文集不一样通常也会出现各种各样的结果。假如我们挑选很科幻的文章(例如阿西莫夫的《基地》),就会出现各种高端科学字眼。假如我们挑选魔幻的文章(《指环王》!),就会出现魔幻的字眼。假如我们挑选科学性的文章(论文?)就会出现很严谨的字眼,让整篇文章虽然看不懂,但好像跟论文一样。把不同文学作品混在一起还会出现很多奇怪的玩意儿。你也能用这个来生成属于自己的 lorem ipsum!

当然,在哪里能看这么多免费网上爽文呢?当然是 古登堡计划 啦!有个不好的地方,就是我上面括号里的文章都不在……因为他们还有版权。

实例

说完了!接下来假如你自己想玩又不想写,这里是一个小玩具:

生成

故事

以下内容不是我写的。

评论区