NLP 遇上中秋节

我正在参加中秋创意投稿大赛,详情请看:中秋创意投稿大赛

Word2Vec 品诗词

Word2Vec 的作用恐怕早已经大白于天下了,但是我们平时用的 Word2Vec 都是用文章来训练的,因为本人偏爱诗词,所有特意用五万多首唐诗和二十六万首宋词来训练 Word2Vec ,过程如下:

  • 只用到了每首诗或者词的主体内容,截去题目、作者、注释等无关内容
  • 因为诗词中的单字含义很丰富,所以将所有的诗或者词都分成单个汉字,写入 song_tang.txt ,每行是一首诗或者词,每个字之间用空格隔开
  • 因为诗词中也有不少词很有意境,所以用 jieba 将所有的诗或者词都分成词,每行是一首诗或者词,每个词之间用空格隔开,追加到 song_tang.txt 文件中
  • 使用 gensim 工具中的 Word2Vec 训练了 100 个 epoch 得到模型

训练代码很简单:

# -*- coding: utf-8 -*-

import logging

from gensim.models import word2vec

def main():

    logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
    sentences = word2vec.LineSentence("song_tang.txt")
    model = word2vec.Word2Vec(sentences, vector_size=250, epochs=100)

    #保存模型,供日後使用
    model.save("word2vec.model")

if __name__ == "__main__":
    main()
复制代码

测试代码也很简单:

# -*- coding: utf-8 -*-

from gensim.models import word2vec
from gensim import models
import logging

def main():
	model = models.Word2Vec.load('word2vec.model')

	try:
		for word in ['月','蟾','嫦娥','兔','中秋','赏月','桂花','花灯','饼','桂花']:
			q_list = word.split()
			if len(q_list) == 1:
				topn = 5
				print("相似詞前 %d 排序"%topn)
				res = model.wv.most_similar(q_list[0],topn = topn)

				for item in res:
					print(word,'-->',item[0]+","+str(item[1]))

	except Exception as e:
		print(repr(e))

if __name__ == "__main__":
	main()
复制代码

主要挑选了和中秋有关的常见意象包括:月、蟾、嫦娥、兔、中秋、赏月、桂花、花灯,本来还要测“月饼”,但是在这么大的诗词集中竟然没有切出来“月饼”这个词,难道古人称呼“月饼”另有其名?如果真的是这样那我凭借这一发现可以拿诺贝尔奖了吧。测试内容如下,从结果来看基本上意象是相近的:

相似詞前 5 排序
月 --> 影,0.5359682440757751
月 --> 雪,0.5294367074966431
月 --> 日,0.5167578458786011
月 --> 明月,0.5035041570663452
月 --> 晚,0.4992968440055847
相似詞前 5 排序
蟾 --> 月,0.4944111108779907
蟾 --> 蟾蜍,0.4766398072242737
蟾 --> 娥,0.4235338866710663
蟾 --> 星,0.41982918977737427
蟾 --> 嫦,0.41793638467788696
相似詞前 5 排序
嫦娥 --> 常娥,0.5356565117835999
嫦娥 --> 姮,0.46553120017051697
嫦娥 --> 素娥,0.44325411319732666
嫦娥 --> 蝉娟,0.44045501947402954
嫦娥 --> 嫦,0.4265734851360321
相似詞前 5 排序
兔 --> 鹿,0.46078577637672424
兔 --> 鼠,0.42531102895736694
兔 --> 狸,0.4184684455394745
兔 --> 獸,0.4146558344364166
兔 --> 兎,0.4029492437839508
相似詞前 5 排序
中秋 --> 重陽,0.5198861360549927
中秋 --> 今宵,0.5187360048294067
中秋 --> 清秋,0.5057112574577332
中秋 --> 今夕,0.4786747694015503
中秋 --> 元宵,0.478258341550827
相似詞前 5 排序
赏月 --> 吟风,0.42945602536201477
赏月 --> 不知今夕何夕,0.40893059968948364
赏月 --> 围棋,0.4009520709514618
赏月 --> 曾共赏,0.3729349374771118
赏月 --> 三国,0.3720923066139221
相似詞前 5 排序
桂花 --> 丹桂,0.46107402443885803
桂花 --> 桂子,0.44184908270835876
桂花 --> 菊花,0.4242440164089203
桂花 --> 桂香浮,0.40674737095832825
桂花 --> 桂枝,0.3999846577644348
相似詞前 5 排序
花灯 --> 宝幄,0.48819929361343384
花灯 --> 缟夜,0.48614564538002014
花灯 --> 暗记,0.450831800699234
花灯 --> 未晓,0.4482809007167816
花灯 --> 铜壶,0.4456891119480133
复制代码

LSTM 写藏头诗

人工智能写诗已经是一个很常见的操作,因为 LSTM 能很好捕捉到上下文的语义关系,诗词这种短小精悍的文本很适合用 LSTM ,如果对这个结构不懂可以去看我之前写的【LSTM 硬核基础讲解】。这里主要对数据的处理做简单的介绍,其他的模型搭建和训练过程套路基本不变,这里不再赘述。

文本是时间序列特征很强的数据,诗词也是如此,每句诗词都是靠含义丰富的字组成的,我们在输入当前字的时候,要预测下一个字,这就决定了我们的输入格式,例如:

原句:白日依山尽,黄河入海流

我们首先要使用"^"表示诗句的开始,"$"表示诗句的结束
变为:^白日依山尽,黄河入海流$

我们设置了最大的诗句长度为 20 ,使用"*"表示未知符号进行填充
变为:^白日依山尽,黄河入海流$*******

其对应的训练目标因为需要对当前时刻的输入来预测下一个时刻的输出,将上面的字符串整体右移,即:y[:-1] = x[1:]
目标:白日依山尽,黄河入海流$********

最后使用字典,将上面的字符串中的每个字映射为数字就完成了数据的预处理
复制代码

模型训练好,在用模型写诗的过程也和上面类似,每次输入上一个时刻的字以及上一个时刻的状态,来预测当前的字,知道满足结束条件,如够多少个字,或者遇到预测出句号为止。

那我们开始测试写藏头诗吧,主要使用了一些中秋常见的人物和话题,说实话有点人工智障的感觉,但是已经迈出了第一步了,之后可以继续完善写出诗的质量,毕竟模型也忒简单了点,就是应个景图个乐,给大家中秋助助兴。

生成藏头诗 --->  嫦娥奔月
嫦娥属星汉,娥皇历七年。奔驰一千分,月下腾双翼。

生成藏头诗 --->  吴刚伐桂
吴转唐皇观,刚将镇选门。伐乏天上命,桂下朝建皇。

生成藏头诗 --->  中秋团圆
中庭窥砌木,秋风下帘绿。团圆粉扇衰,圆珰喷祥雨。

生成藏头诗 --->  中秋团圆阖家欢乐
中原风紧动明时,秋树三川带路长。团莺盖影寻仙籍,圆光丽月照霜轮。阖章合在唯前后,家在将齐退困浮。欢趣梦阑鼙鼓至,乐声幽鸟碧云空。

生成藏头诗 --->  嫦娥奔月广寒成仙
嫦娥几多拜,娥霜五百枝。奔郎避众地,月酒动纨扇。广皓清云表,寒光照夕风。成姿素羽翼,仙殿尚依然。
复制代码

此文待续。。。

感谢

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享