跳到主要内容

古诗生成模型

· 阅读需 30 分钟

去年学习语言模型的时候做了个练习,训练了一个生成古诗的模型,可以在这里测试: http://www.qizhen.xyz/
虽然已经有一段时间每碰它了,但还是抽空总结一些相关的想法。

为什么采用诗而不是其它文体做练习?

因为对于机器学习模型来说,写诗的难度远低于写其它文体。总的来说,文体的长度越短,越容易使用模型来创作。目前常见的机器学习模型的记忆力都比较有限的,生成的文字越多,可能就会越偏离最初的主题。
一首古诗一般就几十个字,用我的个人电脑就可以训练出一个效果还不错的模型。一篇散文常常要几百字,若想训练一个能产生满意结果的模型,就需要分布式运算了。至于写小说,设置一个悬念,几十万字之后再来解开悬念,机器学习要达到这种能力恐怕还需要些年头。
选择古诗做练习的另一个好处是,训练集数据丰富,而且没有版权问题。

诗词在当今社会几乎没有什么影响力了。诗词的黄金年代无疑是唐宋。即使是之后的朝代,民间对诗词的推崇有所下降,但诗词仍是练习科举作文的基本功,依然有刚性需求。然而当今这个年代,诗词的空间几乎都被其它文艺形式占据了。诗词成了只有极少数人还在关注的小众爱好。更糟糕的是,在这少数人中,年轻人的比例更低。
被大众接受的文艺形式必定是欣赏的人远多于创作的人。典型的例子是,视频网站多是靠观众养活的,或者收观众的会员费,或者让观众看广告买东西等。但诗词网站却是靠作者来养活的,收作者的会员费。曾经写诗是创作,而如今写诗却成为了一种消费。一个缺少观众的文体,创作者队伍也很难壮大。
诗词已经没有什么不可替代的应用场合了。如果一定列出一些应用价值,那大概就是在庆典活动中用来做点缀吧。作为点缀,观众甚至都不太会注意到诗词的质量,更别提欣赏了。还有就是社交价值,如果恰好遇到诗友可以聊聊天,就好像球迷们一起聊球。 至于鉴赏,海量的古诗词还鉴赏不过来呢,新诗词在艺术价值上完全没法与古诗词相提并论。

诗词没有市场需求,大型文体目前的模型又处理不了,那么语言生成模型还有啥适合的应用吗?还是有的,比如我现在最烦的是要定期写工作总结,还要给同事领导写评语。其它单位或者公司也都有定期的提交各种心得体会、思想进步之类的硬性要求。如果AI可以在这方面创作有所提高,必然前景不错。我如果有机会得到这方面的训练数据,肯定会尝试一下的。
再拓宽一点,文字创作的需求可能不如音乐创作的需求更强烈。现在哪个视频节目需要配乐呢,专业的视频内容可能无法自动生成,但配乐没什么特殊需求的,还是可以靠AI来大量制作的。

计算机作诗的各种算法

一、基于规则的写诗算法
人们最初使用计算机解决各种问题的时候采用的都是同样的思路,就是列出解题的规则,然后按步骤翻译成计算机指令一步一步执行就行了。很多诗词还是一些比较严格的规则的:篇有定句,句有定字,字有定声,联有定对。比如五言绝句必须四句,每句五字;第一句若是平平平仄仄,则第二句一般为仄仄仄平平;第二句若以韵母eng结尾,则第四句也应当是eng结尾等等。
规则是最容易被编程实现的,因此也是被早期写诗程序广泛采纳的算法。然而基于规则的写诗算法却几乎写不出任何通顺的诗来。比如,这一句就是在基本规则指导下产生的句子:“音挑山落但,下剩物拼贪。”没人会喜欢这样的诗句。
这首先是因为写诗仅仅遵循以上列出的几条规则还远远不够,写诗还要遵循词法语法的规则,比如声音洪亮可以,跑步洪亮不可以;还要遵循自然的规则,比如乌云密布就不可以同时晴空万里;还要遵循情感的规则,比如见到大海心情开阔,见到落花黯然神伤等等。且不说这里面大多数规则都是只可意会不可言传的,即便是那些明确的表面规则,若要写全,也需要逐字给每个字开列出一大串规则来。根本没人有能力和精力来做这样的工作。
其次,规则就是用来被打破的,真正的好诗才不会被规则所限制。比如“白发三千丈”可以无视自然规则。
能总结出来的规则都没什么用,有用的规则都是可意会而不可言传的。基于规则的算法就此也就走到头了。

