NLP小白的Kaggle一轮游总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdufsTFknight/article/details/86688220

博主大三,一月中旬期末考试结束之后都放在这个比赛上面了--Quora Insincere Questions Classification

大半个月过来,做了很多尝试,线下成绩提高了不少,线上LB的成绩还是原地踏步 :)。

现在来总结一下自己做过的一些工作,给大家以及自己一些参考反思。如果各路大佬有更好的idea,欢迎骚扰交流~

该竞赛是个典型的文本二分类问题,用的是美国的知乎(quora),来评判这个帖子是不是水帖。竞赛中最关键的要求有三点:

1、只能使用 Kaggle Kernel 中生成的 submission.csv 来提交;

2、不能使用外部数据,也就是说 embedding 也只能用 Kernel 里提供的四个 embedding 文件;

3、Kernel 的 GPU 运行时间不能超过 120 分钟。

4、不能连接网络

目前我的LB得分是0.700,借鉴的是jetou大佬提供的pytorch 版本的代码。具体的模型结构图如下:

这个版本的kernel 得分已经很高了(铜牌区),再次感谢open source 。我也在这个代码的基础上做了一些改进:

一、输入特征方面:

在文本特征上面,我从数据集中抽取了以下几种:

把以上八维的特征来做为新的text_feature 加入到原来的两维 ['caps_vs_length', 'words_vs_unique'] 里面去。public score:696

这里贴出觉得很赞的文本特征抽取代码:https://www.kaggle.com/kaggleczs/lgb-with-features-engineering

二、特征作为ensemble方面:

在经历了上面的失败之后,我觉得特征直接加入到模型的全连接层不一定能学习得到。

于是我们在模型训练后的ensemble 上做了这个尝试(用模型生成的结果和文本特征做stacking,然后用lightgbm学习)

private score : 0.687  public score : 0.693

感觉这样做的后果就是对训练集的数据过拟合了,也可能是本人太菜了,姿势不对。。

三、词向量的拼接方面:

本次比赛我们也对每种词向量来做了一次比较: fasttext , glove , paragram,其中我们也发现:

glove embedding * 2fold + mean three embedding_matrix

也可以达到 private: 0.680 public:0.700 的成绩,

可以比原来的平均三个词向量的方法省下差不多两百秒的时间。(6820s -- 6986 s)

这里扯一个题外话,前段时间看Jeremy Howard 大神的论文,学习到了一种关于迁移学习应用的语言模型论文。简单来说就是:

Jeremy Howard 提出了一种方法,叫做“用于文本分类的通用语言模型微调ULMFiT。有人(例如早期研究者,或者大机构)在海量数据集(例如Wikipedia)上训练语言模型。之后发布这个模型,而不只是词嵌入向量的表达结果;普通用户拿到这个模型后,把它在自己的训练文本(例如 Yelp 或者 IMDB 评论)上微调,这样一来,就有了符合自己任务问题领域上下文的语言模型;
之后,把这个语言模型的头部,加上一个分类器,在训练数据上学习,这就有了一个针对当前任务的完整分类模型;如果效果还不够好,可以把整个分类模型再进行微调。

然后,这个语言模型需要网络去下载模型,在这个比赛中用不了。在kernel 里面也看到一个重新训练一个ulmfit模型的,看起来效果不太好。这里也贴出来:https://www.kaggle.com/manuelsh/ulmfit-from-fast-ai-pub

除此之外,我也考虑到了不同embedding matrix 之间的鲁棒性问题,我尝试着在每一折中加入不同的embedding matrix。这样做在线下带来了比较好的效果,但是线上结果不太好。private score: 0.689   public score 0.697

四、模型参数调整方面:

在上面那个模型中,训练到4-5轮会出现loss的震动。(图没有做,是观察训练过程得出),我们觉得模型的泛化能力不强并且出现了过拟合情况,说明我们对模型需要进行很大的改进,接下来进行漫长的调参之旅。。

 

