该案例分析项目是在小灶能力派商业数据分析课程上完成的
使用Python和Jupyter Notebook完成,本文是该案例的数据分析报告,详情代码在https://github.com/CLaraRR/xiaozao-data-analysis/tree/master/PDD
目录
1、项目说明
2、项目要求
3、数据认识
4、数据探索
4.1 整体的优惠券使用情况
4.2 不同年龄的使用优惠券情况
4.3 过去6个月优惠券使用情况
4.4 过去1个月优惠券使用情况
4.5 不同职业用户的优惠券使用情况
4.6 不同婚姻状态的用户的优惠券使用情况
4.7 信用卡是否违约的用户的优惠券使用情况
4.8 是否退货的用户的优惠券使用情况
4.9 是否使用信用卡付款的用户的优惠券使用情况
5、模型建立、预测和优化
5.1 数据预处理
5.1.1 数据分箱
5.1.2 哑变量处理
5.1.3 相关系数分析
5.2 模型建立和评估
5.2 模型优化
5.2.1 添加变量
5.2.2 更改损失函数的类别权重
5.2.3 改善数据不平衡
5.2.4 模型解读
6、业务建议
7、项目总结
拼多多是国内主流的手机购物APP,成立于2015年9月,用户通过发起和朋友、家人、邻居等的拼团,以更低的价格,拼团购买商品。拼多多作为新电商开创者,致力于将娱乐社交的元素融入电商运营中,通过“社交+电商”的模式,让更多的用户带着乐趣分享实惠,享受全新的共享式购物体验。对于各大电商平台,在“双十一”这种大促时间段,优惠券会起到非常大的促销作用。那么,如何找到更容易使用优惠券的用户,对他们精准地推送与营销,从而在双十一期间使销售额大大提升呢?这就是我们需要支持拼多多共同分析与解决的一个问题。
根据用户的基本信息以及过去的消费行为数据,完成以下事项:
数据来源于小灶商业数据分析课程,该数据集一共有25317条数据,将原数据字典按照用户信息、消费行为和预测结果进行不同维度的分类,用思维导图来表示如下:
本节的数据探索将分为数值变量和类别变量两种分别进行,主要探索其他变量和是否使用优惠券变量的关系。
统计数据集中所有用户使用优惠券的数量和不使用优惠券的数量。
由上图发现数据集极度不平衡,不使用优惠券与适用于优惠券的数据比例将近9:1,因此在后续建模的时候要改善数据不平衡这个问题。
将所有用户的年龄以5岁的间隔进行分箱,以及区分用户是否使用优惠券绘制直方图,如下图。
从图中发现:
分析原因:
将所有用户过去6个月优惠券使用情况绘制直方图,如下图。
从图中发现:
将所有用户过去1个月优惠券使用情况绘制直方图,如下图。
从图中发现:
1、统计各个职业的用户数量,如图1
2、统计各个职业分别使用优惠券和不使用优惠券的用户数量,如图2
3、统计各个职业中使用优惠券的人数比例,如图3
1、统计不同婚姻状态的用户数量,如图1
2、统计不同婚姻状态用户中使用优惠券的人数比例,如图2
1、统计不同信用卡违约状态的用户数量,如图1
2、分别统计不同信用卡违约状态用户中使用优惠券的人数比例,如图2
1、统计有过退货行为的用户和没有过退货行为的用户的数量,如图1
2、分别统计有过退货行为的用户和没有过退货行为的用户中使用优惠券的人数比例,如图2
1、统计使用信用卡付款的用户和没有使用信用卡付款的用户的数量,如图1
2、分别统计使用信用卡付款的用户和没有使用信用卡付款的用户中使用优惠券的人数比例,如图2
这一节将采用逻辑回归模型对前面涉及到的变量进行建模,用来预测用户是否使用优惠券。
在建模前首先要对数据进行预处理,预处理包括数据清洗(缺失值、异常值)、数据分箱、数据归一化、哑变量处理、相关系数分析等操作。数据清洗在数据探索的时候已经完成了,所以这一节主要是进行数据分箱、哑变量处理和相关系数分析。
分箱的主要目的是为了减少建模中的变量数量,使模型的可解释性更强。
分箱完成后数据变为下面的样子:
其中job_clean是将job划分后创建的新变量,c6对应的是coupon_used_in_last6_month,c1对应的是coupon_used_in_last_month,age_clean对应的是age,然后可以把原变量删除掉。
这一步对类别变量进行哑变量处理,使得使类别变量变成二值变量,从而使得模型能够处理类别变量,数据变为下面的样子:
这一步将其他变量与是否使用优惠券变量进行相关性分析,取出相关系数绝对值大于0.05的变量进行后续建模。
通过分析,得到以下几个变量:c1_1, job_clean_low, c1_2, age_clean_>65,marital_single, marital_married, loan_yes, returned_yes。
其中变量c1_1, job_clean_low, c1_2, age_clean_>65, marital_single和coupon_ind是强正相关,
变量marital_married, loan_yes, returned_yes和coupon_ind是强负相关。
终于到了最关键的一步也是本项目的最终任务——使用逻辑回归模型对相关变量进行建模来预测用户是否使用优惠券。
这一节先不考虑数据不平衡的问题,之后在模型优化的时候再改善这一问题。
首先将数据集按7:3的比例分为训练集和测试集,使用训练集数据训练逻辑回归模型,再应用到测试集上进行预测。模型的训练准确率、测试准确率、精确率、召回率、F1-Score和AUC如下:
train_acc | test_acc | precision | recall | f1-score | AUC | |
Original | 0.8864 | 0.8867 | 0.2667 | 0.0047 | 0.0093 | 0.5015 |
模型的ROC曲线如下:
模型的测试准确率虽然很高,但是由于数据极度不平衡,所以以准确率作为模型优劣的评价准则是有失偏颇的,因此用精确率、召回率、F1-Score作为评价标准更好。
可以看到这个模型的精确率、召回率和f1-score都很低,且AUC值为0.5左右,基本上随机猜测也能达到准确率0.88,这个模型是没有应用的价值的。
我通过三种思路来改进模型:添加变量、更改损失函数的类别权重和改善数据不平衡
原始模型只使用了相关系数大于0.05的变量进行建模,如果把所有变量都加进去,再来看看模型效果是否提升。
train_acc | test_acc | precision | recall | f1-score | AUC | |
AddVariable | 0.8860 | 0.8871 | 0.4333 | 0.0154 | 0.0297 | 0.5064 |
ROC曲线如下:
添加所有变量后模型性能并没有明显提升,这种方法不予采用。
更改类别权重就是针对不同类别的数据设置不同的分错代价,即提高少数类分错的代价或降低多数类分错的代价,最终使各类别平衡。常用的机器学习训练方法中,很多都提供了权重设置参数class_weight,可以手动设置该参数,但一般情况下只需要将其设置为balanced即可。
train_acc | test_acc | precision | recall | f1-score | AUC | |
Balanced | 0.7055 | 0.7132 | 0.2052 | 0.5403 | 0.2975 | 0.6377 |
ROC曲线:
更改类别权重后模型的recall、f1-score和AUC有了较大的提升。
原始模型没有对数据不平衡进行处理,这里我采用了imblearn库的多种重采样方法改善数据不平衡。关于imblearn的使用可以参考链接和官方文档。
需要非常注意的是:必须先划分训练测试集,再在训练集上进行重采样
训练集的作用是为了学得正负样本的分割超平面,但是数据不平衡,会干扰模型的学习,因此,我们才在训练集上使用“重采样”这样的技术手段;而测试集的本质作用是利用历史样本来检验学得的模型的泛化能力,因此测试集必须要代表未来真实的样本分布,不然就丧失了测试集本身应有的作用。所以应该先划分训练测试集,再在训练集上进行重采样,以解决类别不平衡数据怎么"学"的问题。如果先进行重采样再划分训练测试集,那么测试集的分布就不能代表真实的样本分布,而且不同的重采样方法得到的数据不同,在不同的测试集上进行模型对比是不公平的。
各个方法的效果如下表:
method | train_acc | test_acc | precision | recall | f1-score | AUC |
Original | 0.886435 | 0.886684 | 0.266667 | 0.004739 | 0.009313 | 0.501545 |
AddVariable | 0.886035 | 0.887084 | 0.433333 | 0.015403 | 0.029748 | 0.506426 |
Balanced | 0.705473 | 0.713182 | 0.205221 | 0.540284 | 0.297456 | 0.637679 |
RandomUnderSampler | 0.636890 | 0.707457 | 0.201588 | 0.541469 | 0.293796 | 0.634971 |
RandomOverSampler | 0.636457 | 0.713182 | 0.205221 | 0.540284 | 0.297456 | 0.637679 |
SMOTE | 0.626513 | 0.683755 | 0.189955 | 0.555687 | 0.283127 | 0.627829 |
ADASYN | 0.594300 | 0.615712 | 0.164366 | 0.592417 | 0.257334 | 0.605539 |
BorderlineSMOTE | 0.671022 | 0.615712 | 0.164366 | 0.592417 | 0.257334 | 0.605539 |
RENN | 0.893524 | 0.827563 | 0.267765 | 0.308057 | 0.286501 | 0.600698 |
NearMiss | 0.639658 | 0.695872 | 0.198240 | 0.560427 | 0.292879 | 0.636724 |
SMOTEENN | 0.990801 | 0.881891 | 0.361290 | 0.066351 | 0.112112 | 0.525750 |
SMOTETomek | 0.626513 | 0.683755 | 0.189955 | 0.555687 | 0.283127 | 0.627829 |
经过上面多种改善数据不平衡方法的尝试,大部分方法都对原模型在精确率、召回率、f1-score有了不同程度的提升,综合下来,选择各方面都较出色的更改损失函数的类别权重的方法。
这一节使用优化后的模型进行模型系数解读。各个变量的模型系数和概率比值如下表:
变量 | 模型系数 | 概率比值 |
c1_1 | 1.0895 | 2.9728 |
job_clean_low | 0.2608 | 1.2979 |
c1_2 | 1.1283 | 3.0903 |
age_clean_>65 | 1.0840 | 2.9566 |
marital_single | 0.2590 | 1.2956 |
marital_married | -0.1856 | 0.8306 |
loan_yes | -0.5073 | 0.6021 |
returned_yes | -0.7893 | 0.4542 |
1、c1_2系数解读:
c1_2系数为1.1283,c1_2对应的coupon_ind变量是0和1,那么我们可以做出如下假设:
我们计算的系数,就是对应到事件发生(p)与不发生(1-p)概率比值的log转换,结合公式,即为ln(p/1-p)就等于1.1283,也就是说p/1-p=exp(1.1283)=3.0905。
所以我们可以说,在前一个月使用了2次优惠券的用户在本次活动中使用优惠券的概率是其他用户3倍。
2、job_clean_low系数解读:
job_clean_low系数为0.2608,job_clean_low对应的coupon_ind变量是0和1,那么我们可以做出如下假设:
我们计算的系数,就是对应到事件发生(p)与不发生(1-p)概率比值的log转换,结合公式,即为ln(p/1-p)就等于0.2608,也就是说p/1-p=exp(0.2608)=1.2979。
所以我们可以说,低收入用户的优惠券使用概率是非低收入用户的1.3倍。
同理,其他变量的系数解读也是类似的:
整理前面数据探索和建模中得到的结论,可以给出以下业务建议以供参考:
这个项目让我体验到了从数据清洗-->数据探索-->建模预测-->模型优化-->得出业务结论的完整流程,受益匪浅。其中让我感触最深的是数据探索和模型优化这两个环节,如何从各个变量中发掘他们之间的关系,使用哪种可视化图表展示这种关系,这都是一个需要大量练习才能熟练掌握的过程,而模型优化则涉及到机器学习领域甚至是更高深的数学知识,这也促使我去了解各种机器学习模型的应用场景,以及更新的模型方法。但这次项目也有不足的地方,比如业务建议这一块,由于我对业务这块了解不多,因此给出的建议可能会比较笼统而不具体,今后还要在这方面多多积累。