https://tianchi.aliyun.com/competition/entrance/231776/introduction
比赛主打疫情相关的呼吸领域的真实数据积累,数据粒度更加细化,判定难度相比多科室文本相似度匹配更高,同时问答数据也更具时效性。本着宁缺毋滥的原则,问题的场地限制在20字以内,形成相对规范的句对。要求选手通过自然语义算法和医学知识识别相似问答和无关的问题。
本次大赛数据包括:脱敏之后的医疗问题数据对和标注数据。医疗问题涉及“肺炎”、“支原体肺炎”、“支气管炎”、“上呼吸道感染”、“肺结核”、“哮喘”、“胸膜炎”、“肺气肿”、“感冒”、“咳血”等10个病种。
数据共包含train.csv、dev.csv、test.csv三个文件,其中给参赛选手的文件包含训练集train.csv和验证集dev.csv,测试集test.csv 对参赛选手不可见。
每一条数据由Id, Category,Query1,Query2,Label构成,分别表示问题编号、类别、问句1、问句2、标签。Label表示问句之间的语义是否相同,若相同,标为1,若不相同,标为0。其中,训练集、验证集Label已知,测试集Label未知。
示例
编号:0
类别:肺炎
问句1:肺部发炎是什么原因引起的?
问句2:肺部发炎是什么引起的
标签:1
编号:1
类别:肺炎
问句1:肺部发炎是什么原因引起的?
问句2:肺部炎症有什么症状
标签:0
提交说明
参赛者提交的模型在运行后针对测试数据需生成result.csv 文件。
格式如下:
id,label
0,1
1,0
2,1
具体格式请见test示例。
选手检验出的结果和标准答案对比。
本次比赛测评指标为准确率,计算公式为:
准确率 = 正确预测数目 / 总问题对数目
RoBERTa-large-pair
大句子对模型
参数量 290M
存储大小 1.20G
语料 CLUECorpus2020
下载地址:https://github.com/CLUEbenchmark/CLUEPretrainedModels
train.csv 原始训练数据
train_dev.csv 原始训练数据+验证数据
train_dev_improve.csv 数据增强数据
增强方法(举例):
增强前:
id | category | query1 | query2 | label |
---|---|---|---|---|
0 | 咳血 | 剧烈运动后咯血,是怎么了? | 剧烈运动后咯血是什么原因? | 1 |
1 | 咳血 | 剧烈运动后咯血,是怎么了? | 剧烈运动后为什么会咯血? | 1 |
2 | 咳血 | 剧烈运动后咯血,是怎么了? | 剧烈运动后咯血,应该怎么处理? | 0 |
3 | 咳血 | 剧烈运动后咯血,是怎么了? | 剧烈运动后咯血,需要就医吗? | 0 |
4 | 咳血 | 剧烈运动后咯血,是怎么了? | 剧烈运动后咯血,是否很严重? | 0 |
增强后:
id | category | query1 | query2 | label |
---|---|---|---|---|
10749 | 咳血 | 剧烈运动后咯血是什么原因? | 剧烈运动后为什么会咯血? | 1 |
10750 | 咳血 | 剧烈运动后咯血是什么原因? | 剧烈运动后咯血,应该怎么处理? | 0 |
10751 | 咳血 | 剧烈运动后咯血是什么原因? | 剧烈运动后咯血,需要就医吗? | 0 |
10752 | 咳血 | 剧烈运动后咯血是什么原因? | 剧烈运动后咯血,是否很严重? | 0 |
10753 | 咳血 | 剧烈运动后为什么会咯血? | 剧烈运动后咯血,应该怎么处理? | 0 |
10754 | 咳血 | 剧烈运动后为什么会咯血? | 剧烈运动后咯血,需要就医吗? | 0 |
10755 | 咳血 | 剧烈运动后为什么会咯血? | 剧烈运动后咯血,是否很严重? | 0 |
model_0 由train.csv 数据训练
model_1 由train_dev.csv+train_dev_improve.csv 数据训练
model_2 由train_dev.csv数据训练
model_0 | model_1 | model_2 | 得分 |
---|---|---|---|
1 | 0 | 0 | 0.9545 |
0 | 1 | 0 | 0.9583 |
0 | 0 | 1 | 0.9585 |
0.2 | 0.4 | 0.4 | 0.9609 |
0.1 | 0.6 | 0.3 | 0.9616 |
0.1 | 0.5 | 0.4 | 0.9625 |
0.1 | 0.4 | 0.5 | 0.961 |
选择最高得分的权重进行预测
tensorflow-gpu==1.14 cuda10.0-py3
python==3.6
keras_bert==0.81.0
pandas
numpy
sklearn
tqdm
运行main.sh即可
github
Rank1:
小模型同时加入CHIP2019数据训练
模型 | 特点 | 权重 | 加入外部句对数据 |
---|---|---|---|
BERT-wwm-ext | 全词Mask | 1 | YES |
Ernie-1.0 | 对词、实体及实体关系建模 | 1 | YES |
RoBERTa-large-pair | 面向相似性或句子对任务优化 | 1 | NO |
Rank2:
数据增强:
预训练模型选择:
ERNIE
在医疗数据中,往往会存在较多的实体概念;此外文本相似度作为问答任务的子任务,数据描述类型也偏向于口语。ERNIE是百度提出的知识增强的语义表示模型,通过对词、实体等语义单元的掩码,使模型学习完整概念的语义表示,其训练语料包括了百科类文章、新闻资讯、论坛对话。因此ERNIE能够更准确表达语句中实体的语义,且符合口语的情景。
Roberta_large
Roberta_large是目前大多数NLP任务的SOTA模型。在Roberta_large中文版本使用了动态掩码、全词掩码,增加了训练数据,并改变了生成的方式和语言模型的任务。因此,在医疗文本上,Roberta_large能更好地对文本进行编码。
Roberta_large_pair
Roberta_large_pair是针对文本对任务提出的专门模型,能够较好地处理语义相似度或句子对问题。因此,在医疗文本相似度任务上,往往能够取得更好的结果。
模型训练
Multi-sample-dropout
在训练过程中,由于Bert后接了dropout层。为了加快模型的训练,我们使用multi-sample-dropout技术。通过对Bert后的dropout层进行多次sample,并对其多次输出的loss进行平均,增加了dropout层的稳定性,同时使得Bert后面的全连接层相较于前面的Bert_base部分能够得到更多的训练。
数据交叉
通过数据交叉,即训练时使用不同的数据进行组合,能够在数据层面增加模型簇的多样性。这次比赛中,我们秉承的insight是:将难的数据集(外部数据)给更强大的模型,使小的模型能够精准预测,大的模型更具鲁棒性。 此外,也可以通过KL散度计算不同组合的模型的差异,并计算模型两两间的差异和,计算模型簇整体的多样性;以这样的形式,选取数据组合。
模型 | 原始数据 | 增强数据(外部数据) | 增强数据(传递性) | 增强数据(新类别) |
---|---|---|---|---|
ERNIE | yes | no | yes | yes |
Roberta_large_pair | yes | yes | yes | yes |
Roberta_large | yes | yes | yes | no |
在医疗文本相似度任务中,交换两个文本的数据不会改变该文本对的标签。但是对于Bert来说,交换文本对的位置,会改变位置编码,能使模型从不同的角度取观察这两个文本的相似性。在测试数据增强时,通过计算原始文本对与交换文本对的输出概率的平均值,能够使模型更好地在测试数据上的进行预测。
Rank3:
通过相似性传递增强数据
采用对抗训练
query 1 | query 2 | label(true) | label(fgm) | label(none) |
---|---|---|---|---|
腰和后背疼是胸膜炎吗? | 腰和后背疼是胸膜炎的症状吗? | 0 | 0 | 1 |
右下肺部感染是肺炎吗? | 又下肺部感染是肺炎不是 | 1 | 1 | 0 |
23价肺炎有必要打吗 | 23价肺炎有什么作用 | 0 | 0 | 1 |
Rank4_1:
RoBERTa-large,将最后一层的进行平均池化操作并与[cls]进行拼接。在训练时采用对抗训练(PGD)增强语义信息。
def forward(self, input_ids, input_masks, segment_ids):`
sequence_output, pooler_output, hidden_states = self.bert_model(input_ids=input_ids, token_type_ids=segment_ids,attention_mask=input_masks)`
seq_avg = torch.mean(sequence_output, dim=1)`
concat_out = torch.cat((seq_avg, pooler_output), dim=1)`
logit = self.classifier(concat_out)`
return logit
Rank4_2
1.OOV病种数据增强
在本次比赛中,我们需要模型学习哪些信息?我们如何让模型获得OOV病种的这些信息? 在本解决方案中,认为模型需要学习以下四种信息:
基本语义
病名
药名
病理
参照比赛难点中的第1点,我们可以通过某些方法来制作OOV病种样本的数据进行数据增强,参照第3点,我们需要小心翼翼的增强,以避免改变原数据中的重要分布,使得模型性能大幅度下跌
在本解决方案中,使用了外部先验医药知识,尽量避开病理来对已有标注数据进行病名的替换,整个替换的流程如下
2.训练时-测试时交换增强
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WbDK5H7S-1590141558242)(README.assets/1585814961283_E6mQker9SX.jpg)]
3.模型融合与伪标签
本解决方案同样使用了一些数据比赛的常用方法:模型融合和伪标签
Rank6_1
数据增强 根据数据传递性数据增强
预训练模型尝试
模型优化
Rank6_2
有效的trick
1.预训练模型的选择上,Roberta_wwm_large、UER线下实验效果最好
-> https://github.com/ymcui/Chinese-BERT-wwm、https://github.com/dbiir/UER-py
2.通过相似传递进行数据增强(正负采样:A-B相似、A-C相似 -> B-C相似)¶
3.对抗训练,提升模型鲁棒性
-> https://zhuanlan.zhihu.com/p/91269728
4.Label-Smoothing 标签平滑(微小提升)
5.加权融合(自定义search函数寻找最优的融合权重)
6.自蒸馏(没有明显提升)
7.实体替换增强(没有明显提升)