文本生成
最近生成型的网络越来越火,就试着模型写写诗歌。网上这方面的资料和现成的代码还是挺多的。不过大多都是tensorflow,少量torch,我平时keras用的多一些,就想着用keras来写一下,效果比tensorflow还是差不少
tensorflow的代码参考了github一个比较火的项目https://github.com/jinfagang/tensorflow_poems,在此表示感谢!
结构很简单,方法在generate_text文件夹内,再给出keras诗歌、tensorflow诗歌+小说三个demo。但是keras因为效果不好,我后面封装的时候就没再去测试,可能有bug请海涵。 generate_text文件夹包括:
- 数据:全唐诗,来源https://github.com/todototry/AncientChinesePoemsDB;小说《射雕英雄传》,版权问题就不提供地址;在此表示感谢!
- 预处理:data_poem.py是个脚本,用于合并、清洗每个txt文档;Data_process.py是个方法,用于分词、编码、填充
- 网络:在文件夹rnn中,model_keras.py、model_tensorflow.py分别是keras、tensorflow的2层lstm
- 训练:train_keras.py、train_tensorflow.py,分别用keras、tensorflow训练网络
- 生成:generate_keras.py、generate_tensorflow.py,分别用keras、tensorflow生成诗歌
1.keras貌似不能对标签数据在网络内部做one-hot,所以标签会非常占内存,我用服务器96G内存都吃不消30000首诗5000长度字典的生成。
2.同样的网络,keras训练效果不是特别好、loss在5以上,tensorflow的loss能降到1左右,不知道是不是因为没有对x和y做reshape拼接的原因。
3.固定的网络输出是固定的。
4.断句很难控制在5或者7。
1.keras我加入了分批训练时外部执行one-hot,但会大幅增加训练时间。
1.学艺不精,发现keras原来也有sparse_categorical_crossentropy,解决了内存问题。但是内部好像不支持对y做reshape,所以输出是嵌套结构的,不知道是不是这个原因loss到4.5以后就下降的很慢。
2.在预测的时候不取唯一解,而是取最大概率的n个答案,或者对生成的结果做不同概率的抽样。
1.网上很多代码的做法是:每次输入一个字,输出lstm的hidden用于预测下一个字、state用于保存cell状态。下一个循环输入上一轮预测的字和state作为新一轮lsrm的cell初始状态。
我觉得太麻烦了,直接保留整个序列,[1] > [2] | [1,2] > [2,3] | [1,2,3] > [2,3,4]。因为tensorflow里面有一个output = tf.reshape(outputs, [-1,num_units]),输出的就是这句话后移一个单位预测值。
2.由于随机抽样很容易在标点生成的时候跳过标点,我一开始加入了修正:小于3个字符出现标点重新抽样直到字,多余7个字符不出现标点重新抽样直到标点。这里抽样也必须是最大概率的n个,而不是作弊的方式人为断句,这样的结果还是挺不错的,而且会出现4-7个字,比较有韵味,这段代码在generate_tensorflow_correct.py。
但是后面发现,在抽样的时候不用均匀,而是给每个字附上计算得到的概率,RNN完全可以学到标点的位置,结果更贴近唐诗5、7字,也同样丢失了4、6字的风格。
3.训练的时候batchsize是大于1的,生成的时候batchsize=1,cell_mul.zero_state这里要注意。所以要保存训练的参数,生成的时候模型结构有改变,再导入训练参数。
4.闲来无事想试着生成小说,一开始用的网络小说生成的很差,后来找了射雕英雄传可能因为风格比较统一,有那么点感觉。
train_keras.py、train_tensorflow.py进行训练,generate_keras.py、generate_tensorflow.py即可创作,参考demo_xxx.py
Tensorflow 诗歌 随机抽样+修正
Tensorflow 诗歌 概率抽样
Keras 诗歌 概率抽样(这是之前的,更换损失函数以后效果和Tensorflow差不多)
Tensorflow 小说 概率抽样
有几首不错的诗大家看着乐呵乐呵
神
神龙既已落云泉,犹恐风流四百声。
几株红叶几重关,不得人间不敢归。
仙
仙驾千般出水滨,夜凉寒色向山眠。
万里江边过远梦,一日同吟不见人?
鬼
鬼疟朝来入夜风,不似春窗入禁垣。
云飞树下春山暮,水满江山雪未飞。