如果读者已经读过《基于DGCNN和概率图的轻量级信息抽取模型》一文,了解到不用Bert时的模型架构,那么就会理解到上述实现是多么的简介明了。
可以看到,我们引入了Bert作为编码器,然后得到了编码序列$t$,然后直接接两个Dense(1),这就完成了subject的标注模型;接着,我们把传入的s的首尾对应的编码向量拿出来,直接加到编码向量序列$t$中去,然后再接两个Dense(num_classes),就完成object的标注模型(同时标注出了关系)。
这样简单的设计,最终F1能到多少?答案是:线下dev能接近82%,线上我提交过一次,结果是85%+(都是单模型)!相比之下,《基于DGCNN和概率图的轻量级信息抽取模型》中的模型,需要接CNN,需要搞全局特征,需要将s传入到LSTM进行编码,还需要相对位置向量,各种拍脑袋的模块融合在一起,单模型也只比它好一点点(大约82.5%)。要知道,这个基于Bert的简单模型我只写了一个小时就写出来了,而各种技巧和模型融合在一起的DGCNN模型,我前前后后调试了差不多两个月!Bert的强悍之处可见一斑。
(注:这个模型的fine tune最好有8G以上的显存。另外,因为我在比赛即将结束的前几天才接触的Bert,才把这个基于Bert的模型写出来,没有花心思好好调试,所以最终的提交结果并没有包含Bert。)
用Bert做关系抽取的这个例子,跟前面情感分析的简单例子,有一个明显的差别是学习率的变化。
情感分析的例子中,只是用了恒定的学习率($10^{-5}$)训练了几个epoch,效果就还不错了。在关系抽取这个例子中,第一个epoch的学习率慢慢从$0$增加到$5\\times 10^{-5}$(这样称为warmup),第二个epoch再从$5\\times 10^{-5}$降到$10^{-5}$,总的来说就是先增后减,Bert本身也是用类似的学习率曲线来训练的,这样的训练方式比较稳定,不容易崩溃,而且效果也比较好。
事件主体抽取 #最后一个例子来自CCKS 2019 面向金融领域的事件主体抽取,这个比赛目前还在进行,不过我也已经没有什么动力和兴趣做下去了,所以放出我现在的模型(准确率为89%+)供大家参考,祝继续参赛的选手取得更好的成绩。
简单介绍一下这个比赛的数据,大概是这样的
输入:“公司A产品出现添加剂,其下属子公司B和公司C遭到了调查”, “产品出现问题”
输出: “公司A”
也就是说,这是个双输入、单输出的模型,输入是一个query和一个事件类型,输出一个实体(有且只有一个,并且是query的一个片段)。其实这个任务可以看成是SQUAD 1.0的简化版,根据这个输出特性,输出应该用指针结构比较好(两个softmax分别预测首尾)。剩下的问题是:双输入怎么搞?
前面两个例子虽然复杂度不同,但它们都是单一输入的,双输入怎么办呢?当然,这里的实体类型只有有限个,直接Embedding也行,只不过我使用一种更能体现Bert的简单粗暴和强悍的方案:直接用连接符将两个输入连接成一个句子,然后就变成单输入了!比如上述示例样本处理成:
输入:“___产品出现问题___公司A产品出现添加剂,其下属子公司B和公司C遭到了调查”
输出: “公司A”
然后就变成了普通的单输入抽取问题了。说到这个,这个模型的代码也就没有什么好说的了,就简单几行(完整代码请看这里):
x = bert_model([x1, x2])ps1 = Dense(1, use_bias=False)(x)ps1 = Lambda(lambda x: x[0][..., 0] - (1 - x[1][..., 0]) * 1e10)([ps1, x_mask])ps2 = Dense(1, use_bias=False)(x)ps2 = Lambda(lambda x: x[0][..., 0] - (1 - x[1][..., 0]) * 1e10)([ps2, x_mask])model = Model([x1_in, x2_in], [ps1, ps2])
另外加上一些解码的trick,还有模型融合,提交上去,就可以做到89%+了。在看看目前排行榜,发现最好的结果也就是90%多一点点,所以估计大家都差不多是这样做的了...(这个代码重复实验时波动比较大,大家可以多跑几次,取最优结果。)
这个例子主要告诉我们,用Bert实现自己的任务时,最好能整理成单输入的模式,这样一来比较简单,二来也更加高效。
比如做句子相似度模型,输入两个句子,输出一个相似度,有两个可以想到的做法,第一种是两个句子分别过同一个Bert,然后取出各自的[CLS]特征来做分类;第二种就是像上面一样,用个记号把两个句子连接在一起,变成一个句子,然后过一个Bert,然后将输出特征做分类,后者显然会更快一些,而且能够做到特征之间更全面的交互。
文章小结 #本文介绍了Keras下Bert的基本调用方法,其中主要是提供三个参考例子,供大家逐步熟悉Bert的fine tune步骤和原理。其中有不少是笔者自己闭门造车的经验之谈,如果有所偏颇,还望读者指正。
事实上有了CyberZHG大佬实现的keras-bert,在Keras下使用Bert也就是小菜一碟,大家折腾个半天,也就上手了。最后祝大家用得痛快~
转载到请包括本文地址:https://spaces.ac.cn/archives/6736
更详细的转载事宜请参考:《科学空间FAQ》
如果您还有什么疑惑或建议,欢迎在下方评论区继续讨论。
如果您觉得本文还不错,欢迎分享/打赏本文。打赏并非要从中获得收益,而是希望知道科学空间获得了多少读者的真心关注。当然,如果你无视它,也不会影响你的阅读。再次表示欢迎和感谢!
本文链接: http://berthas.immuno-online.com/view-719855.html