天池o2o优惠券使用预测(入门)
一、前言
近期学习了一下天池中o2o优惠券使用预测的学习赛,主要任务是通过分析建模,精准预测用户是否会在规定时间内使用相应优惠券。这次的参与主要是学习为主,牛刀小试。
二、解决方案
- 数据分析:对于给定的数据集进行分析处理。
- 特征工程:挖掘出更具代表性的特征。
- 模型建立:使用随机梯度下降法进行建模(SGDClassifier)
三、功能实现
1、导入相关的库
#导入常规用的库
import numpy as np
import pandas as pd
from datetime import date #日期
#数据集划分相关库
from sklearn.model_selection import KFold, train_test_split,StratifiedKFold, cross_val_score,GridSearchCV
#管道输入函数,自定义模型
from sklearn.pipeline import Pipeline
#SGD随机梯度下降分类器以及逻辑回归
from sklearn.linear_model import SGDClassifier, LogisticRegression
#数据预处理库,归一化处理
from sklearn.preprocessing import StandardScaler
#评价指标
from sklearn.metrics import log_loss, roc_auc_score, auc, roc_curve
from sklearn.preprocessing import MinMaxScaler
%matplotlib inline
%config InlineBackend.figure_format = 'retina' #高清图嵌入
2、导入数据集并观察分析
dfoff = pd.read_csv(r'E:\天池020优惠券使用预测\Code\data\ccf_offline_stage1_train.csv',keep_default_na=False).iloc[:,0:7]
dfon = pd.read_csv(r'E:\天池020优惠券使用预测\Code\data\ccf_online_stage1_train.csv',keep_default_na=False)
dftest = pd.read_csv(r'E:\天池020优惠券使用预测\Code\data\ccf_offline_stage1_test_revised.csv',keep_default_na=False
观察dfoff的前五行,查看数据集情况。
分析结论:
print('有优惠券,购买商品: %d'% dfoff.loc[(dfoff['Date_received']!='null')&(dfoff['Date']!='null')].shape[0])
print('有优惠券,未购买商品: %d'% dfoff.loc[(dfoff['Date_received']!='null')&(dfoff['Date']=='null')].shape[0])
print('无优惠券,购买商品: %d'% dfoff.loc[(dfoff['Date_received']=='null')&(dfoff['Date']!='null')].shape[0])
print('无优惠券,未购买商品: %d'% dfoff.loc[(dfoff['Date_received']=='null')&(dfoff['Date']=='null')].shape[0])
可以看出无优惠券但是也购买的商品的客户还是很多的,为了更加精准的把优惠券发放到会购买商品的客户手里,我们需要建立预测模型进行预测。
3、打折率(Discount_rate)特征处理
从上述显示的数据集来看,除了ID外先看第一个有用的特征,打折率,我们都知道如果商品打折得多购买的欲望就更强,因此我们应该好好分析一下打折率。
首先对打折率这个特征的值进行统计观察:
dfoff['Discount_rate'].unique()
发现打折率的值主要分为以下4中情况:
(1)没有打折,null值
(2)0~1范围,表示直接打折
(3)满多少减多少
(4)干扰值
我们可以先把干扰值所在处的样本去除,干扰值为’2418’和’7751’
#除去干扰值所在样本
dfoff = dfoff[(dfoff['Discount_rate']!='2418') & (dfoff['Discount_rate']!='7751') ]
dfoff['Discount_rate'].value_counts()
数据预处理完都,对打折率特征进行分析处理:
#区分打折函数,没打折返回null,满减返回1,直接打折返回0
def getDiscountType(row):if row == 'null':return 'null'elif ':' in row:return 1else:return 0#折扣率转化,没打折的原价返回1,满减的计算出打折率返回,直接打折的返回原值
def convertRate(row):if row == 'null':return 1.0elif ':' in row:rows = row.split(':')return 1.0 - float(rows[1])/float(rows[0])else:return row#满多少特征提取
def getDiscountMan(row):if ':' in row:rows = row.split(':')return rows[0]else:return 0#减多少特征提取
def getDiscountJian(row):if ':' in row:rows = row.split(':')return rows[1]else:return 0#数据预处理,调用以上函数,进行封装
def processData(df):df['discount_type'] = df['Discount_rate'].apply(getDiscountType)df['discount_rate'] = df['Discount_rate'].apply(convertRate)df['discount_man'] = df['Discount_rate'].apply(getDiscountMan)df['discount_jian'] = df['Discount_rate'].apply(getDiscountJian)return df
以上打折函数编写完毕后,输入要分析处理的数据集进行打折率特征处理:
dfoff = processData(dfoff)
dftest = processData(dftest)
dfoff.head()
4、距离(Distance)特征处理
#观察Distance的类型
dfoff['Distance'].unique()
对空值进行处理,把空值转换为-1
dfoff['Distance'] = dfoff['Distance'].replace('null', -1).astype(int)
dftest['Distance'] = dftest['Distance'].replace('null', -1).astype(int)
5、领券日期(Date_received)
dfoff['Date_received'].unique()
对领券日期进行类型划分以及独热编码处理:
weekday : {null, 1, 2, 3, 4, 5, 6, 7}
weekday_type : {1, 0}(周六和周日为1,其他为0)
Weekday_1 : {1, 0, 0, 0, 0, 0, 0}
Weekday_2 : {0, 1, 0, 0, 0, 0, 0}
Weekday_3 : {0, 0, 1, 0, 0, 0, 0}
Weekday_4 : {0, 0, 0, 1, 0, 0, 0}
Weekday_5 : {0, 0, 0, 0, 1, 0, 0}
Weekday_6 : {0, 0, 0, 0, 0, 1, 0}
Weekday_7 : {0, 0, 0, 0, 0, 0, 1}
(1)提取星期特征
def getWeekday(row):if row == 'null':return rowelse:return date(int(row[0:4]),int(row[4:6]),int(row[6:8])).weekday() + 1dfoff['weekday'] = dfoff['Date_received'].astype(str).apply( getWeekday)
dftest['weekday'] = dftest['Date_received'].astype(str).apply( getWeekday)
dfoff.head()
(2)日期类型特征提取
#日期类型,周末返回1,工作日返回0
dfoff['weekday_type'] = dfoff['weekday'].apply(lambda x: 1 if x in [6,7] else 0)
dftest['weekday_type'] = dftest['weekday'].apply(lambda x: 1 if x in [6,7] else 0)
#回复索引
dfoff.index = range(dfoff.shape[0])
dftest.index = range(dftest.shape[0])
(3)把星期特征进行独热编码
weekdaycols = ['weekday_' + str(i) for i in range(1,8)]
tmpdf = pd.get_dummies(dfoff['weekday'].replace('null', np.nan))
tmpdf.columns = weekdaycols
dfoff[weekdaycols] = tmpdf
tmpdf = pd.get_dummies(dftest['weekday'].replace('null', np.nan))
tmpdf.columns = weekdaycols
dftest[weekdaycols] = tmpdf
6、标签提取
标签主要分为三种情况:
Date_received == ‘null’:表示没有领到优惠券,无需考虑,y = -1
(Date_received != ‘null’) & (Date != ‘null’) & (Date - Date_received <= 15):表示领取优惠券且在15天内使用,即正样本,y = 1
(Date_received != ‘null’) & ((Date == ‘null’) | (Date - Date_received > 15)):表示领取优惠券未在在15天内使用,即负样本,y = 0
pd.options.display.max_columns = None #解除列限制
#定义标签备注函数
def label(row):if row['Date_received'] == 'null':return -1elif row['Date'] != 'null':td = pd.to_datetime(row['Date'],format='%Y%m%d') - pd.to_datetime(row['Date_received'],format='%Y%m%d')if td <= pd.Timedelta(15,'D'):return 1return 0
dfoff['label'] = dfoff.apply(label, axis=1)
7、建立线性模型 SGDClassifier
使用上面提取的14个特征,进行模型建立。
训练集:20160101-20160515;验证集:20160516-20160615。
用线性模型 SGDClassifier
使用上面提取的14个特征。
训练集:20160101-20160515;验证集:20160516-20160615。
用线性模型 SGDClassifier
(1)数据集划分
df = dfoff[dfoff['label']!=-1].copy()
train = df[df['Date_received'] < '20160516'].copy()
valid = df[df['Date_received'] >= '20160516'].copy()
(2)观察是否具有样本不平衡
#观察是否具有样本不平衡问题
train['label'].value_counts()
(3)选定需要分析的特征
original_feature = ['discount_rate','discount_type','discount_man', 'discount_jian','Distance', 'weekday_type'] + weekdaycols
original_feature
(4)模型建立
def check_model(data,predictors):classifier =lambda: SGDClassifier(loss='log'#逻辑损失,penalty='elasticnet',fit_intercept=True,max_iter=100,shuffle=True,n_jobs=1,class_weight=None)# 管道机制使得参数集在新数据集(比如测试集)上的重复使用,管道机制实现了对全部步骤的流式化封装和管理。model = Pipeline(steps=[('ss', StandardScaler()), # transformer('en', classifier()) # estimator])parameters = {'en__alpha': [ 0.001, 0.01, 0.1],'en__l1_ratio': [ 0.001, 0.01, 0.1]}# StratifiedKFold用法类似Kfold,但是他是分层采样,确保训练集,测试集中各类别样本的比例与原始数据集中相同。folder = StratifiedKFold(n_splits=3, shuffle=True)grid_search = GridSearchCV(model, parameters, cv=folder, n_jobs=-1, # -1 means using all processorsverbose=1)grid_search = grid_search.fit(data[predictors], data['label'])return grid_search
模型训练:
predictors = original_feature
model = check_model(train, predictors)
8、验证
对验证集中每种优惠券预测的结果计算 AUC,再对所有优惠券的 AUC 求平均。计算 AUC 的时候,如果 label 只有一类,就直接跳过,因为 AUC 无法计算。
#第一列分类为0的概率,第二类分类为1的概率
y_valid_pred = model.predict_proba(valid[predictors])
y_valid_pred
```![在这里插入图片描述](https://img-blog.csdnimg.cn/20200423102953840.png)
提取正类样本
```csharp
valid1 = valid.copy()
valid1['pred_prob'] = y_valid_pred[:,1]
valid1.head()
AUC面积计算
# 以优惠券种类数进行分局,计算出每种优惠券的AUC,并最后计算所有AUC的平均值
vg = valid1.groupby(['Coupon_id'])
aucs = []
for i in vg:tmpdf = i[1] if len(tmpdf['label'].unique()) != 2:continuefpr, tpr, thresholds = roc_curve(tmpdf['label'], tmpdf['pred_prob'], pos_label=1)aucs.append(auc(fpr, tpr))
print(np.average(aucs))
9、测试
使用测试进行测试,并把结果保存为天池比赛中的结果形式
y_test_pred = model.predict_proba(dftest[predictors])
dftest1 = dftest[['User_id','Coupon_id','Date_received']].copy()
dftest1['Probability'] = y_test_pred[:,1]
dftest1.to_csv(r'E:\天池020优惠券使用预测\Code\data\submit1.csv',index=False, header=False)
dftest1.head(5)
10、导入及保存模型
import os
import pickle
if not os.path.isfile('1_model.pkl'):with open(r'E:\天池020优惠券使用预测\Code\1_model.pkl', 'wb') as f:pickle.dump(model, f)
else:with open(r'E:\天池020优惠券使用预测\Code\1_model.pkl', 'rb') as f:model = pickle.load(f)
最后,把结果文档提交到天池中,得到成绩:
四、总结
从成绩来看效果欠佳,但笔者是本着学习的心态进行参与,后续会在这个基础上尝试使用其他一些更加出色的模型比如:XGboost、随机森林等模型进行尝试。
天池o2o优惠券使用预测(入门)相关推荐
- 天池 O2O 优惠券使用预测思路解析与代码实战
个人网站:redstonewill.com 前阵子因为机器学习训练营的任务安排,需要打一场 AI 比赛.然后就了解到最近热度很高且非常适合新人入门的一场比赛:天池新人实战赛o2o优惠券使用预测.今天, ...
- 【机器学习】天池O2O优惠券使用预测_系统性总结与心得
Preface:上半年参加天池的O2O优惠券预测赛排名第二,同时参加了学校数据仓库老师的课程改革建设团队,于是把参赛经验总结成文,准备分享给该课程的学弟学妹.现在我把总结的参赛教程文章也发到CSDN上 ...
- 天池O2O优惠券使用预测
参考文献: 题目简介: https://tianchi.aliyun.com/getStart/information.htm?raceId=231593 https://blog.csdn.net/ ...
- 天池比赛:o2o优惠券使用预测
一.比赛背景 O2O:全称Online To Offline,线上线下电子商务,是把线上的消费者带到现实的商店中去:在线支付线下商品.服务,再到线下去享受服务.通过打折(例如团购).提供信息.服务(例 ...
- O2O优惠券使用预测项目总结
O2O优惠券使用预测笔记 前言 项目介绍 数据 评价方式 赛题分析 基本思路 数据集划分 特征工程 模型选取 过程及代码 导入python库 导入与划分数据集 特征工程 模型训练与调参 预测测试集 总 ...
- Sklearn:天池新人实战赛o2o优惠券使用预测 part1
日萌社 人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新) 阿里云官网:天池新人实战赛o2o优惠券使用预测 数据集下载链接 ...
- Sklearn:天池新人实战赛o2o优惠券使用预测 part2
日萌社 人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新) 阿里云官网:天池新人实战赛o2o优惠券使用预测 数据集下载链接 ...
- 【天池】优惠券使用预测
代码:mirrors / wepe / o2o-coupon-usage-forecast · GitCode blog:生活大实惠:O2O优惠券使用预测_Julyaaaa的博客-CSDN博客 比赛网 ...
- W12 - 999、O2O优惠券使用预测
初学耗时:999h 注:CSDN手机端暂不支持章节内链跳转,但外链可用,更好体验还请上电脑端. 『 因为要去见那个不一般的人,所以我就不能是一般人.』 W99.阿里大学征服路 - W系列总纲 ...
最新文章
- docker mysql容器启动不_Mysql容器启动失败-解决方案
- Oracle笔记(十三) 视图、同义词、索引
- 修改input file默认样式
- 路由器上不了网?PPPoE协议了解一下
- time库python_Python的time库的一些简单函数以及用法
- Drools 7.4.1.Final参考手册(六) 用户手册
- Linux最常用的基础命令 下篇
- Ubuntu安装摄像头软件GTK_UVC_Viewer
- 3h精通OpenCV(二)-基本功能
- 为ScrollView增加圆角的三种方式,及自定义属性【在Linearlayout中新增ScrollView支持滚动 后续】...
- 面试:Spring Boot的优缺点
- 《Redis系列第五篇、hset与hget的使用|CSDN创作打卡》
- 个人支付免费开通支付宝付款功能(免费签约)支付宝当面付开通集成到网站教程
- sql server 2000 各版本的区别
- ns手柄pc驱动_颜值、功能、手感同步在线 北通宙斯机械游戏手柄体验
- 【腾讯Bugly干货分享】从0到1打造直播 App
- MySQL 序号(排序)函数:row_number() 、rank() 、 dense_rank()、ntile()
- 网购使用的计算机网络技术,浅议计算机网络技术的应用与发展
- 图解next和hasnext
- 计算机没网络本地连接接下来,电脑本地连接没有了网络连接的本地连接不见的解决方法...