从模型入手,由于某一个特定问题对某一个模型的改进千变万化,没有办法全部去尝试,因此我们实验了一些 general 的方法,比如批正则化(batch normalization),dropout,  学习率的调整等。

dropout:在每次训练的时候,让某些的特征检测器停过工作,即让神经元以一定的概率不被激活,这样可以防止过拟合,提高泛化能力 

batch normalization:对神经网络的每一层的输入数据都进行正则化处理,这样有利于让数据的分布更加均匀,能够提升模型的拟合能力。

这次比赛中BN的效果可见一斑,导致了三个千分点的提升(相比原模型),这也说明 batch normalization 技术可以加强模型训练的稳定性,并且能够很大程度地提升模型泛化能力。

学习率:在训练神经网络的时候大伙都有特定的pineline,首先使用较大的学习率进行训练,如果目标函数值下降速度和验证集准确率上升速度出现减缓时,减小学习率。在这次比赛里面,也有大佬是使用了一种叫做 Cyclical Learning Rate 的技术来加速训练收敛速度。相关的学习率我也有在线下调整过,包括在第3、4、5轮的尝试,学习率减低的大小等等。

词向量的finetune:在训练神经网络的时候,我在loss震动的那几折对放入神经网络的embedding_matrix 进行unfreeze,让预训练词向量更加适应本次任务的数据。但是在finetune的结果看来,验证集的loss并没有按预期降低,而是还是在震动。

private 0.683  public 0.700 还是没有提高。。

五、梯度分布上看待样本不均衡问题:

今年的AAAI 2019论文 Gradient Harmonized Single-stage Detector 提出了一个新的视角——梯度分布上看待样本数量和难易不均衡。传送门

(图片源自论文)

其主要是为了限制离群点和平衡容易区分开的样本之间的类别,我也在kernel 里面尝试了使用 GHM-C Loss,结果是和用focal loss差不多的,成绩上没有提升。不过有个比较奇怪的情况就是thredhold 接近于百分之五十,具体原因还请大佬们指点一下。

六、数据增强问题:

数据增强的话我采用了随机mask 的方法来做,以0.2的概率来对每个句子里面的单词做mask。

My brother and I both like to play games, why is he so obese.

My brother and I both like to play games,[UNK] is he so obese

模型在训练过程中比较快的接近收敛,但是也可能存在过拟合的问题。当时因为超时了没有提交成功,线下有三个千分点的提升。private 0.687

其他的数据增强方法目前还在尝试中~

七、后处理问题:

后处理的话考虑用的是pesudo-labeling 方法,但是考虑到训练集的数据量比较大,就没有跑完全部数据(训练集+全部测试集),只是抽取了1/5来进行实验,而且只够时间跑两轮。。。

线下测试过pesudo-labeling的处理数据一个epoch 要250s左右,比原先的要大30s左右。

private score: 0.689   public score 0.696 (嗯,看起来是严重过拟合了)

八、模型复现问题:

本次比赛大家都用的是pytorch,博主本人也是尝试了用keras 去实现了一次这个模型,但是达不到这个LB的效果。对于用惯了keras搭积木的渣渣本人来说很是不方便==

查阅了很多资料,具体原因总结如下:

 TF / Keras 有个比较严重的问题,CuDNNLSTM 和 CuDNNGRU 在训练模型时存在不确定性,同样的 Kernel,提交后分数竟然相差了 ±0.003,这在 Leader Board 上可是相差甚至一两百名的。(link)

而keras 官方也给出了解决的方法(link)具体如何我还没有去尝试

就先总结这么多了,比赛还有几天时间,继续努(fo) 力(xi)上分吧 ! 

如果你有任何疑问或者觉得哪里不对的可以在评论指出来,大家一起学习一起进步~

猜你喜欢

转载自blog.csdn.net/gdufsTFknight/article/details/86688220