天池数据挖掘竞赛是国内数据挖掘圈是很正规,规模很大,组织很好的竞赛平台。作为在读的一名数据挖掘小白,怀着当炮灰的念头,毅然决然的参加了这次竞赛。
赛题在这里就不详细描述,有兴趣的朋友可以去天池搜索,商铺定位比赛。主要是告诉你用户去逛商场的时候,手机会搜到wifi热点,通过给你wifi列表,用户交易时经纬度,交易时间,店铺经纬度,店铺类型,店铺价格和商场名称等信息,让你去预测该用户再次发生交易时,位于哪家店铺。训练集给出了2017年8月一整月的数据,让你去预测2017年9月前两周的商铺定位情况。
数据挖掘竞赛有一个基本的流程,首先对问题进行分析,然后进行数据预处理,然后继续进行传说中最厉害的特征工程,最后利用模型去对目标问题进行分析预测,得到结果。有些朋友的博客也分析的比较清楚,这里就不赘述了。在这里主要给出题目的分析思路和自己操作的结果
在比赛的开始阶段,可以很明显的想到wifi是能够确定店铺的关键因素。后续的事实也证明了wifi的重要性。起初我们在做规则学习,利用wifi的强度构造了wifi距离,也就是在训练集中,对每一个样本的wifi序列出现的强度值求均值,然后利用测试样本中每一个样本的wifi序列和训练样本中wifi序列中的交集部分求欧式距离,最终取距离最近的店铺作为预测结果。起初这样做,效果很差,正确率只有0.16。
后来发现会出现有两个训练样本和一个测试样本算距离,一个交集个数为4,一个交集个数为3,但是按照交集个数的算了相应wifi的距离后是4(假设每个wifi距离为1)和3,我们的思路会将测试样本的答案分配给交集个数为3的店铺,但这与实际不相符合,一般来说交集个数大,他离这家店铺也就会比较近,因此我们在算完距离以后,将算出来的距离除了一个交集个数的平方,从而放大交集个数对结果的影响,经过这样的改动,我们的成绩提升到了0.8589,还是有质的提升。
最后我们发现在wifi中有很多公共wifi,还有手机热点等,我们对求距离的条件进行了强化,对交集部分的个数大于5个的再来求距离,如果交集个数不大于5,就对其距离设为无穷大。这样大大提升了预测的准确程度,预测分数也上升到了0.8893。这里尤其感谢新神,他是为这套方案创造了一套公式,方便编程实现和调参。下次给出。
这里再给出wifi相关思路。
1. 每一个wfi序列可以看成是wifi序列,我们可以从LCS的角度去考虑每家店铺对应的wifi和测试样本中拥有长度最大的最长公共子序列,因为这里既包含了最长公共子序列的长度的影响又包含了wifi的出现的顺序信息。
2. 将每家店铺对应的wifi序列当成是自然语言处理中一句话,然后利用诸如word2vec,gensim等对其进行训练,挖掘每段wifi语言的相似性,然后从中找相似性最大的店铺作为结果。
3. wifi出现在每家店铺的顺序不同,利用wifi出现的顺序对wifi进行编码。
后来做规则,实在是做不太动了,然后刚好群里面的麦芽大神开源了一份代码。仅仅73行,但是能够有高达0.9073的成绩,实在让人有点心动。然后就下载后进行了学习。
麦芽大神的开源思路其实比较简单,就是将wifi出现次数比较少的wifi删去,然后按照商场,将每一家商场下所有的wifi做onehot,在里面是1的位置填充强度值,将其作为特征,再加上交易时的经纬度,利用xgboost做多分类,就可以达到0.9073的分数。实在是羡慕,大神思路明了,代码简洁。然后在仔细看了代码之后,居然发现大神不小心把rowid加入训练和预测,我从中摘出来之后,居然又上升了万分之5,哈哈还是挺开心的。
最后自己对代码进行修改,想着加入特征。但分析数据后,因为测试集中没有店铺相关的信息,我没有办法将店铺相关的特征加入进来,只能挖时间维度了。我通过tableau画出了平日和周末的流量图,发现两者有着明显的不同,因此我们将是否是工作日作为一列特征加入其中,通过多分类的训练,居然上升了万分之十六,还是比较开心。然后自己又重新审视数据,发现8月份有一个比较特殊的节日,那就是七夕节,我就将其加入周末中,成绩又上升了万分之一。之后我们通过观察数据发现,发现用户去店铺的时间基本是有大概的规律,有的用户只是早上而且是同一家,有的是很多家,因此我们将所有店铺的记录发生的时间统一到小时的角度,作为特征加入模型,又上升了万分之四,最终成绩终于有了较大的提升,最终由于自己思路的限制,止步复赛。但是感觉第一次参加这种比赛能够从2897支队伍中做到前200还是比较开心的,希望天池越来越好,希望自己下次能够有好成绩。这里也感谢队友新神和林神,很强势。
最后总结一下在比赛中自己的一些收获和经验教训:
1. pandas在数据分析方面真的是利器,无与伦比。但是循环真的比较慢。而且在循环嵌套的过程中不要在循环中出现深拷贝,对时间上的损耗十分大。比赛之初的代码居然可以跑三天。。。。。最终实在是等不起了,然后将所有的数据格式更改为dict,然后对其遍历,30分钟就可以搞定。
2. pkl文件序列化到硬盘,没有压缩参数,导致文件体积很大。
3. 在以后做比赛还是做开发的时候,需要统一py的版本,因为py改动激进,在字符编码方面和py2完全不一样,在这个问题上浪费了很多时间
4. 在碰到数据量大的情况,利用分而治之的思想比较重要,在这个题目中数据量比较大,因此我们分商场对其进行处理。划分成子问题,这样效果会好的多,并且执行速度上也会快的多。而且对有些变量的onehot也就变成了可能。
5. 碰到类别变量或者字符串变量,可以对类别等进行统计分组,或者找出类别之间的关系和特征,最后考虑onehot,或者利用自然语言处理中的词向量的思想
6. 在分析真实数据的时候,是否是工作日,节假日等十分重要,这种特殊的时间段,往往会表现出不一样的分布,分开处理,往往效果会好的多。
7. 时间维度刻画特征,分段离散化,找起点形成时间距离。
8. 异常数据需要做剔除,会使得预测准确率变高。
9. xgboost调参,特征重要性画法都比较重要