~~~~~~····终于比赛还是结束了,想说研一一半的青春奉献给了阿里,最后艰难挤进了前五十,一路过来真心不容易,每天早上醒来的第一件事就是查成绩,三个月来天天如此,晚上熬夜提交预测,那样的日子想说爱你不容易。。。回顾一路走来的艰难历程,回味其中的付出和收获,谨以此文献给一路走来一起奋斗的小伙伴,么么哒···~~~~~~
一次偶然的机会,在去实验室的路上见到了阿里天猫推荐算法的比赛海报,对近来炒得很火的大数据有很浓的好奇心,点开报名网址,大数据比赛,便踏上了接近四个月的阿里竞赛之路。
比赛大概的描述是:第一赛季阿里官方提供少量的某年4-15到8-15这段时间离线的天猫真实行为数据,参赛者利用机器学习的方法,预测8.15-9-15的用户购买情况,具体评分方式为:根据预测的正确率和召回率计算出调和平均得分来考量参赛者的成绩,如下图所示:
接触第一赛季的时候,比赛已经进行了半个多月,由于非CS出生,机器学习方面只学习过皮毛,做过一两个实验。。。可以说经验匮乏,草草的和实验室队友组队了(草率的决定让自己后来说不出的心酸...无力吐槽),第一次胡乱的提交了一次成绩,第二天就有了成绩啦,看到了成绩以及排名,当时还有点小兴奋,虽然成绩不好,总算有个成绩啦。。。
接下来几天成绩都有小幅度上涨,具体的做法是利用学习过的逻辑回归LR和加一些简单的统计规则进行推荐,一些简单的规则有:利用用户对品牌的点击、购买、收藏、加入购物车这四种基本操作给品牌打分,将得分较高的品牌推荐给用户,做了半个多月,成绩一路上涨
最后还是稳稳的进入了前500名,得到了接触第二赛季的机会,赛季结束的时候,官方组织确定了最终的参赛队伍信息,第一赛季几乎是一个人战斗的我,选择了重新组队,和室友新组建了一个2人小队,心血来潮搞了个队名,,挤进第二赛季,当时定下的目标,冲击一百万,赢取白富美,出任CEO,走上人生巅峰,小小兴奋了一把(~纯属自娱自乐~)
休整了几天之后,阿里开放了第二赛季的天池大数据计算平台ODPS供参赛者使用,对于第一次接触大数据分析平台的我们来说,真是啥都不会。。。三个月的奋斗,我们组大概用了纯规则、LR、RF、GBRT四种方法,其他的一些SVM、贝叶斯等方法效果甚微,浅尝辄止。
第一时间打开了提供的ODPS用户手册,看了简单的入门之后,就开始弄了,再次从0开始学习,这次提供的用户操作记录数比第一赛季高了几个数量级,达到了5亿的规模,直接按照手册提供的sql语句添加的简单规则(给用户推荐热门的10个商品)进行了一次的提交,结果就有了成绩,小激动啊:
接下来的几天,按照第一赛季的流程,对数据进行预处理,删除未购买过品牌的用户记录(不删除最近一周才出现的新用户),删除未被购买过的品牌记录,删除疯狂点击但是从不购买的刷钻用户记录等,利用一些简单规则:定义热门品牌集合,交互时间记录统计,活跃用户集合,最近新出现的品牌集合,周期品牌集合,用户的品牌忠诚度,用户对品牌的操作加权打分等规则,每加一条规则,成绩都蹭蹭蹭往上涨(毕竟我们的baseline还很低),幸福洋溢的感觉有木有:
提升了几天,丝毫没有察觉到规则带来的局限,依靠纯规则推荐,挖掘不出用户购买行为深层次的关系注定有提升上限,做了接近10天的规则成绩涨到3.9左右,不管怎么添加规则,我们的成绩也始终上涨不了了。
训练:筛选出4月15号到7月02号的有过交互记录的,并且在7月03号到7月21号发生购买的用户品牌对作为正样本,将4月15号到7月02号剩下的记录作为负样本,构建好特征后,训练到线下的LR模型;
预测:利用4-15号到7月21号的所有数据,构建好特征后,带入线下训练好的LR模型进行验证;
训练:筛选出4月15号到7月21号的有过交互记录的,并且在7月22号到8月15号发生购买的用户品牌对作为正样本,将4月15号到7月21号剩下的记录作为负样本,构建好特征后,训练到线上的LR模型;
预测:利用4-15号到8月15号的所有数据,构建好特征后,带入线上训练好的LR模型进行推荐;
数据集划分好后,我们组花了大量的时间构建特征,从三个角度出发,用户品牌交互特征类,用户特征类和品牌特征类,到第二赛季结束的时候,累计构建了715个特征(真的是一个比拼特诊构建的比赛了),只罗列出我们组最后用上的效果比较好的一组特征,详细如下:
构建用户与品牌之间交互的统计特征,体现用户与品牌之间的交互特性,大致反映出用户与品牌之间满足某种映射下会发生购买行为,大概有:
<pre name="code" class="objc">click_count :用户A对品牌B的总点击数 buy_count :用户A对品牌B的总购买数 collect_count :用户A对品牌B的总收藏数 cart_count :用户A对品牌B的总加入购物车数 avg_buy_day_count :用户A对品牌B的各次购买离现在的平均天数 variance_buy_day_count :用户A对品牌B的各次购买离现在的时间的方差 least_click_day_count :用户A对品牌B的最近一次点击离现在的天数 least_buy_day_count :用户A对品牌B的最近一次购买离现在的天数 least_collect_day_count :用户A对品牌B的最近一次收藏离现在的天数 least_cart_day_count :用户A对品牌B的最近一次购物车离现在的天数 click_count_before_firstbuy :用户A对品牌B的第一次购买前的点击数 collect_count_before_firstbuy :用户A对品牌B的第一次购买前的收藏数 cart_count_before_firstbuy :用户A对品牌B的第一次购买前的购物车数 avg_click_day_interval :用户A对品牌B的平均点击天数间隔 avg_buy_day_interval :用户A对品牌B的平均购买天数间隔 first_operator_day_count :用户A对品牌B的第一次交互离现在的天数 last_operator_day_count :用户A对品牌B的最后一次交互离现在的天数 max_operator_Day_count :用户A对品牌B的交互次数最多那天离现在的天数 user_buy_brand_rate :用户A对品牌B的购买次数占用户A总购买次数的比例 user_click_brand_rate :用户A对品牌B的点击次数占用户A总点击次数的比例 click_buy_rate :用户A对品牌B的点击购买比 click_2_count :用户A对品牌B的点击数的平方 buy_2_count :用户A对品牌B的购买数的平方 brand_is_bought_rate :用户A对品牌B的购买次数占品牌B被购买的总次数的比例 brand_is_clicked_rate :用户A对品牌B的点击次数占品牌B被点击的总次数的比例 last_31_day_click_buy_rate :用户A对品牌B的最近31天的点击购买比 click_day_count :用户A对品牌B的点击总天数 buy_day_count :用户A对品牌B的购买总天数 buy_last_week_count :用户A对品牌B购买了多少周 avg_click_rate_before_buy :用户A对品牌B最后一次购买后的点击数/用户A对品牌B每次购买前的平均点击 avg_collect_rate_before_buy :用户A对品牌B最后一次购买后的收藏数/用户A对品牌B每次购买前的平均收藏 click_delete_user_avg_rate :(用户A对品牌B的点击数-用户A对操作过的品牌的平均点击数)/用户A对操作过的品牌的平均点击数 buy_delete_user_avg_rate :(用户A对品牌B的购买数-用户A对操作过的品牌的平均购买数)/用户A对操作过的品牌的平均购买数 collect_delete_user_avg_rate :(用户A对品牌B的收藏数-品牌B被平均收藏数)/品牌B被平均收藏数 before_0_day_last_5_day_click_count :用户A对品牌B离现在5天之内的点击数 before_0_day_last_5_day_buy_count :用户A对品牌B离现在5天之内的购买数 before_0_day_last_5_day_collect_count :用户A对品牌B离现在5天之内的收藏数 before_0_day_last_5_day_cart_count :用户A对品牌B离现在5天之内的加入购物车数 before_0_day_last_10_day_click_count :用户A对品牌B离现在10天之内的点击数 before_0_day_last_10_day_buy_count :用户A对品牌B离现在10天之内的购买数 before_0_day_last_10_day_collect_count :用户A对品牌B离现在10天之内的收藏数 before_0_day_last_10_day_cart_count :用户A对品牌B离现在10天之内的加入购物车数 before_10_day_last_10_day_click_count :用户A对品牌B离现在10天之前的10天之内的点击数 before_10_day_last_10_day_buy_count :用户A对品牌B离现在10天之前的10天之内的购买数 before_10_day_last_10_day_collect_count:用户A对品牌B离现在10天之前的10天之内的收藏数 before_10_day_last_10_day_cart_count :用户A对品牌B离现在10天之前的10天之内的加入购物车数 before_20_day_last_10_day_click_count :用户A对品牌B离现在20天之前的10天之内的点击数 before_20_day_last_10_day_buy_count :用户A对品牌B离现在20天之前的10天之内的购买数 before_20_day_last_10_day_collect_count:用户A对品牌B离现在20天之前的10天之内的收藏数 before_20_day_last_10_day_cart_count :用户A对品牌B离现在20天之前的10天之内的加入购物车数 before_30_day_last_10_day_click_count :用户A对品牌B离现在30天之前的10天之内的点击数 before_30_day_last_10_day_buy_count :用户A对品牌B离现在30天之前的10天之内的购买数 before_30_day_last_10_day_collect_count:用户A对品牌B离现在30天之前的10天之内的收藏数 before_30_day_last_10_day_cart_count :用户A对品牌B离现在30天之前的10天之内的加入购物车数 before_0day_last_10_day_click_day_count:用户A对品牌B离现在10天之内的总点击天数 before_0day_last_10_day_buy_day_count :用户A对品牌B离现在10天之内的总购买天数
构建体现用户特性的特征,尽量挖掘处用户购物行为习惯,大致有如下特征:
user_buy_count :用户A总购买的次数 user_click_count :用户A总点击的次数 user_collect_count :用户A总收藏的次数 user_cart_count :用户A总购物车的次数 user_click_buy_rate :用户A总的点击购买比 user_avg_buy_day_count :用户A所有购买发生的时间离现在的平均天数 user_least_buy_day_count :用户A最近一次购买离现在的天数 user_variance_buy_day_count :用户A所有购买发生的时间离现在的时间方差 user_last_5_day_click_count :用户A最近5天的点击总数 user_last_5_day_buy_count :用户A最近5天的购买总数 user_last_5_day_collect_count :用户A最近5天的收藏总数 user_last_5_day_cart_count :用户A最近5天的加入购物车总数 user_click_day_count :用户A点击的总天数 user_buy_day_count :用户A购买的总天数 user_collect_day_count :用户A收藏的总天数 user_cart_day_count :用户A加入购物车的总天数 user_buy_brand_count_for_1_week:用户A只购买1周的商品有多少种 user_buy_brand_count_for_2_week:用户A只购买2周的商品有多少种 user_buy_brand_count_for_3_week:用户A只购买3周的商品有多少种 user_buy_brand_count_for_4_week:用户A只购买4周的商品有多少种
构建体现品牌特性的特征,尽量挖掘处什么样的品牌受用户追捧,会被用户购买,大致有如下特征:
brand_click_count :品牌B被点击的总次数 brand_buy_count :品牌B被购买的总次数 brand_collect_count :品牌B被收藏的总次数 brand_cart_count :品牌B被加入购物车的总次数 brand_click_buy_rate :品牌B的点击购买比 brand_last_3_day_click_count :品牌B最近3天之内的点击总数 brand_last_3_day_buy_count :品牌B最近3天之内的购买总数 brand_last_5_day_click_count :品牌B最近5天之内的点击总数 brand_last_5_day_buy_count :品牌B最近5天之内的购买总数 brand_last_11_day_click_count :品牌B最近11天之内的点击总数 brand_last_11_day_buy_count :品牌B最近11天之内的购买总数 brand_least_operator_day_count:品牌B最近一次被操作离现在的天数 brand_first_operator_day_count:品牌B第一次被操作离现在的天数 brand_hot_level :品牌B的热门度(点击数*0.1+购买数*5+购物车数+收藏数) user_count_buy_brand_morethan_2week :购买品牌B超过两周的用户数 user_count_buy_brand_morethan_3week :购买品牌B超过三周的用户数 user_count_buy_brand_morethan_4week :购买品牌B超过四周的用户数 user_count_buy_brand_equal_1week :购买品牌B为1周的用户数 user_count_buy_brand_equal_2week :购买品牌B为2周的用户数 user_count_buy_brand_equal_3week :购买品牌B为3周的用户数 user_count_buy_brand_equal_4week :购买品牌B为4周的用户数 brand_hot_ave_level :品牌B的热门度(点击数*0.1+购买数*5+购物车数+收藏数)/(品牌B第一次被操作和最后一次被操作的时间间隔天数)
利用天池平台的分布式计算,详细资料见天池平台资料分享。我们组写了三个MapReduce程序,Map阶段分别根据userbrandgroup、usergroup、brandgroup进行拆分,Reduce阶段分别计算出三类特征的数值,后面就是简单的多张特征表的合并操作,线下的训练和预测的特征总表的MR处理是一样的,只有输入时间不一样,如下所示:
<pre name="code" class="sql"><pre name="code" class="sql">//线下训练特征总表 create resource jar C:\TOOLS\mapReduce-getCharacter.jar -f jar --resources mapReduce-getCharacter.jar --classpath C:\TOOLS\mapReduce-getCharacter.jar com.mr.userbrandgroup.MyDriver LR_Offline_Train_Table LR_Offline_Train_Feature_1_Table '04-15' '07-02' '1'; create resource jar C:\TOOLS\mapReduce-getCharacter.jar -f jar --resources mapReduce-getCharacter.jar --classpath C:\TOOLS\mapReduce-getCharacter.jar com.mr.usergroup.MyDriver LR_Offline_Train_Table LR_Offline_Train_Feature_2_Table '04-15' '07-02'; create resource jar C:\TOOLS\mapReduce-getCharacter.jar -f jar --resources mapReduce-getCharacter.jar --classpath C:\TOOLS\mapReduce-getCharacter.jar com.mr.brandgroup.MyDriver LR_Offline_Train_Table LR_Offline_Train_Feature_3_Table '04-15' '07-02'; //线下预测特征总表 create resource jar C:\TOOLS\mapReduce-getCharacter.jar -f jar --resources mapReduce-getCharacter.jar --classpath C:\TOOLS\mapReduce-getCharacter.jar com.mr.userbrandgroup.MyDriver LR_Offline_Validate_Table LR_Offline_Validate_Feature_1_Table '04-15' '07-21'; create resource jar C:\TOOLS\mapReduce-getCharacter.jar -f jar --resources mapReduce-getCharacter.jar --classpath C:\TOOLS\mapReduce-getCharacter.jar com.mr.usergroup.MyDriver LR_Offline_Validate_Table LR_Offline_Validate_Feature_2_Table '04-15' '07-21'; create resource jar C:\TOOLS\mapReduce-getCharacter.jar -f jar --resources mapReduce-getCharacter.jar --classpath C:\TOOLS\mapReduce-getCharacter.jar com.mr.brandgroup.MyDriver LR_Offline_Validate_Table LR_Offline_Validate_Feature_3_Table '04-15' '07-21';
在进行LR模型的时候,我们根据文本检索里面的对数处理准则,对计算到的特征总表进行了整体对数化处理,之后便是对正负样本进行单独抽样得到一个较小的数据集进行训练,抽样总数为330W,抽样比例为10:1(后面改到8:1有小幅度提高),LR模型由于构建数据集和特征,熟悉MR,所以上手的时间很长,做了一周左右,提交的成绩不好
不断添加和测试新的特征,两三天的时间,成绩就有了起色,之前规则的得分上线被LR打破,停滞的F1终于开始涨了,这段时间由于做的有点疲倦,加的特征不够多,成绩上涨的断断续续,F1上涨到接近5的时候又出现了瓶颈,再怎么添加特征都不怎么涨了:
这段时间,LR的瓶颈让我们放弃了对它的执念,看到竞赛群里火热的讨论着RF,我们决定转投RF。。。
感觉我们组好悲催,别的组都能直接从LR过渡到RF上面来,我们又要重新测试一下特征,不能直接转过来,花了两天的时间,成绩稍微正常了一点,但是离LR最好还是差了一大截啊,怀疑我们的方法哪里出问题了,这段时间又是考试周临近,真真的头疼啊(看到别的组天天都在上升,饥饿游戏,滋味不好受,还是每天抽出两三个小时来做比赛)排错排除了一周左右的时间,成绩上涨到和LR差不多的水平了,当时那个开心啊,呵呵,回味无穷
然后,就正式进入考试周了,比赛的时间压缩到极致,两人都忙于复习,比赛做的比较水了,中途不知道哪里出问题了,提交的成绩创历史之最了。。。商量之后决定,决定暂时不搞了,差不多停了两周左右
考完试也就基本是6月底了,和队友也差不多忙完了,每天空闲时间相对多了起来,决定重操旧业,”享受早上起来看成绩兴奋的那一瞬间“,我们花了两天时间重新排查了一遍程序,决定暂时先不对数据做预处理,利用选好的特征,终于得到了超过LR最好得分的成绩,一举破5,停滞的baseline终于开始上涨啦,(果然是预处理影响了我们的模型型。。。当时猜想是数据清洗的过度了,后来也试过删除一些刷砖用户,但是效果甚微)基本上方法对了之后,我们就不断添加新的特征,这几天基本实现两天一个大提升,特征总数也达到了500多,实际用上的特征从30多个,到了接近70个了。
我们RF训练用的方法基本上是界面的方式实现的,具体做法见之前发的一篇博文阿里大数据比赛sesson2 RF上手篇,成绩上涨到5.66这个水平就不太好上升了,试了两三天效果都不好了,正好碰到群里又在火热的讨论gbrt,对于我们来说又是一个新的模型,我们商量之后,没有犹豫,立马决定转到GBRT,继续马拉松。。。
学习了两天的GBRT界面操作(因为一直没注意看BBS的更新资料,导致我们知道7月中旬都一直还在用界面训练预测,耗时耗力。。。),便开始实战了,果不其然,直接RF最好特征转过来,效果又是差的离奇,(奇了怪了,这也太悲催了吧),这两天和哈工大队的大帅交流了下GBRT的使用心得,终于还是步入了正轨,成绩又开始欢快的涨了,涨了。。。
成绩上了5.8之后,上涨的就有点吃力了,不断添加新的特征,不断换数据预处理,经过一周的操作,成绩上涨到了
还是没能上5.9,我们这段时间尝试过RF和GBRT模型融合,添加规则辅助推荐都效果不好,具体的GBRT方法见博文阿里大数据比赛sesson2 GBRT上手篇,20号左右的时候,终于看到了脚本实现的文档。。。再也不用手动训练预测了。。。
24号阿里更新了一批等量的数据,当天晚上,赶在凌晨4点之前,在新数据集上跑完了第一次成绩,当晚的成绩终于破5.9啦
好景不长,接下来的一天,线下在提升,线上却下降了,反思线下特征过拟合了,在讨论组里大家都在议论着提升的问题,我们又重新梳理了特征,再次添加了一批特征,惊喜的发现线下提升了0.06达到了5.39,着实兴奋了一把,果然,第二天成绩怒破6.0,排名稳定在了前50名,激动不已。。。
接下来的几天,我们继续线下调试新特征和试着融合,但是线下效果好,到了线上效果却低于6.02:
最后一天,我们改变了正负样本抽样比例,换到了8:1,线下提升了0.02,线上定格在了6.03:
写博客的一天,再现了四个月来的一路”厮杀“,几个月来就基本没有1点钟之前睡过觉的,虽然辛苦,但是还是觉得收获挺多,感谢阿里提供的这个平台,让我们对大数据不再一无所知,感谢队友朱凌云的陪伴,感谢我们队伍一路走来帮助过我们的哈工大-王帅同学和姚继涛同学,感谢USTC的Cara、Closure、陈朝才和陈诚、李悦、以及宁波大学丁石磊同学,以及一些路见不平拔刀相助的壮士,么么哒O(∩_∩)O~