天池O2O比赛数据分析

时间:2024-04-01 11:52:07

提供用户在2016年1月1日至2016年6月30日之间真实线上线下消费行为,预测用户在2016年7月领取优惠券后15天以内的使用情况。 

一、总体分析

dfoff = pd.read_csv('data/ccf_offline_stage1_train.csv')
dfon = pd.read_csv('data/ccf_online_stage1_train.csv')
dftest = pd.read_csv('data/ccf_offline_stage1_test_revised.csv')

print('有优惠卷,购买商品:%d' % dfoff[(dfoff['Date_received'].notnull()) & (dfoff['Date'].notnull())].shape[0])
print('有优惠卷,未购商品:%d' % dfoff[(dfoff['Date_received'].notnull()) & (dfoff['Date'].isnull())].shape[0])
print('无优惠卷,购买商品:%d' % dfoff[(dfoff['Date_received'].isnull()) & (dfoff['Date'].notnull())].shape[0])
print('无优惠卷,未购商品:%d' % dfoff[(dfoff['Date_received'].isnull()) & (dfoff['Date'].isnull())].shape[0])

结果如下:

有优惠卷,购买商品:75382
有优惠卷,未购商品:977900
无优惠卷,购买商品:701602
无优惠卷,未购商品:0

可见,很多人(701602)购买商品却没有使用优惠券,也有很多人(977900)有优惠券但却没有使用

二、数据集划分:

       预测未来N天的流量(人流,销售等),预测未来N天内的用户-对象对(用户-商品等)的问题等,可以利用滑窗法解决。题目描述为预测未来N天的息,其中N的取值为大于等于1。基本诸如此种问题,题目会给出前X天的详细信息。这样,我们就知道,其完整的数据为 X+N 的形式,其中 N 是需要我们预测的部分,其真实值未知。

       需要在 X 中构造出与 X+N 格式一致的样本,这种情况下,切分X为两个部分,[X-M,M],其中M=N的长度。这样,就拥有了带有标签的数据,其中M是我们线下预测的部分其本质是符合线上的N的部分,而X-M类似于在[X,N]中的X部分。普遍在代码实现时,在[X-M,M]区间中,我们会首先提取M中的真实值Y和唯一标识ID,之后再X-M中不停的统计,最后通过唯一标识ID拼接到这个M中。

       本比赛中,考虑采用滑窗法,将ccf_offline_stage1_train.csv数据如下划分:

训练集1: 将2016年1月1日到4月13日的数据提取特征,利用4月14日的到5月14日的提取label作为训练集1
训练集2: 将2月1日到5月14日的作为数据集提取特征,利用5月15日6月15日的提取label作为训练集2
测试集:   将3月15日到6月30日作为数据集提取特征,再测试7月1日到7月31日的数据

dataset3 = dftest
feature3 = dfoff[((dfoff.date>=20160315)&(dfoff.date<=20160630))|((dfoff.date != dfoff.date )&(dfoff.date_received>=20160315)&(dfoff.date_received<=20160630))]
dataset2 = dfoff[(dfoff.date_received>=20160515)&(dfoff.date_received<=20160615)]
feature2 = dfoff[(dfoff.date>=20160201)&(dfoff.date<=20160514)|((dfoff.date != dfoff.date)&(dfoff.date_received>=20160201)&(dfoff.date_received<=20160514))]
dataset1 = dfoff[(dfoff.date_received>=20160414)&(dfoff.date_received<=20160514)]
feature1 = dfoff[(dfoff.date>=20160101)&(dfoff.date<=20160413)|((dfoff.date != dfoff.date )&(dfoff.date_received>=20160101)&(dfoff.date_received<=20160413))]

三、特征工程

1、其他特征

      这部分特征在训练集1、训练集2和测试集1中提取,即分别在dataset1、dataset2和dataset3中提取,共计8个特征,如下:

this_month_user_receive_all_coupon_count    用户领取的所有优惠券数目

this_month_user_receive_same_coupon_count  用户领取的特定优惠券数目

this_month_user_receive_same_coupon_lastone   特定优惠券是否是用户这个月最新领取的时间

this_month_user_receive_same_coupon_firstone  特定优惠券是否是用户这个月最早领取的时间

this_day_user_receive_all_coupon_count   用户当天领取的优惠券数目

this_day_user_receive_same_coupon_count   用户当天领取的特定优惠券数目

day_gap_before  用户上一次领取的时间间隔

day_gap_after  用户下一次领取的时间间隔

2、商家相关特征

     特征集合中提取,共计9个特征

total_sales  商家做了多少笔生意

sales_use_coupon   商家被核销过的不同优惠券数量

total_coupon  商家发放的优惠券总数

merchant_min_distance  商家被核销优惠券中的最小用户-商家距离

merchant_max_distance  商家被核销优惠券中的最大用户-商家距离