二、从规则到规律
计算机和人的能力有个互补的地方,计算机可以一极快的速度列出所有符合规则的文字;人类这方面能力有限,即便是经过专业训练的,也只能一下子想出少部分这样的文字,其它的要借助查资料等辅助手段。而接下来,如何从众多符合规则的字词中选出一个合适的,则是人类远胜于计算机的地方。如果你不告诉计算机怎么挑,计算机只能随机选一些字,质量可想而知。
按直觉想,只要继续添加规则,指导计算机挑选出最合适的文字不就可以了嘛。但是这需要添加太多太多的细节规则,已经没人有能力列出所有这些规则来了。人虽然没能力了,让计算机帮忙归纳总结一下可不可以呢?

规则是人为制定的。这就意味着第一,它只会是少量的方向指导性的,并不能解决任何细节技术问题。第二,只要有前人制定了规则,就一会有后人来打破规则。规律是客观存在于已有作品中的,有些规律可能根本不是作者有意为之的,但它就是自发的形成了。既然规则指导不了细节,也许可以利用一下其它作品中的规律来做指导。这其实跟一个人学习写诗的过程也十分类似。开始学习了基本规则,然后还要大量阅读其他人的作品,体会他人的作品哪好哪不好,在用于自己的作品才能写出好诗来。

利用统计学的方法,还是可以比较容易的计算出古诗词中的一些规律来的。最直接的,高频词。比如,统计出来的《全宋词》高频词包括:东风,何处,人间,风流,归去,江南,西湖,斜阳,明月等。高频词就是大家看着最顺眼的那些词,如果计算机从这些刚频词中选词,而不是随机挑选,那么结果也会顺眼的多。比如将宋词中的高品词随机组合一下:“回首明月,悠悠心事空,西湖何事寂寞中,风吹斜阳匆匆”,不那么别扭了吧。这也是为什么总有人说计算机写出来的诗怎么感觉都眼熟的原因,因为大量使用了高频词啊。

只考虑词频显然还不够,就算都是频词搭配起来也可能还是非常别扭的,比如:“江南大漠凭栏鱼”。所以还要考虑搭配,比如“流水”经常搭配“浮萍,恋恋,落花,相随”等词。那么,如果诗中如果已经选了流水,就应该尽量从搭配流水的高频词里继续选。其它的还有很多规律可以总结,比如对账的规律“云对雨,雪对风,晚照对晴空”,等等。

有了这么多细节的规律帮助,写诗程序可能依然还是很烂。说实话,研究这些的大多是写诗外行,包括我在内,我自己都不会写诗,又能想到多少有用的规律呢?更多的规律是我想不到的,比如很可能在某个特定的地方放个特定的夸张就会有神奇的功效?或者放个谐音梗?或者就是我完全想象不出来的。

我想不出来的,能不能让计算机去想呢?让计算机不但帮我把规律的数据计算出来,还要帮我研究需要总结哪些规律,甚至是我都想象不到的规律?

三、基于机器学习的写诗算法

“机器学习”从名字也能看出来就是让计算机自己学习,简单来说,你给计算机提供一个训练集,比如以《唐诗三百首》为训练集。也不必告诉计算机怎么学,学什么,反正计算机自己去研究吧,然后计算机利用它学习到的知识输出一些东西出来。
机器学习不是什么新东西,也发展了几十年了。
在自然语言处理方面机器学习的应用也是十分广泛的。然语言处理常见的几种问题包括:分类(比如判断一封信是否是垃圾邮件);知识问答;总结中心思想;翻译;聊天对话等等。不过所有这些问题都是相通的,用一个文字生成算法就可以解决所有问题。文字生成是指给计算机一段上文,然后计算机生成一段下文。比如,上文是一封信,下文“是”或“否”,就可以用来判断垃圾邮件了;上文给一段中文,下文生成英文就是翻译;上文是上联,下文生成下联,就解决了对联问题;上文标题,下文生成诗句,就解决了写诗问题。
机器学习中有各种各样的算法,简单问题,比如垃圾邮件分类,使用简单的贝叶斯分类算法就可以得到比较完美的解决。不过像文字生成这样复杂的问题,就必须用到人工神经网络了。人工神经网络借鉴了动物大脑的结构,依靠神经元组成的网络来模拟和解决各种问题。人工神经网络可以学习,然后根据学习到的东西输出一些数据。对于复杂的人工神经网络,人类已经不能完整的分析出它们到底学了什么内容,只知道学习的效果不错。
当年在学校学习是做的人工神经网络作业,建立的网络只有二十几个节点(神经元)。后来解决一些稍微复杂点的问题也不过就用几百个节点,还比不上蚯蚓的“大脑”。生成文字问题可是复杂的多的问题,小的神经网络很难产生满意的效果。生成单词词组一般至少需要上千个节点;生成句子就要再多几个数量级:我训练的诗词生成模型的节点数已经过亿了。目前,在文字生成领域表现的比较好的一个模型叫GPT3,它有超过一千七百亿个节点。这个数量已经超过人类大脑皮层神经元的数量了,不过不用担心,人工神经网络的效率远远不及人脑,人工神经网络的节点数很可能每年都有翻倍,但即便如此,它们也不会在未来几年内具有真正匹敌人类的创作能力,尤其是像小说这样的大部头文字。
有了这么强大的机器学习功能,我这种门外汉也不需要太了解诗词创作的技巧了。把现有的诗词交给机器,让它学就是了呗。可是这样学出来的机器也只会输出它学过的那些诗词里有的东西啊。举个例子,假如《唐诗三百首》里只有关于牛的诗,没有任何提到羊的诗,那么机器很容易就学会了,牛吃草,牛挤奶。机器也只会写牛吃草,牛挤奶之类的东西,它永远也不会自主写出羊吃草,羊挤奶,虽然对于人类来说这是非常自然的可以借鉴过去的。

