星巴克饮品预测

2020-10-01  本文已影响0人  forward_99

项目概述

这个数据集是一些模拟 Starbucks rewards 移动 app 上用户行为的数据。每隔几天,星巴克会向 app 的用户发送一些推送。这个推送可能仅仅是一条饮品的广告或者是折扣券或 BOGO(买一送一)。一些顾客可能一连几周都收不到任何推送。顾客收到的推送可能是不同的,这就是这个数据集的挑战所在。

数据集中还包含 app 上支付的交易信息,交易信息包括购买时间和购买支付的金额。交易信息还包括该顾客收到的推送种类和数量以及看了该推送的时间。顾客做出了购买行为也会产生一条记录。同样需要记住有可能顾客购买了商品,但没有收到或者没有看推送。

问题描述

有三种可以发出的推送:买一送一(BOGO)、折扣推送和消息型推送。在 BOGO 推送中,用户需要花费一定数额的钱来获得等值的奖励。在折扣推送中,用户获得消费额度的某个比例的奖励。在消息型推送中,用户不会收到任何奖励,但用户也不会有任何最低消费要求。推送可以通过多种渠道传递。

每种推送都有有效期。例如,买一送一(BOGO)优惠券推送的有效期可能只有 5 天。你会发现数据集中即使是一些消息型的推送都有有效期,哪怕这些推送仅仅是饮品的广告,例如,如果一条消息型推送的有效期是 7 天,你可以认为是该顾客在这 7 天都可能受到这条推送的影响。

数据集如下,一共有三个数据文件:

以下是文件中每个变量的类型和解释 :

portfolio.json 30 天试验期间的推送(10 个推送 X 6 个字段)

profile.json 得到奖励的顾客(17000 个用户 x 5 个字段)

transcript.json 事件记录 (306648 个事件 x 4 个字段)

解决思路

1、锁定目标客户
由于项目数据集中没有提供标签,所以我们要自定义标签。目前,在这项目中,我是用自定义的 valid_transaction 作为标签,其中,值为1表示 有效交易;值为0表示 无效交易。
2、数据集加载以及预处理
其中,预处理包括 空值情况、分类标签转换为独热编码(例如:portfolio中的channels、offer_type列等)、统一列名称(例如:将profile数据集中的 id列 重命名为 person)等。
3、定义函数,提取出交易记录中所有person的交易情况(从接收到消息推送到交易完成,期间经历的时间小于或等于该推送的duration时间即为合法,其他情况为非合法)

主要步骤如下:

4、数据可视化;
5、模型的评估与验证。

评价指标

本文主要是预测顾客是否对推送进行正反馈,这是个二分类任务。分类任务常见的评价指标有准确率(Accuracy)、精确率(Precision)、召回率(Recall)、F1 score、ROC曲线(Receiver Operating Characteristic Curve)等。

准确率(Accuracy):正确分类的样本占总样本的比例,对总体准确率的评估。
精确率(Precision):在被识别为正类别的样本中,确实为正类别的比例是多少?
召回率(Recall):在所有正类别样本中,被正确识别为正类别的比例是多少?
混淆矩阵(Confusion Matrix):对于二分类问题,可将样例根据其真实类别与分类器预测类别的组合进行划分:

ROC曲线:一种显示分类模型在所有分类阈值下的效果的图表。
F1 score:F1值为算数平均数除以几何平均数,且越大越好。

这个数据集中存在数据类别不平衡的问题,例如:在接收到推送通知的顾客中,只有很小部分顾客对推送做出反应(打开推送或产生消费),考虑到如果使用准确率作为评估目标,要先对数据进行平衡处理;另外,推送通知也算是一种广告推广,对于不希望接收到推送通知的顾客,我们不应该给他们发起推送,应该尽量只给潜在顾客或者目标顾客发送相对应的推送通知。所以,在上述评估指标中,我选取F1 score作为最终的评估目标,

探索性数据分析

导入数据以及相关的库: image.png 查看 portfolio数据集 空值情况: image.png 查看 profile数据集 空值情况: image.png

由上述可知,profile数据集中,gender、income各有2175个缺失值

分析 profile数据集 空值原因: image.png 查看 transcript数据集 空值情况: image.png

数据预处理

对 portfolio数据集的操作(重命名id列为offer_id、offer_type以及channels进行独热编码): image.png 收集profile数据集的特征统计数据: image.png

