机器学习 (十六)电商O2O优惠券使用预测-2

版权声明:本文为博主原创文章,未经博主允许不得转载,谢谢尊重每个人的权利。 https://blog.csdn.net/lilongsheng1125/article/details/82875646

介绍

       这篇文章是想继续总结一遍优惠券预测,写写感受并进行一个记录总结,零零散散以作为记录整理之用。

本篇是选了三点本人觉得项目中重要的写了一下,其它内容暂时略过

  • 第一部分:数据清洗数据分析代码基本功
  • 第二部分:特征理解和选择
  • 第三部分:模型选择和调休

数据分析利器-python

       在用python进行数据分析时候,确实发现其有很多方便之处,其强大的函数处理功能,正看在《利用python进行数据分析》这本书发现还是不错的,简单内容如下:

在这里插入图片描述

在这里插入图片描述
笔记:

  • copy
    用在了提取特征地方,复制一份数据单独处理,不影响以前的,默认深复制
data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'],
        'year': [2000, 2001, 2002, 2001, 2002, 2003],
        'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
frame = pd.DataFrame(data)
print(frame)
# 深复制 修改不影响原对象
data_deep_copy = frame.copy()

data_deep_copy.iloc[1] = 2018
print(data_deep_copy)
print(frame)

# 浅复制  修改影响原对象
data_shallow_copy = frame.copy(deep = False)
data_shallow_copy.iloc[1] = 2019
print(data_shallow_copy)
print(frame)

-梳理
分组
在提取用户特征时,根据User_id进行分组,得到分组对象,然后可以再分组对象上进行各种统计操作。

# 用户 User 特征
u = fdf[['User_id']].copy().drop_duplicates()

# u_coupon_count : num of coupon received by user
u1 = fdf[fdf['Date_received'] != -10][['User_id']].copy()
# 每个用户领取优惠券的数量
u8 = utmp.groupby(['User_id'], as_index = False).median()
u8.rename(columns = {'distance':'u_median_distance'}, inplace = True)
u8.head(2)

  • fillna()
    处理缺失的数据,可以填充为自定义数字等,下面是再计算商户特征将特征忘训练集合并时,有的数据会为NaN值,将其填为中位数、平均数、最大、最小等,除了一般用法filla还有很多用户用,可以参入函数来处理。
    df.fillna(method=‘ffill’)
    表示用前一个不为零的数据填充该列,又如df.fillna(method=‘ffill’, limit=2) 是过滤掉NAN值,且只填充前两个。
merchant_feature = pd.merge(merchant_feature, m7, on = 'Merchant_id', how = 'left')
merchant_feature = merchant_feature.fillna(0)
  • drop_duplicates
    属于过滤数据 移除重复项,比如在优惠券求每个用户买个的商户数量时进行了去重操作,默认会根据所有列相同去重,如果想要根据某列去重就需要传入列名或列名数组,另外其实每个方法基本都支持传入inplace=True,表示改变原始数据的值,如果只想显示哪行重复还可以使用duplicates会返回True 或False .
    # u_merchant_count : num of merchant user bought from
    u4 = df[df['Date'] != -10][['User_id', 'Merchant_id']].copy()
    u4.drop_duplicates(inplace = True)
    u4 = u4.groupby(['User_id'], as_index = False).count()
    u4.rename(columns = {'Merchant_id':'u_merchant_count'}, inplace = True)
  • get_dummies()
    该方法是处理离散变量的常用方法,因离散变量每行之间的大小比较关系不太大,重要的是哪个样本取了哪个值,因为等于某个变为取值时我就让其为1,没有取值的列让其为0,变为了哑变量、或指标变量,如典型的星期。下面即将周一到周日变为了one-hot encode展示。
# change weekday to one-hot encoding 
weekdaycols = ['weekday_' + str(i) for i in range(1,8)]
print(weekdaycols)
 
tmpdf = pd.get_dummies(dfoff['weekday'].replace('-10.0', np.nan))
tmpdf.columns = weekdaycols
dfoff[weekdaycols] = tmpdf
  • value_counts()
    这个方法求的是某个值出现的次数,常用来分析标签类的个数,也可以把统计结果做成各种图方便查看,既然是统计每个值出现的个数,那需要先确定有哪些值可以使用unique()方法,返回一个去重后的数组,在展示数据的时候遇到一个问题就是我根据条件过滤标签后,进行统计,统计完的结果我往往不知道哪个值在上还是在下,不利于我展示图形。
    解决方法是可以对value_counts()后的结果进行排序,具体实现看下面代码。
print(dfoff['label'].value_counts())
print('已有columns:',dfoff.columns.tolist())
dfoff.head(2)

obj = pd.Series(['c', 'a', 'd', 'a', 'a', 'b', 'b', 'c', 'c'])

# 对原列对象去重,得到唯一值列表,未排序
uniques = obj.unique()
print(uniques)