merchant_mean_distance  商家被核销优惠券中的平均用户-商家距离

merchant_median_distance  商家被核销优惠券中的平均用户-商家距离中位数

merchant_coupon_transfer_rate  商家优惠券被领取后核销率

coupon_rate   使用优惠券占商家总的销售笔数

3、用户线下相关的特征

     特征集合中提取,共计13个特征

count_merchant  用户购买的商家个数

user_min_distance   用户使用优惠券购买商品距离商店的最小距离

user_max_distance  用户使用优惠券购买商品距离商店的最大距离

user_mean_distance  用户使用优惠券购买商品距离商店的平均距离

user_median_distance   用户使用优惠券购买商品距离商店的中位数距离

buy_use_coupon   用户使用优惠券购买的次数

buy_total  用户购买的次数

coupon_received  用户接收到优惠券的数量

user_date_datereceived_gap  用户使用优惠券消费与领取优惠券的时间间隔

avg_user_date_datereceived_gap   用户使用优惠券的平均时间间隔

min_user_date_datereceived_gap  用户使用优惠券的最小时间间隔

max_user_date_datereceived_gap  用户使用优惠券的最大时间间隔

buy_use_coupon_rate 用户所有购买行为中使用优惠券占的比例

user_coupon_transfer_rate  对于用户来说,接收到的优惠券使用率

4、用户和商户 User & Merchant 交叉特征

      这部分也是特征集合中提取,共计9个特征

user_merchant_buy_tota  每个用户商户对交易统计

user_merchant_received  每个用户商户对发放优惠券的统计

user_merchant_buy_use_coupon  每个用户商户对使用优惠卷的交易行为的统计

user_merchant_any  用户和商户对统计

user_merchant_buy_common  用户和商户对交易不使用优惠券统计

user_merchant_coupon_transfer_rate  使用优惠卷的交易行为占所有用户商户对发放优惠卷的比例

user_merchant_coupon_buy_rate  使用优惠卷的交易行为占所有用户商户对交易行为的比例

user_merchant_rate   每个用户商户对交易行为占所有用户商户对的比例

user_merchant_common_buy_rate     用户和商户对交易不使用优惠券占所有用户商户对交易行为的比例

5、优惠券特征

      这部分特征在训练集1、训练集2和测试集1中提取,即分别在dataset1、dataset2和dataset3中提取,共计8个特征

day_of_week  领取优惠券是一周的第几天

day_of_month  领取优惠券是一月的第几天

days_distance  距离6月30日天数

discount_man   满

discount_jian  减

is_man_jian  是否满减

discount_rate  打折率

coupon_count  

四、训练集和测试集

is_weekend   是否周末

weekday1、weekday2....weekday7 独热编码

label 标签

最后dataset1、dataset2在加上上面9个特征,去掉'merchant_id','day_of_week','date','date_received','coupon_id','coupon_count'后,共计56个字段

dataset3去掉'merchant_id','day_of_week','coupon_count',共计57个字段

五、模型训练

      将训练集1和训练集2合并后,作为训练集

dataset12 = pd.concat([dataset1,dataset2],axis=0)
dataset1_y = dataset1.label
dataset1_x = dataset1.drop(['user_id','label','day_gap_before','day_gap_after'],axis=1)  
dataset2_y = dataset2.label
dataset2_x = dataset2.drop(['user_id','label','day_gap_before','day_gap_after'],axis=1)
dataset12_y = dataset12.label
dataset12_x = dataset12.drop(['user_id','label','day_gap_before','day_gap_after'],axis=1)
dataset3_preds = dataset3[['user_id','coupon_id','date_received']]
dataset3_x = dataset3.drop(['user_id','coupon_id','date_received','day_gap_before','day_gap_after'],axis=1)

     去掉部分特征后,最终训练的特征共计52个,

predictors = dataset12_x.columns

trainSub, validSub = train_test_split(dataset12, test_size = 0.2, stratify = dataset12['label'], random_state=100)

import lightgbm as lgb 
from sklearn.model_selection import KFold, train_test_split
model = lgb.LGBMClassifier(
                    learning_rate = 0.01,
                    boosting_type = 'gbdt',
                    objective = 'binary',
                    metric = 'logloss',
                    max_depth = 5,
                    sub_feature = 0.7,
                    num_leaves = 3,
                    colsample_bytree = 0.7,
                    n_estimators = 5000,
                    early_stop = 50,
                    verbose = -1)

model.fit(trainSub[predictors], trainSub['label'])

y_valid_pred = model.predict_proba(validSub[predictors])
validSub1 = validSub.copy()
validSub1['pred_prob'] = y_valid_pred[:, 1]
validSub1.head()

#测试

y_test_pred = model.predict_proba(dataset3[predictors])
submit = dataset3_preds.copy()
submit.to_csv('submit8.csv', index=False, header=False)
submit.head()

天池O2O比赛数据分析