抱歉,你查看的文章已删除

CCF BDCI新闻情感分类初赛A榜4/2735,复赛1%题解报告

写在前面

本文将带来CCF BDCI新闻情感分类的题解报告,该方案在初赛A榜获得了4/2735,复赛成绩1%。希望可以给大家提供一些思路,互相交流学习。

比赛代码已经开源在https://github.com/linhaow/TextClassify

赛题说明

比赛的链接在这里:

https://www.datafountain.cn/competitions/350

比赛的内容是互联网的新闻情感分析。给定新闻标题和新闻的内容,然后需要我们设计一个方案对新闻的情感进行分类,判断新闻是消极的,积极的还是中立的。

训练数据集的字段如下:

id:新闻的唯一标识。

title:新闻的题目。

content:新闻的内容。

label:情感分类的标签。

数据分析

一个好的数据分析可以给比赛带来很大的提升。所以数据分析的过程不能忽视。对训练数据集分析后,可以发现训练集有如下一些特征。

(1)训练数据集中0标签的数据量比较少,只有几百。

(2)训练集中1和2的标签比较平衡,都是几千,相差不大。

(3)此外新闻的文章内容很长,很多有上千个字。

(4)相比于新闻内容,新闻标题较短,很少有上百字的标题。

针对上述特征,可以看出标签中存在一定的数据不均衡,此外如何处理过长的文章内容也是一个核心任务。对于常用的bert模型,只能接收512个token,所以需要一个能处理过千字的文章内容的方法。

baseline

我刚参加比赛的时候初赛已经过去了一段时间了,当时有一个郭大开源的baseline,我的baseline是基于这个开源baseline修改的。baseline的结构图如下:

整个模型由两个部分组成。

(1)第一部分是最下方的split_num个bert模型(这里可以使用bert全家桶中的任意一个),现在基本文本分类比赛的前排都是bert模型。毕竟bert模型在预训练的时候就加入了很多比赛外的数据。所以相对来说效果也不会太差。

为了同时利用标题和文章内容信息,在bert模型的输入端。我选用了两个sentence加[SEP]做为模型的输入,其中sentence1是该新闻的标题,而sentence2则是该新闻的内容的一部分。为了让新闻内容可以覆盖到整篇文章,我首先将文章分成split_num段,然后在每一段选择maxlen的长度,分别做为split_num个bert模型的sentence2的输入。

举个例子,如果下面的长方形代表的是一个文章的内容,而split_num是3,则三颗五角星的地方是三个bert的sentence2的输入。sentence1均是文章标题。

(2)第二部分是上方的biGRU模块。该模块将bert对文章理解的不同部分串起来,最后给出综合考虑的分类输出。在这种RNN结构中,双向的效果往往比单向更好,所以使用了双向的GRU。

上述结构有如下的优点:

(1)减少了显存的使用,经过split后你可以在同样显存下处理更长的长度。

(2)另一个就是解决了长度上千的句子塞进bert的问题。上文bert模型处我使用的是中文的roberta-large模型。

提升模型

使用完上述baseline,并且调参后成绩就可以达到100名左右了。接下来就是如何提升模型的效果了。

(1)首先我发现郭大最初的代码好像有bug,当gru的层数大于1的时候维度不对。于是我查看源代码后把它fix了,然后在gru中加了几层layers,调整参数后,名次就到了前50了,大概线上是81.6左右。

具体的代码在pytorch_transformers文件夹中的modeling_bert.py第976行,修改后的代码如下:

self.gru.append(nn.GRU(config.hidden_sizeif i==0else config.lstm_hidden_size*2, config.lstm_hidden_size,num_layers=1,bidirectional=True,batch_first=True).cuda() )

这里增加layers的层数是为了让BiGRU更好地学习一篇长文章的不同部分。一层layer明显是欠拟合的,实际上实验结果也证明这里layers增大后成绩上去了不少。

(2)我尝试去清洗数据,除去一些url,img之类的数据,发现成绩不但没有提升,还有下降(其实这一点早就有心理准备了)。