在对profile数据集进行空值计数时:gender为null时,对应的顾客年龄均为118岁,这里的数据也许是个脏数据,可能是记录有误导致的,而且gender为null占profile整个数据集比例为12.79%,占的比例不是很大,这里考虑将 所有空值 都删除。

# 删除profile中所有的空值
profile.dropna(inplace=True)

将profile数据集中的 id列 重命名为 person

profile.rename(columns={'id': 'person'}, inplace=True)

根据person值连接 profile和transcript数据集

profile_transcript_df = profile.join(transcript.set_index('person'), on='person')
profile_transcript_df.reset_index(drop=True, inplace=True)
获取所有person的交易情况(从接收到消息推送到交易完成,期间经历的时间小于或等于该推送的duration时间即为合法,其他情况为非合法),并组合为新的DataFrame。 image.png 将gender进行独热编码、转换 became_member_on值 为DateTime格式、以及删除 gap_time列,并将valid_transaction列放置最后一列: image.png

数据可视化

没有收到推送消息与收到推送消息的情况下去购买星巴克饮品的占比图: image.png

由饼状图可知,极少数人会在没有消息推送的情况下去购买星巴克饮品。

transcript数据集中时间记录饼状图: image.png

从上面饼状图可知,交易记录占了45.33%,比重比较大,这表明客户还是比较喜欢购买星巴克饮品。

不同年龄段购买星巴克饮品的分布图: image.png

由上图可知,购买星巴克饮品以中老年居多,其中中年占比最大。

对交易数据进行时间序列数据的分析 (transcript表的time列): image.png

由上图可知,在18天的时候,transaction的交易数目最多。其次是第25天。每次新一轮的offer received总是在offer viewed和offer completed的最低点过后的一天触发。

热力图(移除邮箱列): image.png

由热力图可知,与valid_transaction相关性较强的有以下特征:duration、difficulty、offer_type_discount、reward以及channels_web,与特征offer_type_informational相关性最低。而且目前相关性最大的值只是0.35,这表明所有特征与valid_transaction的相关性都不是很好。

模型的评估与验证

拆分数据集与验证集

y = person_offer_status_new_df['valid_transaction']
# cols = ['income', 'difficulty', 'duration', 'reward', 'offer_type_discount', 'channels_web', 'gender_F']
# X = person_offer_status_new_df[cols]
X = person_offer_status_new_df.drop(['person', 'became_member_on', 'offer_id', 'valid_transaction'], axis=1)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
使用逻辑回归模型进行预测: image.png image.png 使用随机森林模型进行预测: image.png 使用AdaBoostClassifier进行预测: image.png

刚开始使用 LogisticRegression模型去预测,F1 Score为: 0.70,预测执行时间将近300ms,其次是RandomForestClassifier模型,F1 Score为: 0.71,预测执行时间420ms左右,最后是AdaBoostClassifier模型,F1 Score为: 0.78,预测执行时间1.3s左右。由于AdaBoostClassifier 模型的F1 score得分最高,虽然预测时间比其他两种算法较长,但还可以接受;另外,AdaBoostClassifier模型用错分数据点来识别问题,通过调整错分数据点的权重(增大分错样本权重,降低分对样本权重)来改进模型,有利于找出对推送通知做出反应的精准用户而又不会乱发送推送通知。所以,综上所述,最终使用AdaBoostClassifier模型来进行本项目的预测。

模型改进

获取自变量的重要性情况并按照重要性进行排序,重新筛选用来训练的特征

# 自变量的重要性排序
importance = pd.Series(ada_model.feature_importances_, index = X_train.columns)
importance.sort_values().plot(kind='barh')
plt.show()
image.png 使用GridSearchCV调参,并获取最优参数组合下的最优模型,并进行预测,最终结果为: image.png image.png

讨论结果

由上面模型预测的结果来看,目前通过GridSearchCV调参,并用最优模型(learning_rate=0.1, n_estimators=300,base_estimator使用max_depth=3的DecisionTreeClassifier分类器)去预测,得到的F1 Score只为0.77左右,分值并不是很高,这表明该模型还需要再改进。我想导致得分不高的一部分原因是:要预测的 valid_transaction 特征跟其他特征相关性不是很强,最高也只是0.35。这其中可能是由于数据集不平衡导致的,另外,如果要提高F1 Score,可尝试换别的分类算法去预测。

反思

改进

疑问

参考链接:

上一篇 下一篇

猜你喜欢

热点阅读