2019中国高校计算机大赛已正式结束。对于我个人而言,这是第一次进入算法比赛的TOP10。我们队伍在初赛排在大概50名左右,复赛B榜8名,最终决赛第9名,这里是自己比赛的最终提交方案,求star。。。。。。。。。。本次总结是争对决赛TOP5方案的,毕竟自己做的跟他们比还有一些差距,我会尽自己所能的将他们做的全部方案融合进这一篇blog中,以此来帮助到我和大家。
blog中直接引用了很多TOP5方案的PPT,如果有哪些组不愿意将自己的PPT或者方案公开,请联系我邮箱[email protected],我将第一时间在blog中删除。另外,相关nlp比赛想组队也可以联系我,求大佬carry。
总的来说,这次比赛前排TOP10的方案中几乎都包括了lgb和esim两个模型。而且在esim模型中除了第五名的一组,其他的都加入了手工特征。我记得评委在现场问过一句话–“我看过前面的很多方案,他们做的跟你们大体一样,但为啥各自的线上qAuc差别很大”,我已经记不得当时的大佬是怎么回答,前排的成绩相对来说还说还比较接近,各自的差异可能仅仅是由于一处到两处的做法不同,这一点在特征工程还不太明显,但是在后面nn结构设计尤为明显,TOP3都争对esim做了一些很小的改动,废话不多说了,下面直接进入到赛题分析部分。
搜索中一个重要的任务是根据query和title预测query下doc点击率,本次大赛参赛队伍需要根据脱敏后的数据预测指定doc的点击率。
训练集为10亿,A榜测试集为2KW, B榜测试集为1亿。
[外链图片转存失败(img-d9B596hv-1566973637025)(C:\Users\tinySean\AppData\Roaming\Typora\typora-user-images\1566959895666.png)]
第二名的队伍分析了queryid下title数目的分布情况,大家看一下这个柱状图,我们只列出来了title数目为3、4、5、6、7和20的分布情况,训练集中queryid下title数量为20的比较多,A榜测试集中queryid下title数量为3的比较多,我们通过线下测试发现,queryid下title数目为3的qauc值远低于title数目为20的qauc值,这也说明了为什么线上线下得分差异比较大,而B榜测试集的queryid下的title数量分布情况和训练差不多,因此B榜得分相对与A榜得分高了很多。
上面我原封不动的摘抄了他们的PPT,他们的大致意思就是相对于testA,testB query_id下title数目的分布情况更接近于训练集,但是他们这里并未给出testB的分布情况,可能是由于时间情况吧。假设testB和训练集的分布情况差异也很大的话,那么我们可能需要对训练集进行一些采样来拟合testB构建验证集进行本地验证,甚至可能需要拟合训练集分布来进行训练。
[外链图片转存失败(img-CqSSp1Ad-1566973637026)(C:\Users\tinySean\AppData\Roaming\Typora\typora-user-images\1566960083172.png)]
上图也来自第二名队伍的数据分析。其实这方面工作我们也做了,主要就是看看query和title对在测试集的重复率,当时我们是根据这重复率来对训练集进行采样拟合测试集A,我们考虑的是如果对于重复的title和query,nn预测出的点击率可能会比较高(因为它以前看过这个),而对于新的title和query,nn可能预测出的点击率可能会比较低(它以前没看过这个),因此如果测试集中大量都是训练集中没出现的query和title,那么整体预测出的点击率分布会偏低,qAuc这一排序指标就不太准,可惜的是当时我们做的这份工作反而把整体模型的性能拉低了。我猜测可能是由于训练集和测试集的时间戳是连续的,直接进行随机采样可能会打乱这时间戳的连续性,决赛中TOP10方案好像没有随机采样训练集的。(当然也存在另外一种可能,那就是我的代码有BUG,如果你有拟合测试集的成功案例的话希望能在讨论区跟我反馈一下)。
特征工程大家做的差异很大,大致可以分为下列这几类
nunique特征,也可以理解为query和title出现的频次,不同query下title的数目,不同title下query的数目(对query id进行groupby之后再对title进行unique)
下面是第四名对上述特征的解释:query次数表示用户看到不同title的个数。个人理解看的越少说明有足够满意的title。(包含用户行为信息)title的频率包含了title的热度,频率越高说明该title的热度越高。
最长公共子序列,最长公共子序列在query中的跨度,最长公共子序列在title中的跨度,最长子序列长度/title长度等特征
前缀后缀特征
Difflib(计算query和title之间的diff ratio,marchs表示共现词长度和), sequencematcher
[外链图片转存失败(img-wWw46MNU-1566973637031)(C:\Users\tinySean\AppData\Roaming\Typora\typora-user-images\1566966768765.png)]
LongShareRate,最长共现语句 s,计算
[外链图片转存失败(img-sbLVZYNh-1566973637032)(C:\Users\tinySean\AppData\Roaming\Typora\typora-user-images\1566966310763.png)]
fuzzywuzzy模糊匹配
N-gram特征
编辑距离(Levenshein)
jaccard距离
pagerank,分别以query和title为节点构建有向图,计算query和title的文本重要性。
[外链图片转存失败(img-8yNt6a8A-1566973637034)(C:\Users\tinySean\AppData\Roaming\Typora\typora-user-images\1566967056823.png)]
下面一些相似度特征可以只选取query的前m个词,以及title的前n个词,因为对于ctr问题,前面词的重要性更加高。
首先定义相似度函数:有欧氏距离、曼哈顿距离、Canberra距离、汉明距离、余弦距离等等,具体可在scipy的spatial.distance下搜寻。
下面是第四名队伍给出的距离函数重要性排序:
[外链图片转存失败(img-6uqi2NlS-1566973637036)(C:\Users\tinySean\AppData\Roaming\Typora\typora-user-images\1566967828521.png)]
之后就要选择争对哪些向量了,可以直接得到的有tfidfvectorizer和countvectorizer出来的稀疏向量,对于这类向量的相似度的计算可以尝试skelarn.pairwise下的那些函数(经测试,它们的计算速度较快)
而对于word2vec和fasttext出来的向量组,有下列三种方式转成句向量:
直接等权平均
根据tf_idf加权,
Smoothed Inverse Frequency Embedding,第二名队伍分析中指出这一种方法会比tf_IDF加权上升2个千
word2vec和fasttext转成句向量后就可以直接通过相似度函数计算相似度特征
除去上面这些相似度特征,还有下面一些函数库计算的相似度特征
自己也尝试过去构建点击率特征,在初赛的时候总体性能还行,但是到了复赛却崩了,这是一个相当容易导致模型过拟合的特征,使用的时候技巧性比较强,各组争对过拟合也有自己的方案。
首先说第五名的方案:他们组使用使用前9亿5000万数据进行统计title的ctr,使用后5000万做训练,最终出
现了严重的过拟合。解决策略是将训练两个lgb,第一个包括ctr但不包括title相关特征,第二个包括title相关特征,两个lgb的特征是完全没有重合的地方的。由于lgb能够自动组合特征,将ctr和title两个特征拉开,可以防止lgb记住ctr和title的组合(也就是防止lgb将ctr和title关联到一起),以此来遏制过拟合。同时这两个lgb差异性比较大,这样他们的最终融合收益也比较高。
第四名的方案:
[外链图片转存失败(img-3rOWscvx-1566973637037)(C:\Users\tinySean\AppData\Roaming\Typora\typora-user-images\1566968788827.png)]
第二名的方案:
[外链图片转存失败(img-dYCV0hQw-1566973637039)(C:\Users\tinySean\AppData\Roaming\Typora\typora-user-images\1566968806911.png)]
第三名的方案(这也是我觉得解决的最好的一个点击率特征方案):
[外链图片转存失败(img-BdL85TMC-1566973637040)(C:\Users\tinySean\AppData\Roaming\Typora\typora-user-images\1566968885405.png)]
他们组跟前面组最大的差别就是对query和title提取关键词,这样可以大幅减少空值。
8、 其余特征
词位置特征(query前10个词在title中的位置)
Proximity
title质量分数特征
[外链图片转存失败(img-RoSTpUpM-1566973637042)(C:\Users\tinySean\AppData\Roaming\Typora\typora-user-images\1566969454532.png)]
末词(tag)的信息数据挖掘
[外链图片转存失败(img-2TfqXfJI-1566973637043)(C:\Users\tinySean\AppData\Roaming\Typora\typora-user-images\1566969524271.png)]
word share特征
[外链图片转存失败(img-x3i4jggV-1566973637045)(C:\Users\tinySean\AppData\Roaming\Typora\typora-user-images\1566969575202.png)]
[外链图片转存失败(img-MF1Ug6n3-1566973637047)(C:\Users\tinySean\AppData\Roaming\Typora\typora-user-images\1566969588356.png)]
每个特征内部也可以争对同一个query定义一个排名,尤其是相似度特征
直接拿nn的某一嵌入曾输出作为lgb特征,拿esim来说,可以把maxpooling和averagepooling那层之后的作为lgb特征,这会是相似度特征的一个很好的刻画。
每个特征计算耗时不同,重要性也不同,需要对他们进行一个统一的筛选,选择方案有大概下面三种(当然仅仅是TOP5方案中出现或者我自己使用的):
机器学习模型自然是以lgb为主的,lgb对数据不太敏感,它的性能高低完全取决于前面所做的特征,TOP5方案有人把lgb做到了0.626,最终也取得了较好的排名。
深度学习主要就是esim模型,几乎所有队伍都得出一致的结论:在这题上面esim是最优nn,大家主要就是争对这一nn进行讨论。
对于esim,首先要讨论的就是要不要加入第三个输入,大部分组是直接选择加入手工特征来提高nn单模成绩,但这样做会降低nn和lgb的差异性,使得融合的收益减少。值得注意的是,第五名的队伍他们在nn中没有加入第三个输入,最终两个lgb(0.57, 0.59)和一个esim(0.58)融合出了0.627的成绩,也就是不加入第三个输入的nn融合收益很大。
接下来就说加入手工特征的nn,大部分队伍都是把lgb全部特征输入nn,对于我个人而言我是选取了lgb的部分特征输入了nn,我觉得加入太多特征会扰乱nn反向传播,会使得第三个输入反向传播的梯度比较大,第一个输入和第二个输入反向传播的梯度比较小,当然这仅仅是实验结论(打印nn的weights),但是这选取方法是纯手动的。esim融入手工特征有两种方案:
concat方案
gate方案(要略微优于concat)
eisim模型上的微调还有将两层BILSTM改成BIGRU和CNN进行融合,以此增加模型上的多样性,也就是即使对于同一组训练集,在不对模型做大的变动下仅仅改变那两层BILSTM就可以得到三个esim变体。对于我个人来说的话,我尝试过将esim的Embedding层进行替换,也就是我训练了两个词向量fasttext和word2vec,仅仅替换它们就可以得到两个esim变体。
在nn训练时,有的队伍采用了CLR修改学习率,以及SWA得到全局化的通用最优解。
最后说说自己队伍的一些在nn上做的主要变动吧,我们仅仅在手工特征的基础上加入lgb stacking特征(即五折lgb的预测值),就使得nn从0.602上升到了0.618,进入了前十
下面是第三名的方案,用相关系数进行模型选择
[外链图片转存失败(img-s0DGuPwH-1566973637047)(C:\Users\tinySean\AppData\Roaming\Typora\typora-user-images\1566972577016.png)]
模型融合最主要的就是增加模型的多样性,在增加模型多样性方面有下列方案
二分类(bce loss)问题和排序问题(pairwise loss)的思考,大部分队伍都是将这一题视为前一类问题,对于后面一类问题我自己不太懂,但是第二名方案的实验结果表明lgb排序loss的性能比lgb二分类loss的性能要出色。
最后回过头来看前三名的方案,他们都使用了3亿以上的数据量,而我们自己队伍仅仅使用了一亿的数据量,我感觉对于这一题的关键点就是数据量的使用吧。
TOP5方案的PPT
第三名完整解决方案
第五名完整解决方案
第九名完整解决方案,求star