因为在bert的使用中去除停用词等经常不能带来性能的提升。毕竟bert在预训练时使用的就是完成的带有噪声的文本信息,所以去停用词,清洗数据等不一定能带来效果的提升。

(3)我尝试了不同的split_num和maxlen,发现在roberta模型中,split_num越大的时候效果越好(我在7,8左右时效果最好),这是因为更大的split_num可以让模型更好地获取长句子的信息,更多的split_num可以让模型捕捉的密度更高,从而对长篇章的把握更加准群。给一个极端的例子,如果你的split_num比较小,maxlen也比较小,刚好把文章先抑后扬的抑的部分全捕捉了,那准确性肯定会下降。与此同时也需要增加weigt_decay去防止过拟合。通过这个方法线上就可以到81.7了

(4)使用多折交叉验证,多折交叉验证的效果会明显好于单折。多折交叉和融合往往都能带来一定的稳定性和性能的提升。不过多折也会增加训练的时长,所以往往在先调参确定好模型后再进行多折交叉。通过这个方法,线上就可以到达81.8了,当时已经在a榜前15了。

(5)使用roberta-wwm-ext模型,roberta-wwm-ext是一个基于全词遮罩(Whole Word Masking)技术的预训练模型。 简单来说,原有基于WordPiece的分词方式会把一个完整的词切分成若干个子词,在生成训练样本时,这些被分开的子词会随机被mask。在全词Mask中,如果一个完整的词的部分WordPiece子词被mask,则同属该词的其他部分也会被mask,即全词Mask。这个模型在复赛的a榜上效果比较好。这个应该是初赛和复赛训练数据集分布情况不同导致的。不过多样化的模型对于模型融合是很有帮助的。repo的链接如下:

https://github.com/ymcui/Chinese-BERT-wwm

(6)All data训练,在之前的训练中会使用一部分作为验证集,但是当你确定了所有超参数后你就可以尝试把所以数据拿过来盲跑,这样训练数据会多一点,不过缺点是拿不到本地的开发集测试结果。

模型融合

在得到两个模型的多个不同split_num,maxlen值后,就可以对模型的结果进行融合了,在融合中我使用的是分类问题中常用投票法

总的来说就是用不同的模型输出结果进行投票,哪个结果的票多就选择哪个结果,如果票数一样,有0 label就选0,没有的话就选单模最好的模型。这里选0是因为之前的0样本在训练的时候比较少。

对于候选融合结果的选择我们采用的方法如下:

首先我们计算不同输出文件之间的相关性,然后选择相关性最小的几个输出结果,在相关性和得分上需要对不同的输出结果进行一个trade off。即最好的情况就是几个得分较高的模型相关性比较低。相关系数可以使用pandas中的corr()计算。

接着对选出的几个模型进行融合即可得到最后的输出,投票融合结果的代码框架如下:

import pandas as pd
import numpy as np
submits =['0.818.csv','0.816.csv']
#需要融合的文件放submits中
files = []
data = []
for f in submits:
    if 'csv' in f:
        files.append(f)
        data.append(pd.read_csv(f).values)
print(len(files))

weight = [2,1]
#融合的权重
result = np.zeros([len(data[0]), 3])

for i in range(len(data)):
    for j in range(len(data[0])):
        if data[i][j][1] == 0:
            result[j][0] += weight[i]
        elif data[i][j][1] == 1:
            result[j][1] += weight[i]
        elif data[i][j][1] == 2:
            result[j][2] += weight[i]

np.argmax(result, axis = 1)
submit = pd.read_csv('submit_example.csv')
submit['label'] = np.argmax(result, axis = 1)
submit.to_csv('result.csv',index=None)

总结

其实比赛中还有很多方法可以尝试,不过中间有点事耽误了很多时间所以就尝试了两个模型,有点可惜,文章中有很多地方都还是可以调整的,比如融合方法等,大家有空可以继续探究。


本文转载在公众号:纸鱼AI,作者:linhw

本文分享自微信公众号 - AINLP(nlpjob)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

编辑于

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励