/>

NLP入门:基于马尔可夫链的随机百科(二)

最近很忙,本来想着中考后再更新,但既然今晚睡不着,那就继续填坑吧。上回我们训练出了一个包括语料中所有三元组的概率模型,这次就来讲讲如何通过这个概率模型来让机器生成文本。

直接上代码

理论性的东西差不多都讲过了,可以直接阅读代码来了解原理。

开始肯定是要将两个存储在文件里的模型导入。

首先确定第一个前缀和你想要生成的长度,接着开始循环,每次循环的开始都是输出前缀的第一个元素,然后声明一个用来存储以当前pre为前缀的三元组及其概率的字典items和一个用来存储当前前缀的所有后缀的列表li,并将索引字典中该前缀对应的值(类型即为列表)赋给它。接下来就遍历li中的值,将空空如也的items用概率模型中存有的该前缀开头的三元组及其概率的键值对填充。

关键的来了,接下来的正式生成环节,本质上是从所有备选项中选出最合适的那个,与当前前缀的第二个元素组成一个新前缀。不过,再看看标题,“随机”二字如何体现?为了防止生成的文本看上去像是在复读语料内容,我们草率地引入一个新的选择机制:求出所有待选三元组的概率平均值,如果某个待选三元组的概率大于或等于这个平均值,就将它的后两个元素组成的元组,也就是有可能成为新前缀的那个两元组,放到choices里等待下一轮的随机选取。这样可以使得生成的文本不那么复读,同时大体上保证生成质量。

现在就是真随机环节了,调试的过程中我发现choices有为空的情况(具体为啥暂时不是很确定,可能会在下一章中讨论),所以这里加了个条件判断,不为空就在choices中随机选取,否则在所有后缀中选取。这样我们就得到了新的前缀,可以继续按照这样的方法来往后推。

来看看程序生成的几个结果吧(截头去尾,下面引用栏中的所有内容均为程序根据算法自动生成,绝不代表任何事实或观点,请不要相信这些内容,否则本人不承担任何后果):

1、哲学是一门对生物细胞的生物技术,其中第一乐章是葬礼哀歌。这种温度下,2012年伦敦奥运会的足球比赛。足球是一种新元素,并警告会产生火焰的颜色来识别……

2、……对,我总是呼吁和平。虽然很多人不满意……

3、……反之,当用户查询“more a Salesman",是比formula_85,则三角形面积是长蛇座、六分仪座矮星系。这些由大气或相关的死亡发生在三个或三个以上电感器的缠绕方式……

嗯,非常随机,非常愚蠢,真是人工智障的大成功(手动滑稽)。

还有,其他我都能理解,那个“more a Salesman"一个全角引号一个半角引号是真神奇。

一些后话

暂时还不建议你对这些代码的成熟性抱有太大期望,因为它们还存在一些问题,比如有时会出现接不下去的情况(要是开局的前缀语料里没出现过那就更别玩了),而且它们在运行过程中有可能会出现我这边没有出现过的问题,这些问题我会慢慢去解决。

不过如果你有兴趣试一试或者想要帮着改进一下的话,可以拿去玩玩,我也会把训练好的模型放出来,但你的电脑最好有8G或以上的内存,因为以目前的优化程度来看,即使是一个小模型,占用内存还是比较多的,这里使用的语料库大约是16万个维基百科词条,并不多,但概率文件还是有800余兆,索引文件也有400余兆,加载到内存里也不少了(如果你有工作站或大型服务器,别管我说的这些,直接跑他一个维基百科)。

关于这个程序之前和后续的优化,以及一些问题的发现与解决,我会也许在下一章在谈谈(看情况,也不一定出)。能看到这里真是非常感谢,如有你有任何问题或我有任何问题,都请提出,再次感谢。

 

icecream

2020/3/7