阿里大数据竞赛第一名大神github源代码分享(O2O优惠券使用预测)
队伍简介
队伍名 “诗人都藏在水底”,三位队员分别是来自北大的wepon和charles,来自中科大的云泛天音
赛题介绍
本赛题提供用户在2016年1月1日至2016年6月30日之间真实线上线下消费行为,预测用户在2016年7月领取优惠券后15天以内是否核销。评测指标采用AUC,先对每个优惠券单独计算核销预测的AUC值,再对所有优惠券的AUC值求平均作为最终的评价标准。
解决方案
本赛题提供了用户线下消费和优惠券领取核销行为的纪录表,用户线上点击/消费和优惠券领取核销行为的纪录表,记录的时间区间是2016.01.01至2016.06.30,需要预测的是2016年7月份用户领取优惠劵后是否核销。根据这两份数据表,我们首先对数据集进行划分,然后提取了用户相关的特征、商家相关的特征,优惠劵相关的特征,用户与商家之间的交互特征,以及利用本赛题的leakage得到的其它特征(这部分特征在实际业务中是不可能获取到的)。最后训练了XGBoost,GBDT,RandomForest进行模型融合。
数据集划分
可以采用滑窗的方法得到多份训练数据集,特征区间越小,得到的训练数据集越多。以下是一种划分方式:
划取多份训练集,一方面可以增加训练样本,另一方面可以做交叉验证实验,方便调参。
特征工程
赛题提供了online和offline两份数据集,online数据集可以提取到与用户相关的特征,offline数据集可以提取到更加丰富的特征:用户相关的特征,商家相关的特征,优惠劵相关的特征,用户-商家交互特征。
另外需要指出的是,赛题提供的预测集中,包含了同一个用户在整个7月份里的优惠券领取情况,这实际上是一种leakage,比如存在这种情况:某一个用户在7月10日领取了某优惠券,然后在7月12日和7月15日又领取了相同的优惠券,那么7月10日领取的优惠券被核销的可能性就很大了。我们在做特征工程时也注意到了这一点,提取了一些相关的特征。加入这部分特征后,AUC提升了10个百分点,相信大多数队伍都利用了这一leakage,但这些特征在实际业务中是无法获取到的。
字段表
Table 1: 用户线下消费和优惠券领取行为 表名 train_offline_stage2
Field |
Description |
---|---|
User_id |
用户ID |
Merchant_id |
商户ID |
Coupon_id |
优惠券ID:null表示无优惠券消费,此时Discount_rate和Date_received字段无意义 |
Discount_rate |
优惠率:x in [0,1]代表折扣率;x:y表示满x减y。单位是元 |
Distance |
user经常活动的地点离该merchant的最近门店距离是x*500米(如果是连锁店,则取最近的一家门店),xin[0,10];null表示无此信息,0表示低于500米,10表示大于5公里; |
Date_received |
领取优惠券日期 |
Date |
消费日期:如果Date=null & Coupon_id != null,该记录表示领取优惠券但没有使用,即负样本;如果Date!=null & Coupon_id = null,则表示普通消费日期;如果Date!=null & Coupon_id != null,则表示用优惠券消费日期,即正样本; |
Table 2: 用户线上点击/消费和优惠券领取行为 表名 train_online_stage2
Field |
Description |
---|---|
User_id |
用户ID |
Merchant_id |
商户ID |
Action |
0 点击, 1购买,2领取优惠券 |
Coupon_id |
优惠券ID:null表示无优惠券消费,此时Discount_rate和Date_received字段无意义。“fixed”表示该交易是限时低价活动。 |
Discount_rate |
优惠率:x in [0,1]代表折扣率;x:y表示满x减y;“fixed”表示低价限时优惠; |
Date_received |
领取优惠券日期 |
Date |
消费日期:如果Date=null & Coupon_id != null,该记录表示领取优惠券但没有使用;如果Date!=null & Coupon_id = null,则表示普通消费日期;如果Date!=null & Coupon_id != null,则表示用优惠券消费日期; |
Table 3:用户O2O线下优惠券使用预测样本 表名 prediction_stage2
Field |
Description |
---|---|
User_id |
用户ID |
Merchant_id |
商户ID |
Coupon_id |
优惠券ID |
Discount_rate |
优惠率:x in [0,1]代表折扣率;x:y表示满x减y. |
Distance |
user经常活动的地点离该merchant的最近门店距离是x*500米(如果是连锁店,则取最近的一家门店),xin[0,10];null表示无此信息,0表示低于500米,10表示大于5公里; |
Date_received |
领取优惠券日期 |
Table 4:选手提交表名要求统一命名为:o2o_result 字段要求如下表 其中user_id,coupon_id和date_received均来自Table 3,而Probability为预测值
Field |
Description |
---|---|
User_id |
用户ID |
Coupon_id |
优惠券ID |
Date_received |
领取优惠券日期 |
Probability |
15天内用券概率,由参赛选手给出 |
特征提取:
- 用户线下相关的特征
- 用户领取优惠券次数
- 用户获得优惠券但没有消费的次数
- 用户获得优惠券并核销次数
- 用户领取优惠券后进行核销率
- 用户满0
50/50200/200~500 减的优惠券核销率 - 用户核销满0
50/50200/200~500减的优惠券占所有核销优惠券的比重 - 用户核销优惠券的平均/最低/最高消费折率
- 用户核销过优惠券的不同商家数量,及其占所有不同商家的比重
- 用户核销过的不同优惠券数量,及其占所有不同优惠券的比重
- 用户平均核销每个商家多少张优惠券
- 用户核销优惠券中的平均/最大/最小用户-商家距离
- 用户线上相关的特征
- 用户线上操作次数
- 用户线上点击率
- 用户线上购买率
- 用户线上领取率
- 用户线上不消费次数
- 用户线上优惠券核销次数
- 用户线上优惠券核销率
- 用户线下不消费次数占线上线下总的不消费次数的比重
- 用户线下的优惠券核销次数占线上线下总的优惠券核销次数的比重
- 用户线下领取的记录数量占总的记录数量的比重
- 商家相关的特征
- 商家优惠券被领取次数
- 商家优惠券被领取后不核销次数
- 商家优惠券被领取后核销次数
- 商家优惠券被领取后核销率
- 商家优惠券核销的平均/最小/最大消费折率
- 核销商家优惠券的不同用户数量,及其占领取不同的用户比重
- 商家优惠券平均每个用户核销多少张
- 商家被核销过的不同优惠券数量
- 商家被核销过的不同优惠券数量占所有领取过的不同优惠券数量的比重
- 商家平均每种优惠券核销多少张
- 商家被核销优惠券的平均时间率
- 商家被核销优惠券中的平均/最小/最大用户-商家距离
- 用户-商家交互特征
- 用户领取商家的优惠券次数
- 用户领取商家的优惠券后不核销次数
- 用户领取商家的优惠券后核销次数
- 用户领取商家的优惠券后核销率
- 用户对每个商家的不核销次数占用户总的不核销次数的比重
- 用户对每个商家的优惠券核销次数占用户总的核销次数的比重
- 用户对每个商家的不核销次数占商家总的不核销次数的比重
- 用户对每个商家的优惠券核销次数占商家总的核销次数的比重
- 优惠券相关的特征
- 优惠券类型(直接优惠为0, 满减为1)
- 优惠券折率
- 满减优惠券的最低消费
- 历史出现次数
- 历史核销次数
- 历史核销率
- 历史核销时间率
- 领取优惠券是一周的第几天
- 领取优惠券是一月的第几天
- 历史上用户领取该优惠券次数
- 历史上用户消费该优惠券次数
- 历史上用户对该优惠券的核销率
- 其它特征
这部分特征利用了赛题leakage,都是在预测区间提取的。
- 用户领取的所有优惠券数目
- 用户领取的特定优惠券数目
- 用户此次之后/前领取的所有优惠券数目
- 用户此次之后/前领取的特定优惠券数目
- 用户上/下一次领取的时间间隔
- 用户领取特定商家的优惠券数目
- 用户领取的不同商家数目
- 用户当天领取的优惠券数目
- 用户当天领取的特定优惠券数目
- 用户领取的所有优惠券种类数目
- 商家被领取的优惠券数目
- 商家被领取的特定优惠券数目
- 商家被多少不同用户领取的数目
- 商家发行的所有优惠券种类数目
模型设计
基于以上提取到的特征,进行模型设计与融合。
- 单模型 第一赛季只训练了XGBoost单模型提交,连续几周位居排行榜第一位。 第二赛季训练了XGBoost,GBDT,RandomForest三种单模型,其中GBDT表现最好,XGBoost次之,RandomForest相比之下最差。GBDT和XGBoost单模型在第二赛季仍然名列Top3,融合后效果更佳,尝试了以下两种方法:
- 加权融合
得到了单模型的预测结果后,直接将概率预测值进行加权融合,我们简单地用
0.65 * GBDT + 0.35 * XGBoost
就得到了第一的成绩。
- .Net 转战 Android 4.4 日常笔记(5)--新软件Android Studio 0.5.8安装与配置及问题解决
- 第2章 对象激活上下文-对象激活
- .Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化
- .Net 转战 Android 4.4 日常笔记(3)--目录结构分析
- .Net 转战 Android 4.4 日常笔记(2)--HelloWorld入门程序
- 读书笔记(二)对象激活和上下文
- 程序员的噩梦有哪些?除了改需求,还有这些…
- UC Berkeley提出新型分布式执行框架Ray:有望取代Spark
- 卡奇话爬虫使用方法以及下载地址
- flash读取XML 背景自动适应大小
- 记录一个发邮件的cs文件
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(56)-插件---单文件上传与easyui使用fancybox
- xml-rpc(2)-first demo_v2
- xml-rpc(1)-first demo
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【SpringBoot web-2】web项目参数传递
- 筛法求素数
- redis学习(十三)
- 【SpringBoot web-3】web项目统一数据封装与全局异常处理
- 送你 8 张图,好好理解一下。
- 【前端系列-1】ajax与Springboot通信将数据库数据渲染到前端表格
- 【前端系列-2】layui+springboot实现表格增删改查
- 容器技术|Docker三剑客之docker-swarm
- 【前端系列-3】layui表格使用自定义模板templet
- 【前端系列-4】layui表格集成select选择框和switch开关
- 使用docker Registry快速搭建私有镜像仓库(内附干货)
- 【前端系列-5】layui-from swtich使用小结
- Python解析变长结构体
- 如何优雅地在JS中使用枚举定义
- 【Java基础-1】 Java8新特性Stream详解