更多的知识可能并不在训练集中,要让模型掌握这些知识,仅仅使用训练集是不够的。需要首先使用预训练集对模型进行初步训练。比如使用维基百科上的所有内容对模型进行预训练,让模型先学会一些基本知识,比如牛和羊是非常相关、类似的动物。这样之后,在使用诗词对模型进行训练,模型会利用之前预训练时掌握的一些知识。在诗词训练集中学到了牛吃草,那么,模型也会根据之前掌握的知识,创作出羊吃草这样的文字。

我做的练习模型

一、模型选择
我在自己做练习之前,先查看了一下能够找到的别人写的一些诗词生成模型。使用简单的LSTM、seq2seq等模型是不太容易生成行文自然的诗句的。真正效果好的模型都是最近两年在超大模型比如BERT,GPT等基础上构架上训练的。我在github上看到一些例子,效果真的很好,我作为理科生,已经分辨不出某些诗句是AI还是真人写的了。

肯定是越大的模型效果越好,但是越大的模型训练越费时费钱。
另外一个考虑的因素是,有的预训练模型可以直接做文本生成,有的还需要在附加一些神经网络层才可以。我用了GPT2的小型模型做练习,这个模型写大文章可能差点,但应付诗词还可以;而且GPT2可以直接生成文字,用起来很方便。
GPT2在某些情况下,可能还是太费钱了一些。训练一个GPT2模型一般最多两三天吧,就算用GPU,只租两天也不算是太贵。可是要长期发布就麻烦了。这个GPT2模型如果只使用CPU做预测,当下主流电脑做一个预测需要十秒钟以上,有点太长了。使用GPU,速度可以快一百倍左右,但价格也差不多要高一百倍。目前租一个云服务器,只用CPU的话,第一年只需要¥70左右;租一个带GPU的,需要¥7000每年。

二、训练集选取
整个项目里,整理训练集是最费时间和精力的工作。对于多数机器学习项目,都是训练集越大效果越好,但是做诗词生成也学并不是的。古人创作过无数的诗词,能广为流传的是极其少数的一部分。也就是说,我们能够整理出来的诗词大多数其实写的并不好,如果让电脑跟它们学,恐怕也学不了多好。理想情况是只收集那些高水平的诗词。另外,太多的训练数据会激励算法使用一些不太常用的字词来作诗。这些词语如果应用不当,就非常影响作品可读性。反之,风月、云雨、山水等高频词,无论如何搭配,读起来都不至于太别扭。

当然小数据集也有缺点,它只会覆盖部分主题。我实验有了相对较小的数据集,主要包含了《千家诗》、《唐诗三百首》和其它一些我个人比较喜欢的诗词。训练好的模型对于处理风花雪月这类常见题材是可以产生出相对不错的结果,但是如果让它写个没训练过的内容,比如关于建设现代化等的题材,就没办法生成的很好了。

如果资源足够,采用大训练集,给不同质量的诗词配上不同的权重,应该可以获得更好的训练结果。

