o2o优惠券使用预测--天池新人实战赛--Baseline代码及说明 ( 35 )

版权声明:博主是初学者,博文可能会有错误,望批评指正!转载请注明本博客地址,谢谢! https://blog.csdn.net/LieQueov/article/details/82781312

一、代码说明

1.代码为一个baseline代码,处理特征和使用的模型都非常简单,将会在后期完善。

2.代码中只使用offline数据

3.只是简单对日期和优惠券特征进行了简单的处理。

4.代码中使用逻辑回归进行分类

二、python源码

# -*- coding: utf-8 -*-
"""Created on Tue Sep 18 10:13:08 2018
@author: HGaviN
"""
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn import metrics
#写处理折扣率的函数
#获取折扣类型
def Discount_type(Dis_Rat):
    Dis_Rat = str(Dis_Rat)
    if 'nan' in Dis_Rat:
        return np.nan
    elif ':' in Dis_Rat:
        return 1 #类型1为满减
    else:
        return 0 #类型2为直接折扣
    
#将满减类型的优惠券转化为折扣率
def Discount_convert(Dis_Rat) : 
    if ':' in str(Dis_Rat):
        rate = Dis_Rat.split(':')
        return (float(rate[0])-float(rate[1]))/float(rate[0])
    else :
        return Dis_Rat
#将满减优惠券的满和减分解出来
def Discount_m (Dis_Rat) :
    if ':' in str(Dis_Rat) :
        rate = Dis_Rat.split(':')
        return float(rate[0])
    else :
        return 0
    
def Discout_j (Dis_Rat) :  
    if ':' in str(Dis_Rat) :
        rate = Dis_Rat.split(':')
        return float(rate[1])
    else :
        return 0 #这里面减少的设置,可能会折扣率类型的不太公平  

#日期处理函数   
#转化成标准日期函数      
def date_convet(Date):
    if 'nan' in str(Date):
        return np.nan
    else:
        datestr = str(int(Date))
        return pd.to_datetime(datestr) 
#读取数据
train_off = pd.read_csv('./ccf_offline_stage1_train.csv') 
test_off = pd.read_csv('./ccf_offline_stage1_test_revised.csv')
data = train_off.append(test_off,sort = False)
data = data.reset_index(drop=True)
del train_off
#将两个数据合成同一个,进行相同的特征工程
#特征工程
#对优惠券特征进行处理
data.loc[:,'Discount_type'] = data['Discount_rate'].apply(Discount_type)
data.loc[:,'Discount_rate_new'] = data['Discount_rate'].apply(Discount_convert)
data.loc[:,'Discount_m'] = data['Discount_rate'].apply(Discount_m)
data.loc[:,'Discout_j'] = data['Discount_rate'].apply(Discout_j)
#对时间类特征进行简单处理
#将优惠券领取的月份,星期几,和一年中的星期几
data.loc[:,'date_received_new'] = data['Date_received'].apply(date_convet)
data.loc[:,'date_received_month'] = data['date_received_new'].dt.month
data.loc[:,'date_received_dom'] = data['date_received_new'].dt.day
data.loc[:,'date_received_doy'] = data['date_received_new'].dt.dayofyear
data.loc[:,'date_received_dow'] = data['date_received_new'].dt.dayofweek

# 将Distance中的确实信息,统一填充为-1
data['Distance'] = data['Distance'].fillna(-1).astype(int)
# 对日期型数据进行one-hot编码
month_onehot = pd.get_dummies(data[['date_received_month']].astype(str))
dom_onehot = pd.get_dummies(data[['date_received_dom']].astype(str))
dow_onehot = pd.get_dummies(data[['date_received_dow']].astype(str))
doy_onehot = pd.get_dummies(data[['date_received_doy']].astype(str))
date_onehot = pd.concat([month_onehot,dom_onehot,dow_onehot,doy_onehot],axis = 1)
data_feature = pd.concat([data,date_onehot],axis = 1)
data_feature = data_feature.drop(['date_received_month','date_received_dom','date_received_dow','date_received_doy'],axis = 1)
del month_onehot,dom_onehot,dow_onehot,doy_onehot,date_onehot
#数据划分(实际上,应该在第一步的时候,对数据进行清洗)
#1.将训练集和测试集分解出来
train_off = data_feature[0:1754884]
test = data_feature[1754884:1868524]
del data 
#1.取出训练集的正样本和负样本
train_off_pos = train_off.loc[~train_off['Date'].astype(str).str.contains('nan') & ~ train_off['Coupon_id'].astype(str).str.contains('nan')]
train_off_neg = train_off.loc[train_off['Date'].astype(str).str.contains('nan') & ~ train_off['Coupon_id'].astype(str).str.contains('nan')]
#2.选择正负样本中需要的特征,并打上标签
train_off_pos = train_off_pos.reset_index(drop=True)
train_off_pos['label'] = 1
train_off_neg = train_off_neg.reset_index(drop=True)
#对负样本进行随机采样
train_off_neg = train_off_neg.sample(n=train_off_pos.shape[0])
train_off_neg['label'] = 0
train = train_off_pos.append(train_off_neg)
del train_off_neg,train_off_pos
train_feature = train.drop(['User_id','Merchant_id','Coupon_id','Discount_rate','Date_received','date_received_new','label','Date'],axis = 1)
train_label = train[['label']]
train_label=train_label.values.reshape(train_label.values.shape[0])
test_feature = test.drop(['User_id','Merchant_id','Coupon_id','Discount_rate','Date_received','date_received_new','Date'],axis = 1)

#模型训练 构建一个逻辑回归模型,没有进行交叉验证
LR = LogisticRegression(penalty='l2',C=1.0)
LR.fit(train_feature.values,train_label)
preL = LR.predict(train_feature.values)
metrics.accuracy_score(train_label,preL)

#测试数据
test_label = LR.predict_proba(test_feature.values)
result = test_off[['User_id','Coupon_id','Date_received']]
result = pd.concat([result,pd.DataFrame({'Probability':test_label[:,1]})],axis=1)
result.to_csv('submit1.csv',index = False, header = False)

三、提交结果

auc为0.54,相对较小,有很大的提升空间。

四、改进空间

1、特征方面:

            (1) 特征清洗:没有观察特征的情况,特征是否存在不合理的情况。

            (2) 缺失值填充:缺失值填充没有依据,特征大小并没有缩放。

            (3) 数据采样:生成的正负样本不太合适,预测的是15天内使用优惠券的概率,而现在代码中的判断为只要使用优惠券就为正样本。并且生成的正样本的数量远远少于负样本的数量。需要进行适当的过采样和欠采样。

            (4)特征工程:需要结合online数据,进行适当的组合特征,并且对日期特征还要进行处理,比如生成领取优惠券15天内是否有假日/促销日等特征。

             (5)在生成足够多的特征后,再进行特征选择。

2、模型方面:

         (1)没有进行模型融合。

         (2) 没有通过交叉验证+网格搜索的方式对模型进行调优。

         (3) 评估函数没有使用auc,没有进行离线评价。

五、一些心得

        (1)模型融合不一定带来性能的提升,建议先处理特征,再进行模型的调优

        (2)在进行特征工程时,要在对特征进行初步分析的情况下(比如生成组合特征,所有数据的值都一样,这样没有区分度),再进行,以节约时间。

猜你喜欢

转载自blog.csdn.net/LieQueov/article/details/82781312
35