作者 @惊鹊 学校 | UIUC 知乎 | 惊鹊的机器学习笔记
最近本人参加了一场NLP文本分类比赛,参赛本意是想将自己掌握的理论知识加以实践,这篇文章就是想对这次参赛经验做一次总结,分享出来与大家交流,起到一个利他的作用。
比赛源码由github链接给出,尽可能给出了源码以及一些讲解-(训练好的模型文件并没有上传, 一些文件直接跑或许会有对应的信息的报错)
该比赛面向零基础小白,比赛赛题是匿名数据的文本分类比赛,所谓匿名数据也就是脱敏数据,文字是用数字来表示的,所以该比赛一个重点就是如今比较火的预训练模型: Bert系列可能没办法拿来直接使用,以及Word2Vec和GloVe等词向量也必须选手重新自己训练,所以如果是对整个流程不是很清楚的选手,很建议参加该比赛或者复盘比赛来进一步深入地学习。
数据包含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个字,可以看出文本非常长,这也是本次比赛数据集最关键的特点。
这里对于竞赛小白还是很重要的,我们首先用9:1的比例划分线下训练集和线下验证集。然后对应TextCNN等等预训练模型之前表现很好的模型,必须将文本进行一个截断,我直接采用了尾部截断的策略,对应那几个模型将每句话截断至2400 (这里的策略是要求这个长度起码覆盖90%/95%的数据)-这里直接用的是tf2.0+的Keras。
对于Bert-small而言,则是选择了首尾截断,对于每个文本都截断/填充到512的文本长度。然后对于预训练所需要的数据我则是结合了train-set与A榜的测试数据,利用句号 感叹号和问号来对文本进行相应的分割,获取了多个句子。
关于标点符号的统计,一般来说,这种统计每个词出现的次数,逗号出现的一般是最多的,其次是句号,剩余的几个出现次数很多的可以先保留记录成字符集合A,因为也有可能是一些真实的文字,然后再对文本的最后一个字符进行统计,基于之前的字符集合A,出现的最多的可能就是问号和感叹号等等。
因为本次比赛的数据经过脱敏,因此无法使用外部已经实现好的词向量,需要我们自己训练,比如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的表达
Bert我则是自己利用pytorch-pretrained-bert这个包写了对应的预训练代码,当然之前也尝试过tianchi的Bert-mini, 不过结果一般,可能单模型singlefold也只有0.95这里。鉴于本人GPU资源有限,我就训练了一个Bert-small,具体的Bert版本(small/medium/base/large)可以见这里。
个人觉得Bert系列的模型如果采用medium和base预训练了的话,可能效果就会超过我,达到比赛的top3。
首先介绍几个通用且好玩的Trick:
首先用tfidf+lightgbm做了一个baseline,当时提交的结果就有0.945这儿了。一般来说比赛都要先搭建一个baseline进行迭代优化。
首先是基于深度学习的文本分类的模型介绍: 史博:基于深度学习的文本分类[4]
这里就不进行详细的介绍了,如果有感兴趣的同学可以通过阅读各种专栏以及比赛分享进行查阅和理解。
比赛中主要采用了
首先测试的是TextCNN这个模型,我也有一些小经验可以和大家分享,很推荐大家了解DPCNN这个模型。个人在小瑶的分享上学到了很多:夕小瑶:从经典文本分类模型TextCNN到深度模型DPCNN[5]
这篇文章很详细地讲解了对于文本分类到底是卷积层重要还是分类层重要,我通过这个改进了一下自己的TextCNN,加入了一层全连接层效果有1个点的improvement,虽然最后我并没有选择这个模型hhh。
然后关于Multi-sample Dropout这个是比赛的一个trick啦,经过我个人的实验,总之收敛速度还是很快的,泛化性能可能有少许提升。具体的介绍可以看这里:
这些模型大体都是按照这个模式的:
本次比赛Bert效果也没有那么显著超过以前的textbigru等等模型,我想最主要的原因也在于Bert系列需要更多的数据或者更好的策略进行预训练,但我想如果用Bert-medium和base等等应该分数还会有提升,因为我的small我也仅仅预训练了几个epoch,优化的也没有那么好。
关于模型融合,一般来说结合几个偏差比较接近+有较大区别的模型集成效果很好,我这里做了一些尝试,拿tfidf的预测概率来做stacking也会有一点点的improvement,当然也可以直接将tfidf feature拿出来用做stacking的feature,说不定也会有改进。
里面表现的最好的就是bertbilstm_attn+textbigru这两个模型,光是simple average,结果就有0.969+。
后面用oof的stacking做了一些工作,分数最后在B榜有0.9702,但是我在线下验证集的结果有0.971,我想这很可能是训练集和测试集类别分布不一致的原因吧。
本次比赛很基础,很适合对NLP没有什么实践经验的同学入手,对个人的提升还是有不少的!欢迎各位朋友有机会和我一起参加各种比赛,提升自己的实践能力~
本人查看过比赛第一名的方案,其实他们的工作比我简单,他们只是单纯使用了bert-base+对抗训练embedding+bert版本的模型融合就达到了0.973的f1-performance。在这里给大家做这样的讲解希望大家都可以有更好的成长~
零基础入门NLP - 新闻文本分类-天池大赛-阿里云天池: https://tianchi.aliyun.com/competition/entrance/531810/introduction
[2]Dynamic Meta-Embeddings for Improved Sentence Representations: https://arxiv.org/pdf/1804.07983.pdf
[3]lsh1803544/bert: https://github.com/lsh1803544/bert
[4]史博:基于深度学习的文本分类: https://zhuanlan.zhihu.com/p/34212945
[5]夕小瑶:从经典文本分类模型TextCNN到深度模型DPCNN: https://zhuanlan.zhihu.com/p/35457093
[6]在文本分类任务中,有哪些论文中很少提及却对性能有重要影响的tricks?: https://www.zhihu.com/question/265357659/answer/578944550
- END -
由于微信平台算法改版,公号内容将不再以时间排序展示,如果大家想第一时间看到我们的推送,强烈建议星标我们和给我们多点点【在看】。星标具体步骤为:
(1)点击页面最上方"AINLP",进入公众号主页。
(2)点击右上角的小点点,在弹出页面点击“设为星标”,就可以啦。
感谢支持,比心。
推荐阅读
征稿启示| 200元稿费+5000DBC(价值20个小时GPU算力)
完结撒花!李宏毅老师深度学习与人类语言处理课程视频及课件(附下载)
模型压缩实践系列之——bert-of-theseus,一个非常亲民的bert压缩方法
文本自动摘要任务的“不完全”心得总结番外篇——submodular函数优化
斯坦福大学NLP组Python深度学习自然语言处理工具Stanza试用
关于AINLP
AINLP 是一个有趣有AI的自然语言处理社区,专注于 AI、NLP、机器学习、深度学习、推荐算法等相关技术的分享,主题包括文本摘要、智能问答、聊天机器人、机器翻译、自动生成、知识图谱、预训练模型、推荐系统、计算广告、招聘信息、求职经验分享等,欢迎关注!加技术交流群请添加AINLPer(id:ainlper),备注工作/研究方向+加群目的。
阅读至此了,分享、点赞、在看三选一吧🙏