2017京东金融信贷需求预测 赛题总结

(由于平台限制,公式无法正常显示,更好排版请访问我的博客:https://tianle.me/2017/12/12/jd/
项目源代码:https://github.com/zhangtianle/jd

赛题回顾

京东金融提供8到11月的用户借款信息,订单购买信息,页面点击信息以及用户个人和贷款的初始额度信息;要求预测12月每个用户的贷款信息。评价方式采用RMSE函数:
$$RMSE = \sqrt {\frac{1}{n}\sum\nolimits_{i = 1}^n {{{({y_i} - {{\hat y}_i})}^2}} } $$
其中yi真实值,y_hati为预测值,n为用户总数。
数据下载,百度网盘 密码:2lk3
---- 20171219更新 ----

浪教授

  1. 以30天划分训练集,按30天为周期对齐;
  2. 滑动窗口特征,等差 每 7 天 10 天 等;
  3. 让预测月份的均值等于前几个月的均值(比赛前期);
  4. 强特征:激活日期、loan time、可贷款金额、 pid param组合前20个 one-hot
  5. 模型融合,加权平均

第17名代码
https://github.com/klyan/JDD_Loan_Forecasting

比赛结果

A榜50,B榜48
A榜50,B榜48

A榜

B榜

解决方案

  1. 数据分析
  2. 区间划分
  3. 特征提取
  4. 模型分析
  5. 模型调参
  6. 模型融合

数据分析

在本次比赛中,数据分析比较少,仅仅是用 Jupyter Notebook 简单的画了几个图,没有针对数据情况进行特定的特征提取,基本上是想到什么特征就用什么特征,然后 总和、平均、最大、最小、方差 这几个来一套。这是本次比赛中不足的地方。
赛题中对金额字段进行了加密,但是在竞赛群里,立刻就有大佬给出了加密({% raw %}$y = {\log _5}(x + 1)${% endraw %})和脱敏({% raw %}$y = {5^x} + 1${% endraw %})方法,我们直接使用该方法,效果提升非常明显。

区间划分

采用传统的划窗法对数据划分,注意:在划分数据时,一定不能出现数据穿越,即 训练的数据集中用到预测的数据 (如:要预测11月的贷款数据,则在训练数据中不能包含11月的数据信息) 否则会造成线下CV(交叉验证)效果非常好,但是线上糟糕。
本次比赛的划分方式我们尝试了两种方案:

  • 方案一:
0 特征区间(feature) 预测区间(llabel)
训练集 2016-08-03到2016-10-31 2016-11-01到2016-11-30
测试集 2016-08-03到2016-11-30 2016-12-01到2016-12-31
  • 方案二:
    将测试集中的8到11月改成9到11月,即
0 特征区间(feature) 预测区间(llabel)
训练集 2016-08-03到2016-10-31 2016-11-01到2016-11-30
测试集 2016-09-01到2016-11-30 2016-12-01到2016-12-31

在实际测试中我们发现,本次比赛,在相同的特征提取方式下,方案一的结果优于方案二,因此采用方案一。

特征提取

这就比较多了。。。。
参数说明:
start_month 划分区间的起始月份
end_month 划分区间的结束月份
NUM 结束月份 - 起始月份 + 1,即 期间经过了NUM个月

user用户信息表

特征名 特征含义
delta_time 结束时间 - 激活时间 (天)
start_delta_time 起始时间 - 激活时间 (天)
age,sex,limit 年龄,性别,初始额度 one-hot编码

click点击信息表

这个表貌似没什么用,也不知道这里面具体参数是什么含义,所以直接one-hot编码

特征名 特征含义
uid,param 点击页面,点击参数 one-hot编码

loan贷款信息表

特征名 特征含义
remain_days 到下个月的天数 (平均、方差、最大、最小) datetime(2016, end_month+ 1, 1) - parse(x)
pass_days 开始月的天数过去的天数 (平均、方差、最大、最小) parse(x) - dt.datetime(2016, start_month, 1)
over 计划时间是否超出时间
average_loan 平均每月贷款
loan_month 区间内贷款额(最大、最小、方差)
average_pay 每月月供(平均、最小、最大)
remain_loan 历史贷款总额
remain_pay 累计月供
current_loan_sum 当月月供(总和、最大、最小、平均、方差)
current_pay 当月贷款总额(总和、最大、最小、平均、方差)
pay_each 每一次月供(最大、最小、平均)
loan_each 每一贷款(最大、最小、平均)
average_plannum 平均贷款还款周期

order订单信息表

参数说明:
per_price:用户购买单价
price_sum:购买总和
discount_ratio:优惠率

特征名 特征含义
price_sum_mean 每次购物的平均价格
num_order 每月购买次数(最大、最小、平均、方差)
price_each 每个用户每次消费(最大、最小、平均、方差)
price 每个用户购物价格(最大、最小、平均、方差)
real_price 每个用户购物折扣后总价(最大、最小、平均、方差)
average_discount 平均折扣
qty_each 每个用户每次购买(最大、最小、平均、方差)
discount_price_ration 历史折扣力度(平均、方差)
no_free_discount_ratio 每月非免费平均总价格/每月非免费平均折扣后的总价/每月非免费平均折扣力度/每月非免费平均折扣(平均、方差)
current_real_price 每个用户当月的购买物品总价格和(平均、方差)
current_price 当月平均单价(平均、方差)
current_no_freeprice 当月非免费平均单价(平均、方差)
current_discount 当月每次平均折扣(平均、方差)
current_discount_ratio 每次折扣力度(平均、方差)

order_loan 订单-贷款交叉信息

特征名 特征含义
loan_order_ratio 贷款总额 / 购买总额
diff_order_loan 购买总额 - 贷款总额

user_order 用户-订单交叉信息

特征名 特征含义
diff_loan 贷款总额和初始的差

模型分析

一看题目,咋们就很明显的看出这是一个回归问题,那么我们就先选用回归的各种模型来尝试,比如 GBDT、XGB、LR、 Ridge。
随后,我们通过分析数据发现,有相当大的一部分用户没有发生贷款行为,那么是否可以尝试采用先分类再回归呢?分为用户是否会贷款,如果否,直接将贷款值设为0;如果是,那么再用回归模型对用户的贷款行为预测。但是实际情况是,我们的分类模型得到的CV结果准确率仅为85%,加上分类再回归,反而导致了总体评分下降。在做了简单的尝试之后,我们便放弃了这个方法,还是直接使用回归模型。

模型调参

在这里,我们安利一个非常棒的 自动 特征处理(归一化、放缩)、模型选择、调参、模型融合的工具 TPOT,它是用遗传算法跑的,所以运行速度非常非常慢。在本次比赛中,我们一百多维的特征,9W多行(用户),TPOT参数设置:迭代25次,种群规模40,跑完一次,得到模型结果需要1-2天的时间。
此外,我们主要尝试了XGB和GBDT模型,最终的结果是GBDT要优于XGB,参数如下:
GBDT:

    X_train, X_test, y_train, y_test = train_test_split(train_X, train_Y, test_size=0.2, random_state=1)

    clf = GradientBoostingRegressor(loss='ls', alpha=0.9,
                                    n_estimators=500,
                                    learning_rate=0.05,
                                    max_depth=8,
                                    subsample=0.8,
                                    max_features=0.6,
                                    min_samples_split=9,
                                    max_leaf_nodes=10)
    clf = clf.fit(X_train, y_train)

XGB:

{'max_depth': 5, 'eta': 0.05, 'silent': 1, 'eval_metric': 'rmse', 'max_leaf_nodes': 5}

模型融合

在这次比赛中,我们采用了Stacking融合方法,理解不深,只是简单尝试了一下:

gbdt = GradientBoostingRegressor(loss='ls', alpha=0.9,
                                         n_estimators=500,
                                         learning_rate=0.05,
                                         max_depth=8,
                                         subsample=0.8,
                                         min_samples_split=9,
                                         max_leaf_nodes=10)
xgb = XGBRegressor(max_depth=5, n_estimators=500, learning_rate=0.05, silent=False)
lr = LinearRegression()
rfg = RandomForestRegressor(bootstrap=False, max_features=0.05, min_samples_leaf=11, min_samples_split=8,n_estimators=100)
svr_rbf = SVR(kernel='rbf')

stregr = StackingRegressor(regressors=[gbdt, xgb, lr, rfg], meta_regressor=svr_rbf)

stregr.fit(X_train, y_train)
stregr.predict(X_train)

但是效果不咋滴。
由于我们用了TPOT这个调参工具,根据它生成的模型,貌似已经加上模型融合,所以我们在这一块没有放上太多的时间。
还有其他几个模型融合方法,比如:blending,加权平均。据师兄介绍,加权平均的融合方法有时候能取得一个非常不错的结果。根据阿里天池O2O比赛第一名的分享,他们就采用了加权的方法O2O-Coupon-Usage-Forecast

总结

初次比赛,还不懂套路,拿到赛题和数据后,我们没有做数据分析,直接巴拉巴拉暴力提取特征,导致很多特征都没有什么实际用处。另外在数据清洗上也没有进行操作,直接选取了全部数据;在一些缺失值,异常值(比如购买金额,贷款金额为负值)操作上,直接进行填零。不知道是否因为这些原因导致结果比较差。另外,在比赛初期,我们新增特征时,对结果有较大提高,特别是一些强特征(GBDT特征重要性排序),但在比赛后期,新增特征后,对结果几乎没有提高,有时甚至下降了。在本次比赛中,没有找到什么骚操作,也没有发掘出某个神奇的东西,对结果有大幅提高。但是,TPOT是个不错的东西,在特征确定的情况下,通过该工具,对模型调整有着突出的效果,缺点是运行速度太慢。过段时间,看看各位大佬的分享,再好好总结总结。

参考资料

如何在 Kaggle 首战中进入前 10%
第一次参加Kaggle拿银总结
[天池竞赛系列]O2O优惠券使用预测复赛第三名思路
O2O第一名【诗人都藏在水底】代码 思路
O2O第十六名代码 思路

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270