1. Abstract
Quora是问答SNS网站,可以看作是国内的知乎.在该网站上有很多不同的问题需要大家解答,但是里面存在很多色情,种族歧视,辱骂等的问题(例如如何人体自交,如何跟小姨子***等令人大开眼界的问题).所以Quora举办了这个比赛来让kaggler来做一个二分类的模型将insincere questions找出来.衡量结果的指标为F1 score,这十分符合比赛的要求,毕竟实际应用中我们应该给出的hard value,而不是probability. 比赛限制条件也很多: 只允许kernel submit, 使用CPU运行最多只允许6个小时, 使用GPU运行最多只允许2个小时,不能引入外部数据.
2. Final LeaderBoard:
38th,第一次杀入前1%. 难免有些小激动, 但其实运气占比比较大, 仍需要想大家学习各种调参和特征工程的知识.
3. My main work:
Model Strutruct
这是我主要使用的模型. 比赛的最后结果使用5-fold训练5个模型比将其预测结果平均融合.
Embedding weight
embedding的权值:0.5 * glove+0.4 * para+0.1 * wiki
。权值获取方式如下: 首先获得句子当中关于3个embedding的向量x, shape为(batch_size, maxlen, embed_size, 3)。将weight(shape: (3, ))进入softmax层在与tensor x点乘得到的embedding.我将数据分为5-folds, 每个fold都获得embedding weight对其求平均值作为最终的embedding weight. 简单来说embedding的权值获取的方式为数据驱动.
Word embedding
首先我尝试word保留大小写, 然后通过预训练词向量获得其word vector. 没有匹配到的, 再将word进行: lower upper capitalize处理来寻找对应的word vector. 假如没找到就随机生成该vector. 但这总做法的效果不佳, 我猜测的主要原因是: 存在一些奇奇怪怪的拼写方式如: "tHe", "ThE".我再查找原文发现它们本来的意思就是"the".但在glove里面却找到对应的embedding vector.而这些单词出现的次数相对比较少,所以在训练glove的时候他们的置信度未必有"the"高,而且它们的意思就是一样.于是我将他们都变为lowcase.
Data Cleaning
- 用空格将一些奇奇怪怪的字符用空格分割开
- 将一些拼写有误或者在embedding当中找不到的word进行替换
- 数字用空格分割开
单词替换要注意要尽可能与原来的意思相近, 这个kernel将很多有问题的单词都转换成同义词,除了外文翻译没有做:More Text Cleaning To Increase Word Coverage. 其查找方法是Bad case analysis, 只说人工智能还是要先人工后智能.
Fitting
比赛中,我使用了Adam作为优化器, 比采用了CyclicLR作为lr的更新其. 假如CyclicLR调参调得好,会加速模型收敛速度. 所以也是很玄学的.
CV Evaluation
在discussion上, 大家都在苦恼应不应该trust local cv. 但很多人都只是trust single model local cv, 而不是trust ensemble model local cv. 对于前者评估的是single model, 后者评估的是ensemble model. 比赛最后使用的ensemble, 那应该做ensemble model local cv. 方法如下: 我们将training set分为k-folds, 然后将需要融合的模型都训练一遍并将预测结果融合,这样就得到一个fold的预测结果,如此类推.另外我使用的corr去看fold训练出来的相似度, 希望模型好而不同.我这种做法其实很危险, 毕竟split folds带有随机性, 越多随机因子, 最后结果越不稳妥.
Loss Function
我尝试使用Focal loss去做, 得到的single model local cv很不错,有0.712.但是别忘记刚刚说的,这只是single model local cv,而不是ensemble model local cv. 最后由于时间关系没有做其ensemble local cv, 但我觉得认真调一下参或许能比Binary Cross Entropy好一些.
3. Other Solutions:
1st:
- Fixed Threshold: 对所有模型预测结果的probability进行排序并将其平均, 然后计算每个fold的最佳F1与在不同的threshold下平均排序得到的F1的偏差. 使用偏差较少的threshold作为Fixed Threshold
- 为了加快训练速度,采用了动态pad_sequence, 以batch_size为单位, 来确定其max_len. 这个在tensorflow里面使用dynamic_rnn.
2rd :
- Embedding不像大家那样使用平均求和或者权值加和等, 它的word embeddings有[glove embedding 300d,
wiki embeddings 300d, 使用fasttext训练出来的64d, 4 binary features], 整个word embeddings大小为(nb_words, 668) - 与1st一样使用了动态pad_sequence.
3rd:stemmer, lemmatizer, spell correcter, lower, title 等找word vector
4rd word2vec fine-tuning & embedding sampling:
7th place solution - bucketing: 使用tensorflow当中的bucket_by_sequence_length
.将模型训练速度提高,其实跟动态pad_sequence也是相似,提高训练速度,增加融合模型的个数. standford当中的slide也有讲25页-28页
10th Meta embedding, EMA, Ensemble:
- Meta embedding意思是将embedding进行降维度 :
Embedding(max_features, 600)
Linear(in_features=600, out_features=128, bias=True)
ReLU()
GRU(128, 128, batch_first=True, bidirectional=True)
GlobalMaxPooling1D()
Linear(in_features=256, out_features=256, bias=True)
ReLU()
Linear(in_features=256, out_features=1, bias=True)
- EMA: tensorflow 当中的用法 通过采用指数衰减保持滑动平均变量
13th: 没什么特别的看头
15th Solution - focus on models: 主要集中模型融合上.
18th place solution from 300-th at Public LB: 每个epoch逐渐增大batch_size,这个我尝试过效果一般般.
20th: 使用mixed loss(BCE+F1 loss)优化网络,作者也尝试BCE + Lovasz, BCE pretrain and Lovasz fine-tune, BCE pretrain去训练,但结果都没有BCE+F1 loss效果好
22nd Solution - 6 Models and POS Tagging 使用词性标记来消除单词的歧义问题,
27th kernel: 其中一个模型使用了tf-idf作为训练特征
44th solution: Add all the randomness or how to improve your ensemble when all your models suck: 他认为用randomness来降低模型直接的相关度,但我觉得保持模型输出的确定性也是很重要,结果不能复现那也没用
1st place solution (public LB): 这是public leaderboard最高分的结果,他做的其实用脚本通过脚本访问quroa网站上对应的question,假如返回来的HTML有QuestionRestrictedInsincerePrompt,那这个就是有问题的。接着将结果压缩复制到线上kernel,再解出来就是答案。感慨 kaggle其实是通过hack来拿到最佳结果,而不是模型
欢迎各位评论,如有遗留其它好的解决方法后续更新下去。