博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
keras基于CNN和序列标注的对联机器人
阅读量:6223 次
发布时间:2019-06-21

本文共 1896 字,大约阅读时间需要 6 分钟。

动手 #

“对对联”,我们可以看成是一个句子生成任务,可以用seq2seq完成
分析 #
然而,我们再细想一下就会发现,相对于一般的句子生成任务,“对对联”有规律得多:1、上联和下联的字数一样;2、上联和下联的每一个字几乎都有对应关系。如此一来,其实对对联可以直接看成一个序列标注任务,跟分词、命名实体识别等一样的做法即可。这便是本文的出发点。

说到这,其实本文就没有什么技术含量了,序列标注已经是再普通不过的任务了,远比一般的seq2seq来得简单。所谓序列标注,就是指输入一个向量序列,然后输出另外一个通常长度的向量序列,最后对这个序列的“每一帧”进行分类。相关概念来可以在《简明条件随机场CRF介绍(附带纯Keras实现)》一文进一步了解。

模型 #

本文直接边写代码边介绍模型。如果需要进一步了解背后的基础知识的读者,还可以参考《【中文分词系列】 4. 基于双向LSTM的seq2seq字标注》、《【中文分词系列】 6. 基于全卷积网络的中文分词》、《基于CNN和VAE的作诗机器人:随机成诗》。

我们所用的模型代码如下:

x_in = Input(shape=(None,))x = x_inx = Embedding(len(chars)+1, char_size)(x)x = Dropout(0.25)(x)x = gated_resnet(x)x = gated_resnet(x)x = gated_resnet(x)x = gated_resnet(x)x = gated_resnet(x)x = gated_resnet(x)x = Dense(len(chars)+1, activation='softmax')(x)model = Model(x_in, x)model.compile(loss='sparse_categorical_crossentropy',              optimizer='adam')

其中gated_resnet是笔者定义的门卷积模块(在《基于CNN的阅读理解式问答模型:DGCNN》一文也介绍过这个模块):

def gated_resnet(x, ksize=3):    # 门卷积 + 残差    x_dim = K.int_shape(x)[-1]    xo = Conv1D(x_dim*2, ksize, padding='same')(x)    return Lambda(lambda x: x[0] * K.sigmoid(x[1][..., :x_dim]) \                            + x[1][..., x_dim:] * K.sigmoid(-x[1][..., :x_dim]))([x, xo])

仅此而已~

就这样完了,剩下的都是数据预处理的事情了。当然,读者也可以尝试也可以把gated_resnet换成普通的双向LSTM,但我实验中发现双向LSTM并没有gated_resnet效果好,而且LSTM相对来说也更慢,所以LSTM在这里就被抛弃了。

效果 #

训练的数据集来自:。

完整代码:

训练过程:

对联机器人训练过程
对联机器人训练过程

部分效果:

上联:晚风摇树树还挺,下联:夜雨敲花花更香

上联:今天天气不错,下联:昨日人情无明

上联:鱼跃此时海,下联:鸟鸣何日人

上联:只有香如故,下联:不无月若新

上联:科学空间,下联:文明大中

看起来还是有点味道的。注意“晚风摇树树还挺”是训练集的上联,标准下联是“晨露润花花更红”,而模型给出来的是“夜雨敲花花更香”,说明模型并不是单纯地记住训练集的,还是有一定的理解能力;甚至我觉得模型对出来的下联更生动一些。

总的来说,基本的字的对应似乎都能做到,就缺乏一个整体感。总体效果没有下面两个好,但作为一个小玩具,应该能让人满意了。

微软对联:

结语 #

改动后的python3 代码如下:

欢迎star~~
cpu版TensorFlow 跑了2.5小时。结果还不错。

最后,也没有什么好总结的。我就是觉得这个对对联应该算是一个序列标注任务,所以就想着用一个序列标注的模型来试试看,结果感觉还行~当然,要做得更好,需要在模型上做些调整,还可以考虑引入Attention等,然后解码的时候,还需要引入更多的先验知识,保证结果符合我们对对联的要求。这些就留给有兴趣做下去的读者继续了。

本文转载自 : 地址:

转载于:https://blog.51cto.com/13000661/2362352

你可能感兴趣的文章
客户传真第四部分 个人理财风险防范8.当心银行汇款引发的诈骗
查看>>
php 事件驱动 消息机制 共享内存
查看>>
分享一个IIS日志分析工具-LogParse
查看>>
Silverlight中使用Grid创建自定义的Table表格
查看>>
Console-算法[for,if]-不用第三个变量,交换两字符串的值
查看>>
Hadoop入门(一):Hadoop伪分布安装
查看>>
Tomcat环境配置
查看>>
屌丝程序员的那些事(一)-毕业那年
查看>>
CWidgetMgr---H
查看>>
spring测试实例
查看>>
创建Sdcard
查看>>
两个数组a[N],b[N],其中A[N]的各个元素值已知,现给b[i]赋值,b[i] = a[0]*a[1]*a[2]…*a[N-1]/a[i];...
查看>>
cocos2d-x与ISO内存管理(转)
查看>>
磁盘I/O的性能评估方法
查看>>
计算机排序算法
查看>>
普通IT和文艺IT工程师的区别
查看>>
sql之left join、right join、inner join的区别
查看>>
分贝显示器,实时显示声音强度(附源码)
查看>>
Struts2 高危漏洞修复方案 (S2-016/S2-017)
查看>>
新手必看:如何快速看懂VC++项目
查看>>