准备材料的时候又找了一下相关资源,发现已经有多个队伍公开方案或者开源代码了。
&1. 第一名的经验分享:/p/33243415
&2. 第三名的代码开源,模块分得很清晰,推荐阅读:/fuliucansheng/360
&3. 一份代码和总结,没公开名次:/p/31963565
以及之前的第21名的代码:/a550461053/BDCI-360
先说几点泛泛的感受。
模型都差不多,而且由于任务跟“看山杯”类似,不少人借鉴了“看山杯”的获奖模型。单模型准确率是基础,ensemble 是锦上添花,对 TOP X 才有意义。模型怎么去设计,决定分数上限。虽然网络结构设计还是有点玄学,而且当事人解释的时候怎么看怎么觉得有马后炮意味,但对于没做出来的人,这之间的差距是实打实的。Keras 很好用。尤其是如果跑大数据量和深度模型,直接用 Keras 会省很多力气。
1. 传统方法与深度模型融合
从他们的方案来看,网络模型是分数主导,贡献了至少90%,但基于规则和传统特征的方法也可以作为补充。只靠传统方法,第三个链接表示 F1 只有0.7。有人提到善用 FastText 最高可以到 0.84,已经是 TOP 10 的水平了。
分数归分数,不费时费力做专门的可视化,确实搞不清楚网络用数据中的什么信息来判断的。对于人来说,规则和传统方法当然更有底气。
从第一名的分享来看,他们是把规则和传统特征跟网络的倒数第二层连接起来,再常规地连一层线性分类器(softmax)实现的。多网络融合也可以采用这种方法。
2. 预处理
&3.中的处理方法应当是很标准的。使用全部语料训练 Word2Vec,而不是只用负样本。好处是能够得到尽可能多的数据的词典。虽然按理说负样本不应该用来训练词向量,但反过来想,负样本在总数据集中占比很高,无监督地学习负样本中的词向量,似乎也可以得到一些有用的词间关系。&3还另外用哈工大的 LTP 构造了分词+词性数据,从结果来看应该是有用的。
关于文本长度。比较通用的做法应该是计算了全样本长度的均值,大概1100个词。
另外,“看山杯”的时候有人试过“字向量”,但效果不好。这次我也试过,发现确实不行。原本觉得字与字之间的关系应当可以用 Word2Vec 来很好地建模,但结果确实不好。说不清为什么。
&3.使用的字向量方法是词性+字,模型有 0.89 的分数,确实很厉害了。
对了,跑分词的时候可以用 joblib 做线程并行,线程数不要超过你机器的线程上限。我玩了两次都把服务器搞崩了。Python 多线程好神奇啊。
跑网络的时候数据在内存里,计算在 GPU 上所以没感觉,跑脚本都是 CPU 在跑。尤其考虑 Python 的速度相对慢一点,我开始是直接逐行读文件同时做分词的,计算效率非常低。先把文件按格式做成数据集然后多线程跑分词这样会快好几倍。
3. 模型
模型就那么多。主要是 TextCNN 和 Attention 的东西,以及各种组合。Hierarchical Attention + CNN,HRCNN,都得研究一下。第一名用了所谓 C-GRU,说穿了就是卷积加循环模块。总之搭积木嘛,挨着试。
RNN 始终没怎么搞明白。看上去序列信息虽然 CNN 也成了主力,但 RNN 至少是个很好的次要模型,接下来还是得研究一下。
4. 训练
这是很多经验分享比较坑或者说无意中忽视掉的。这么干不好。很可能同样一个网络,两个人跑法不一样,一个第一,一个倒数都有可能。虽然套路也很固定,但经验不同结果就差很多。
文本数据需要的 epoch 相对少一点,&3用了15个,第八个上强行把 lr 减小到 1e-4,第十二个上放开 embedding 层的权重。每一个 epoch 都保存一次参数。
总结
比赛报名之前看一下题目和数据量,如果要跑 DNN,数据量还比较大(一般超过1G),没有好一点的 GPU 就不要参与了,纯属浪费时间。360 的数据其实不算好,而且“生成文本”本身就是个比较难的课题。根据一些 EDA,有机械拼接的,有网络生成的,还有很多疑似错标的。比赛数据可以说小问题不断,大问题不少。另外据说决赛的时候第二还是第三的队伍因为跟 360 的评委有点纠纷直接被判为第五。好霸道啊。所以这次的数据不适合用来学习。找一些小数据集,或者 Kaggle 这次的 Toxic Comments,才几十MB的文件。套路一定要熟悉。多写代码多写代码多写代码。哪怕只用 Keras,数据处理、模型设计和调参一定要熟练,而且中间环节不要有错误。之前看到的一份资料,文本分类常用模型都囊括进来了,推荐一下:
/brightmart/text_classification