# 对唯一值列表排序
uniques.sort()
print(uniques)

# 排序方法一:返回的value_counts是一个Series对象 它包括索引和值,可以直接对索引排序
print(obj.value_counts().sort_index())

# 排序方法二:新建一个Series对象,对vales 和 index 赋值,index 先排好序
uc2 = pd.Series(obj.value_counts().values, index=uniques)
print(uc2)
  • apply()
    它常用来处理一列或者整个表格一起处理数据,可以传入函数,在数据清洗、转换等非常有用,如将满减券转为折扣券过程中一个方法即可完成。
def convertRate(row):
    """Convert discount to rate"""
    if row == -10 :
        return 1.0
    elif ':' in row:
        rows = row.split(':')
        return 1.0 - float(rows[1])/float(rows[0])
    else:
        return float(row)
        
def processData(df):
    # convert discunt_rate
    df['discount_rate'] = df['Discount_rate'].apply(convertRate)
    print(df['discount_rate'].unique())
    return df
    

模型好坏主因-有效的特征

用户特征提取

1.用户线下消费优惠券的日期
2.用户线下消费优惠券的距离
3.用户线下消费优惠券折扣率
4.用户接收到优惠券数量
5.用户购买记录的数量(包括使用和非使用优惠券)
u_buy_count : times of user buy offline (with or without coupon)
6.用户购买记录的数量(使用优惠券)
u_buy_with_coupon : times of user buy offline (with coupon)
7用户购买记录的商户数量(包括使用和非使用优惠券)
#u_merchant_count : num of merchant user bought from
8.用户购买记录(使用优惠券)与商家的各种距离,一个用户不止一次购买,不止在一个商家
#u_min_distance、u_max_distance、u_mean_distance、u_median_distance
u_use_coupon_rate
9.用户使用优惠券概率=用户使用优惠券买东西数量 / 用户拥有优惠券数量
u_buy_with_coupon_rate
10.用户使用优惠券购买概率 = 用户使用优惠券买东西数量 / 用户购买数量
#calculate rate

商户特征提取

#m_coupon_count : num of coupon from merchant
11.每个商户发放的优惠券数量
m_sale_count : num of sale from merchant (with or without coupon)
12.每个商户卖出记录(包括使用和非使用优惠券)
m_sale_with_coupon : num of sale from merchant with coupon usage
13.每个商户卖出记录(包括使用)
#m_min_distance
14.每个商户卖出记录(使用优惠券)与商家各种距离,一个商家不止一次卖出记录,不止卖给一个顾客
#m_coupon_use_rate
15.商家优惠券使用概率 = 商家卖出的数量(使用优惠券) / 商家发放的优惠券数量
16.商家卖出的里面优惠券概率 = 商家卖出的数量(使用优惠券) / 商家卖出的数量

       项目90%以上的代码是在处理各种特征、提取、转换、清洗等工作,特征工程可见很重要,找出来的特征越好,那么模型效果越好,可以说在做项目的时候要重视特征提取这块,全力了解需求、了解业务场景是做好一个模型的前提,切记。

项目模型

       如果只是使用机器学习的分类、回归等,那sk-learn库完全可以够用,里面包含了常用算法的实现,这些库往往是一些技术领导者封装出来,如谷歌、IBM等,我们可以研究他们的实现思路,优惠券中用到了逻辑回归

  • 线性模型 逻辑回归
    SGDClassifier 在第一篇已经提及,这里略过。。
  • LGBMClassifier
    lgbm基于boost思想实现的一个模型融合方法,基于逐渐提升算法常用的融合算法有adaboost、gbmboost等,sk-learn已经提供了实现方法,另外还有两种实现框架xgboost、lgbmboost,他们性能更好一些,后面讲详细介绍。

API文档地址
http://lightgbm.apachecn.org/cn/latest/Python-API.html#scikit-learn-api

model = lgb.LGBMClassifier(
                    learning_rate = 0.01,   #提升学习率
                    boosting_type = 'gbdt', #提升树的类型
                    objective = 'binary',#目标二分类
                    metric = 'logloss',#early_stop 对数损失
                    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'])

随笔思考

改变人生的不是道理,而是习惯

       开始做一个项目时感觉这么多内容要分析,有时难免有些踌躇不前,思想决定行为,表现出来后果是做这件事难免拖拖拉拉,效率可见非常缓慢,终于有一天起了个大早静下心来一口气梳理完了,发现也没有想的那么难,最重要的是有信心去做,心无旁骛的做,效率会很高,很快就会做完。
       从一片文章上提到“改变人一生的不是道理,而是习惯“,感觉颇有道理,道理是用来听得、记得,而习惯是行动,每个人的生活无时无刻在发生各种动作、行为也即为习惯,成功与平庸的人相比并不是懂得更多的道理,而是将一个个大道理转化为了行为习惯。

猜你喜欢

转载自blog.csdn.net/lilongsheng1125/article/details/82875646