搜狐文本匹配:基于条件LayerNorm的多任务baseline
By 苏剑林 | 2021-04-16 | 83043位读者 |前段时间看到了“2021搜狐校园文本匹配算法大赛”,觉得赛题颇有意思,便尝试了一下,不过由于比赛本身只是面向在校学生,所以笔者是不能作为正式参赛人员参赛的,因此把自己的做法开源出来,作为比赛baseline供大家参考。
赛题介绍 #
顾名思义,比赛的任务是文本匹配,即判断两个文本是否相似,本来是比较常规的任务,但有意思的是它分了多个子任务。具体来说,它分A、B两大类,A类匹配标准宽松一些,B类匹配标准严格一些,然后每个大类下又分为“短短匹配”、“短长匹配”、“长长匹配”3个小类,因此,虽然任务类型相同,但严格来看它是六个不同的子任务。
# A类样本示例
{
"source": "英国伦敦,20/21赛季英超第20轮,托特纳姆热刺VS利物浦。热刺本赛季18轮联赛是9胜6平3负,目前积33分排名联赛第5位。利物浦本赛季19轮联赛是9胜7平3负,目前积34分排名联赛第4位。从目前的走势来看,本场比赛从热刺的角度来讲,是非常被动的。最终,本场比赛的比分为托特纳姆热刺1-3利",
"target": " 北京时间1月29日凌晨4时,英超联赛第20轮迎来一场强强对话,热刺坐镇主场迎战利物浦。 热刺vs利物浦,比赛看点如下: 第一:热刺能否成功复仇?双方首回合,热刺客场1-2被利物浦绝杀,赛后穆里尼奥称最好的球队输了,本轮热刺主场迎战利物浦,借着红军5轮不胜的低迷状态,能否成功复仇? 第二:利物浦近",
"labelA": "1"
}
# B类样本示例
{
"source": "英国伦敦,20/21赛季英超第20轮,托特纳姆热刺VS利物浦。热刺本赛季18轮联赛是9胜6平3负,目前积33分排名联赛第5位。利物浦本赛季19轮联赛是9胜7平3负,目前积34分排名联赛第4位。从目前的走势来看,本场比赛从热刺的角度来讲,是非常被动的。最终,本场比赛的比分为托特纳姆热刺1-3利",
"target": " 北京时间1月29日凌晨4时,英超联赛第20轮迎来一场强强对话,热刺坐镇主场迎战利物浦。 热刺vs利物浦,比赛看点如下: 第一:热刺能否成功复仇?双方首回合,热刺客场1-2被利物浦绝杀,赛后穆里尼奥称最好的球队输了,本轮热刺主场迎战利物浦,借着红军5轮不胜的低迷状态,能否成功复仇? 第二:利物浦近",
"labelB": "0"
}
一般来说,完成这个任务至少需要两个模型,毕竟A、B两种类型的分类标准是不一样的,如果要做得更精细的话,应该还要做成6个模型。但问题是,如果独立地训练6个模型,那么往往比较费力,而且不同任务之间不能相互借鉴来提升效果,所以很自然地我们应该能想到共享一部分参数变成一个多任务学习问题。
模型简介 #
当然,如果看成是常规的多任务学习问题,那又太一般化了。针对这几个任务“形式一样、标准不一样”的特点,笔者构思了通过条件LayerNorm(Conditional Layer Normalization)来实现用一个模型做这6个子任务。
关于条件LayerNorm,我们之前在文章《基于Conditional Layer Normalization的条件文本生成》也介绍过,虽然当时的例子是文本生成,但是它可用的场景并不局限于此。简单来说,条件LayerNorm就是一种往Transformer里边加入条件向量来控制输出结果的一种方案,它把条件加入到LayerNorm层的$\beta,\gamma$中。
对于这个比赛的6个任务而言,我们只需要将任务类型作为条件传入到模型中,就可以用同一个模型处理不同6个不同的任务了,示意图如下:
这样一来,整个模型都是共用的,只是在输入句子的时候同时将任务类型的id作为输入,实现了参数的最大共用化。
代码参考 #
关于条件LayerNorm的实现,早已内嵌在bert4keras中,所以想到这个设计后,用bert4keras来实现就是水到渠成了,参考代码如下:
代码使用了RoFormer为基准模型,这主要考虑到在“长长匹配”中,两个文本拼接起来的总长度还是很长的,用以词为单位的RoFormer可以缩短序列长度,同样的算力下可以处理更长的文本,而且RoFormer所使用的RoPE位置编码理论上可以处理任意长的文本。代码测了几次,线下的F1为0.74左右,线上测试集提交后的F1为0.73上下。在3090上测试,单个epoch好像是1个小时左右,跑4、5个epoch就差不多了。
现在的代码是所有数据混合在一起然后随机训练的,这样做有个小缺点,就是原来的序列长度比较短的样本也填充到最大长度进行训练了,导致了短序列样本训练速度变慢(当然肯定比你独立训练6个模型要快),可以做的优化是在分batch的时候尽量让同一个batch的样本长度相近,不过我懒得写了,留给大家优化吧~
文章小结 #
本文分享了一个搜狐文本匹配的baseline,主要是通过条件LayerNorm来增加模型的多样性,以实现同一模型处理不同类型的数据、形成不同输出的目的。
转载到请包括本文地址:https://spaces.ac.cn/archives/8337
更详细的转载事宜请参考:《科学空间FAQ》
如果您还有什么疑惑或建议,欢迎在下方评论区继续讨论。
如果您觉得本文还不错,欢迎分享/打赏本文。打赏并非要从中获得收益,而是希望知道科学空间获得了多少读者的真心关注。当然,如果你无视它,也不会影响你的阅读。再次表示欢迎和感谢!
如果您需要引用本文,请参考:
苏剑林. (Apr. 16, 2021). 《搜狐文本匹配:基于条件LayerNorm的多任务baseline 》[Blog post]. Retrieved from https://spaces.ac.cn/archives/8337
@online{kexuefm-8337,
title={搜狐文本匹配:基于条件LayerNorm的多任务baseline},
author={苏剑林},
year={2021},
month={Apr},
url={\url{https://spaces.ac.cn/archives/8337}},
}
April 17th, 2021
非常感谢苏神,在你这里找到了思路
April 18th, 2021
苏神,针对这种二分类问题,最后输出维度为2使用多分类交叉熵,和使用1分类BCE交叉熵,哪种效果好呢,1分类最后可以调阈值,最后的F1会更高点吧
2节点的softmax照样可以调阈值,因为$p_0+p_1=1$,所以你可以将$p_1$作为标准,那么就跟sigmoid场景一样了。
April 18th, 2021
苏神你好,请问代码129行为什么使用全局平均池化而不是用cls的768维信息呢?感觉一般来说不都是使用cls的768?而且您之前的代码也都是直接使用的cls,请问这里池化有什么更多的意义吗?
用多了cls,换个口味试试而已。
感谢苏神回复。
另外还有一个事打扰一下苏神,代码里F1的计算方法是不是有问题(就是,虽然能体现模型性能,但是并不是标准F1的计算方法)
有什么问题?
不好意思苏神,仔细推到了一下,是对的
April 19th, 2021
苏神,那个 20个4分类的是不是可以基于这个去做 有条件 预测,一个模型搞定所有分类
预测时不用 输入 条件吗,比如,当前要预测是 短短 还是 长短
看到了,有
需要。
可以这样做,但是这样预测性能会降低,因为相当于每个样本要跑20次预测了。
April 19th, 2021
苏神,你的条件数据生成是每个样本生成六类吗?因为没看到有判断条件。
请问什么叫做“条件数据生成是每个样本生成六类”呢?
六类就是你说的6个子任务。我是想知道每个样本的任务类型id是怎么对应的,因为原始的数据集是只有0和1这个label,没有任务类型id。
原始训练集和测试集不都分了6个文件吗?每个文件本身不就是标签吗?非得明明白白在样本上写着1、2、3才能用?
现在才看到原始数据集,原来是已经分好了,不好意思,(*/㉨\*)捂脸
我...
April 24th, 2021
苏神你好,我使用你的模型测试,用的tensorflow2.1.0运行代码,一直不收敛,而且f1score一直为0,你用的是tensorflow1.14.0版本,请问会是tensorflow版本不同的原因导致的吗
可能是。去掉 optimizer.apply_ema_weights() 和 optimizer.reset_old_weights() 这两句试试
May 2nd, 2021
苏神你好,请问这个任务使用MSELoss,CrossEntropyLoss或者BCEwithLogitLoss不同的损失函数有区别吗?
这个我也不清楚呀,没逐一试验过,也没用过pytorch
May 5th, 2021
我将任务类型词嵌入编码后粗暴地与wobert的cls向量拼接在一起,然后送入全连接层分类器,线下也有0.74的f1,是不是基于条件的分类任务都可以这样玩?
这倒是个有意思的发现,应该说是适合这些高度雷同的多任务吧。
May 6th, 2021
来个小tip!如果想使用24层的large版预训练模型,训练一开始会比较不稳定模型很难收敛,这边改成只在最后12层(这个值可以自己选哈)使用Conditional Layer Normalization,模型就收敛的很快啦!!!
仅供大家参考哈,也有可能我使用的方法有问题。
可能还需要降低学习率~
May 13th, 2021
想问下苏神,这个问题为什么不用“小布语音助手”一样的思路,预测[CLS]的值来进行语义匹配,而是进行了global average pooling,您是怎么考虑的?
理论上来说,RoFormer+CLN+预测[CLS]的方式训练是否是可行的,和您这种方法相比哪个更好呢,为什么?
理论上MLM+CLN+预测[CLS]是否可行?除了有些慢还有什么缺点吗?
都行啊,你随意,Global Average Pooling和取CLS都差不多的,没有什么明显区别。我只是多尝试一下而已~
好的!