Rank4 NLP 新闻文本分类 - 开源代码 + 经验分享 @惊鹊
最近本人参加了一场 NLP 文本分类比赛,参赛本意是想将自己掌握的理论知识加以实践,这篇文章就是想对这次参赛经验做一次总结,分享出来与大家交流,起到一个利他的作用。
比赛源码由 github 链接给出,尽可能给出了源码以及一些讲解-(训练好的模型文件并没有上传, 一些文件直接跑或许会有对应的信息的报错)
目录:
比赛描述
Tricks 和模型介绍
模型融合
总结
1. 比赛描述
该比赛面向零基础小白,比赛赛题是匿名数据的文本分类比赛,所谓匿名数据也就是脱敏数据,文字是用数字来表示的,所以该比赛一个重点就是如今比较火的预训练模型: Bert 系列可能没办法拿来直接使用,以及 Word2Vec 和 GloVe 等词向量也必须选手重新自己训练,所以如果是对整个流程不是很清楚的选手,很建议参加该比赛或者复盘比赛来进一步深入地学习。
1.1. 简单数据统计
数据包含 3 个数据文件
1) 线下用的训练数据 train_set.csv;
2) A 榜的测试数据 test_a.csv;
3) B 榜的测试数据 test_b.csv;
经过统计,train_set.csv 和 test_a/b.csv 分别包含 20w 和 5w 数据,包含将近 7000 个不同的 word,以及每篇文本平均长度为 900 个字,可以看出文本非常长,这也是本次比赛数据集最关键的特点。
1.2 数据预处理
这里对于竞赛小白还是很重要的,我们首先用 9:1 的比例划分线下训练集和线下验证集。然后对应 TextCNN 等等预训练模型之前表现很好的模型,必须将文本进行一个截断,我直接采用了尾部截断的策略,对应那几个模型将每句话截断至 2400 (这里的策略是要求这个长度起码覆盖 90%/95%的数据)-这里直接用的是 tf2.0+的 Keras。
对于 Bert-small 而言,我则是选择了首尾截断,对于每个文本都截断/填充到 512 的文本长度。然后对于预训练所需要的数据我则是结合了 train-set 与 A 榜的测试数据,利用句号 感叹号和问号来对文本进行相应的分割,获取了多个句子。关于标点符号的统计,一般来说,这种统计每个词出现的次数,逗号出现的一般是最多的,其次是句号,剩余的几个出现次数很多的可以先保留记录成字符集合 A,因为也有可能是一些真实的文字,然后再对文本的最后一个字符进行统计,基于之前的字符集合 A,出现的最多的可能就是问号和感叹号等等。
1.3 词向量预训练
因为本次比赛的数据经过脱敏,因此无法使用外部已经实现好的词向量,需要我们自己训练,比如 Word2Vec, GloVe, Fasttext, Bert 等等。
Word2Vec 我采用的 gensim 的 word2vec 进行了相应的训练,fasttext 用的 facebook 的开源的包进行了训练,GloVe 我用 stanford 的开源的脚本修改了 sh 文件,提取了对应的 GloVe vector。(最后关于 meta embedding,我选择将 200dim 的 word2vec(skip-gram 和 CBow 没什么特别大的区别啦,我就直接用的 CBoW)+200dim 的 GloVe 进行 concat 作为最后的表达,我并没有选择 Fasttext,因为 Fasttext 和 Word2Vec 可能相关性会高一些,会弱化 word2vec 的表达)-关于 Meta Embedding 的介绍可见:https://arxiv.org/pdf/1804.07983.pdf-Bert 我则是自己利用 pytorch-pretrained-bert 这个包写了对应的预训练代码,当然之前也尝试过 tianchi 的 Bert-mini, 不过结果一般,可能单模型 singlefold 也只有 0.95 这里。鉴于本人 GPU 资源有限,我就训练了一个 Bert-small,具体的 Bert 版本(small/medium/base/large)可以见这里。GitHub - lsh1803544/bert: TensorFlow code and pre-trained models for BERT我个人觉得 Bert 系列的模型如果采用 medium 和 base 预训练了的话,可能效果就会超过我,达到比赛的 top3。
2. Tricks 和模型介绍
首先介绍几个通用且好玩的 Trick:
对抗验证,我们可以从训练数据中抽取一部分以及从测试数据中抽取一部分提取特征然后用一个简单快捷的模型进行训练,将训练数据对应的 label 设置为 1,将测试数据对应的 label 设置为 0,如果模型分类效果很好,那么可能本次比赛不是很好入手,因为训练集和测试集的分布都不是那么接近了。-具体的代码实现可以见我的 github。
由于本次比赛是一个文本分类任务,我们还可以通过文本匹配的方式来做,本人尝试了用 fasttext 提取的测试集的 sentence vector 对应训练集的 sentence vector 做了个相似度计算,选择了最接近的训练数据的标签作为对应测试数据的标签,个人觉得这个策略很有意思。 2.1 baseline 构建 首先我用 tfidf+lightgbm 做了一个 baseline,当时提交的结果就有 0.945 这儿了。一般来说比赛都要先搭建一个 baseline 进行迭代优化。 2.2 本次比赛我使用基于深度学习的模型介绍 我这里就不进行详细的介绍了,如果有感兴趣的同学可以通过阅读各种专栏以及比赛分享进行查阅和理解。
我这里主要采用了
tianchi: Bert-small + BiLSTM + Attention
Bert-RNN
Bert-Multisample Dropout
Bert-RCNN
Textcapsule
TextBiGRU
我首先测试的是 TextCNN 这个模型,关于这里我也有一些小经验可以和大家分享,这里很推荐大家了解 DPCNN 这个模型。@详细可以看我知乎分享。在 TextCNN 后加上 FC 可以进一步改善性能。
然后关于 Multi-sample Dropout 这个是比赛的一个 trick 啦,经过我个人的实验,总之收敛速度还是很快的,泛化性能可能有少许提升。
查看本文全部内容,欢迎访问天池技术圈官方地址:Rank4 NLP新闻文本分类-开源代码+经验分享@惊鹊_天池技术圈-阿里云天池
评论