合辙押韵是诗词的一个非常重要的属性,但是我在练习中没有考虑这一问题。为程序添加人为指定的平仄,尾韵等规则并不是一个好的办法。因为那些最为脍炙人口的古诗中,很大一部分,以现在的读音朗读都不在押韵,或者至少不是精确的押韵了。一首诗读起来顺不顺耳,最主要的还不在于是否押韵,而是是否耳熟。我们从小就背着那些不再精确押韵的古诗,审美早已适应这种宽松的规则了。过度强调押韵反而会影响生成诗词的质量。

最好的办法还是让模型自己去学习韵律。我的训练集只包含文字,没有文字的发音信息,所以模型无法学到发音规律。只要把字音信息也加入数据集,把数据集中的每一个字都扩展为“字+拼音”的格式。比如,原本数据集中的文字是“风雨送悲声”,改为“风feng1雨yu3送song4悲bei1声sheng1”。这样一来,文字的平仄韵律信息就都有了。模型自然也就可以学习到如何押韵了。
同理,我在训练的时候也没有把文字是如何书写的这个信息传递给模型,所以模型绝对不会掌握比如对拆字联这样的功能。如果把文字的书写信息(使用图像,或者抽象成偏旁部首)加入训练集,那么模型就可以学习到与书写有关的功能了。

三、损失函数
我偷懒,使用了默认的损失函数,也就是说,训练时没有添加额外规则。但实际上这样会影响模型的效果。一些规则,模型是很难自己学习到的,尤其是数据集也不够大的情况。比如,押韵、用词要丰富多彩等一些规则,模型自己领悟不到。
通过挑选训练集,可以弥补一部分不足,比如比如尽量避免有重复词的诗句,以方便模型更快的掌握这个规律。

四、训练时间
看别人的经验,训练时间在使用GPU的情况下一般一两天。这与模型大小和数据集有关。我试验的模型和数据集都不算太大,用GPU一两个小时效果就已经不错了。这时候,模型还会时不时产生一些莫名其妙的结果。增加训练时间,可以让模型产生更规范的结果,但同时,也会削弱预训练数据的作用。个人感觉,虽然这时候模型的输出减少了明显错误,但也同时减少了惊艳的诗句。可能模型也跟人一样,要有创造力、要天马行空才能写出神句来。学习的太多,反而影响创造力。
我也试了一下只使用CPU做训练,比使用GPU要慢一两个数量级。

五、生成结果
我个人纯理工背景,文采很差,对于诗词的好赖,只能大致一评。

我觉得程序生成的诗词基本还行吧,虽然也有一些不足。首先是生成的诗完全没有考虑押韵。其次是生成的诗不是每一首都令人满意的。当然也可能我的水平太差,看不懂模型生成文字的深意。不过以我的水准来评判,程序有时还是会产生一些相当不错的诗句的。我在计算机生成的诗篇里挑拣了一些,个人认为还算可以的,发表到了一些诗友论坛。诗句文采怎样先不论,至少没有读者跳出来说你这根本不是人话,也算是成功了。

首先测试作对。吟诗常以做对为基础嘛。以“倦鸟无心归去”为上联,电脑对下联“野花有意偷开”。对的妙啊,能把“花”和“开”联系起来就算不错了,还能把“野”和“偷”关联上,已经超出我的预料了。我不相信电脑真的明白什么是野花,也许只是在训练集或预训练集中野花总和偷摸之类的词在一起吧。但无论怎样,这表明电脑水平还是可以的。
有时候模型写的对联思路极其开阔。比如看到这一副生成的对联时,我差点一口老血喷到屏幕上:“千家百姓,共建和谐社会;三宫六院,同沾雨露春风”。

诗人一生的经历都会体现在作品里,比如,读李煜的诗,就总是会联想到他亡国之君的悲伤;读苏轼的诗,会让人燃起在逆境中乐观的态度。计算机没有任何过往经历,它堆出来的词再美丽也也没有任何内涵。但反过来,(高情商说法)也可说电脑作诗最擅长那些不需要具体内容的空洞题材,比如说泛泛的写景,赞美称颂等等。而且,前面也讨论过,如今社会有使用需求的恰恰也是这一类的诗。比如写马屁诗,模型一分钟至少能写八百首。

模型可以日夜不停的写,我却没有精力去读,随便摘取了一些:

风牵残阳过,云披暮雨收。红尘千里远,白发几时休。 故国关山外,天涯岁月悠。相思不可寄,惟有旧时愁。

水静月高影自长,山空竹瘦共疏凉。世间多变心如水,春雨随风落蕊香。

痒处难禁手自抓,一番搔过又重加。无穷欲念生烦恼,忍得方知气自华。

太虚无色夜澄清,万象悠悠映远星。俗世尘埃皆是幻,心归净土自安宁。