概述
Sparkify是一家数字音乐服务的公司,大量用户每天使用该服务听自己喜欢的歌曲,他们可能是带广告的免费用户,或是使用尊贵会员的用户,会员听歌免费但是需要按月支付一定费用,用户可以升级降级,注销其账号。如果用户在平台体验不好,或需求没有得到满足,他们可能会流失(churn),要在用户流失之前留住他们
为什么要预测用户流失?
此notebook尝试预测哪些用户可能会流失,如果在用户流失之前用某种方式留住他们(例如打折),就能避免损失营业额。
如何预测用户流失?
我们假设现有数据代表sparkify平台上用户的一种模式,在现有数据上构建的模型可以泛化到其他用户。为了预测平台用户的流失,需要在现有数上构建了模型。具体来说,步骤是大致遵循加载数据集,清理数据,探索数据,提取特征,创建模型,最后用模型预测用户流失。
数据
用户每次和Sparkify服务互动都会产生用户行为数据,例如听歌曲,访问页面,添加好友,点赞等。完整的数据是12G,本notebook使用数据的一个子集(128M),在非集群环境运行。
清洗数据
artist / length / song 的缺失比率一样,这些缺失是用户在没有听任何歌曲的状态的数据,由于后边用到length的缺失比率作为特征,所以我没有处理这些缺失值。
firstName / gender / lastName / location / registration / userAgent 缺失比率一样,这些是游客用户的数据,由于游客不会注销,所以我将游客的数据删除,userId存在为空字符串的行,这也是游客的数据,删除游客的记录后,就没有userId为空的记录了。
数据中的ts是unix时间戳的形式,将其转换成方便阅读的形式,然后提取了小时和星期保存到新的字段
提取了location中的州
探索数据
定义churn
观察数据发现用户访问过Cancellation Confirmation之后就没有任何活动了,所以将churn定义为访问过Cancellation Confirmation页面的用户,并在数据中添加churn列作为用户的标签。标签的分布是偏态的,这可能会影响模型的预测结果(用户更可被预测为churn)
有23.11%的用户流失了,大部分用户没有churn
检查数据中标签是否偏态很有必要。在实践中这是非常普遍的,许多分类学习算法对于不常见的类别预测准确性较低。
单变量探索
用户数量:
page的唯一数量:
探索每个小时的数据量,每个时间段内所有用户的总操作次数在一定程度上可以代表用户的活跃度,从图中看出在凌晨24点用户的活跃度相对较高
双变量探索
探索各个地区的用户数量,加利福尼亚州的用户最多
gender 和 level:探索男性和女性的付费用户数量,每个性别的付费比率,平台上女性付费用户比男性付费用户多,两个性别付费比率相差不多都是80%
探索和churn相关的特征
我的目的是根据用户的特征预测用户是否会流失,这需要每个用户占一行每列为用户的一个特征,而现有数据中的userId列有重复的用户,不符合要求。所以需要从现有数据中提取用户的特征。
在这一部分我提取了9个特征,通过绘图探索了特征和标签的关系,稍后将使用这9个特征作为算法的输入。这里也可以使用假设检验来选择特征,检验流失用户和非流失用户的单个特征是否有显著区别。
churn vs 用户注册时长,可以看出注册时长短的更容易churn
某些特征的分布是偏态的(例如用户的好友数量),这违反了逻辑回归的假设,我对偏态的特征做了开平方转换,转换后接近正态分布。但是在后面的部分使用转换后的特征作为逻辑回归的输入,并没有提高得分。
特征工程
从原始数据中提取了探索过的9个特征作为算法的输入,将特征和标签保存在df_features中。总共有225个用户样本。
评估标准
我使用F1 score作为评估指标,因为数据的标签是偏态的,且阳性居多。
模型选择
首先划分了数据集,将60%作为训练集,20%作为验证集,20%作为测试集。
然后使用全部预测为churn和全部预测不为churn的模型作为基准模型,计算了基准模型的F1 score
预测用户全部不会流失的模型:F1 score:0.7111111111111111
然后使用叉验证训练了逻辑回归,GBT,支持向量机,随机森林的模型。根据模型在验证集的表现选择了随机森林。
需要注意的是,项目要求将数据划为三个部分(训练验证和测试),所以在模型选择过程中我没有使用k折交叉验证,因为使用验证集做模型选择。
k折交叉验证可以用来选择模型:k折的意思是将训练集数据分为k份,使用不同的k-1份训练多次,每次使用剩余的1份用来验证,这样做的好处是让训练集中所有数据都参与训练和验证,最后取多次训练的平局得分。交叉验证避免了使用测试集选择模型(如果用测试集选择模型,最终得到的模型必将在测试集上表现良好)。个人认为,可以将数据只划分为训练和测试集,不划分验证集,模型选择过程中,在训练集上使用k折交叉验证,这样相当于有80%的数据用于训练和验证。而Notebook中只有60%的数据用于训练,20%的数据用于验证。
调整模型参数
使用网格搜索调整参数
在随机森林上算法上使用网格搜索进行超参数选择,numTree使用[4,6,8],maxDepth使用[4,6,8],最优超参数的模型在测试集上的表现为f1: 0.784,在测试集的15条记录中,有2个真实是1被预测为0,有1个真实是0被预测为1。最终结果的F1 socre比基准模型(F1 score:0.71)有提高,但是提高并不多。
调整阈值
F1分数对阈值敏感,使用ROC调节阈值,选择训练籍中tpr-fpr值最大的阈值应用到测试集,测试集的得分并没有提高。
特征重要性
随机森林的feature_importance显示hour_since_reg对于用户是否会churn有着很大的影响,这是合理的,因为注册的时间长的用户代表用户在很长时间内都没有注销其账号,可能是经常使用,这样的用户更不容易注销账号,但也可能是很久以前注册过一直没用,也没有注销。
结论
Sparkify预测用户流失项目在128M的数据上训练了用于预测用户是否会流失的模型,评估了四个模型:逻辑回归,GBT,支持向量机,随机森林,通过对比F1 socre选择了随机森林并在其上调整参数,使用最优模型在测试集上得到的F1 score 是0.784,准确率是0.8。由于测试集只有15个样本,所以在测试集上的到的得分和现实有较大偏差。最后列出随机森林给出的对于用户是否会churn的最重要特征是用户注册了多长时间(hour_since_reg)。此notebook使用的是数据的子集,这样才能在单台机器上运行,如果用完整数据(12G),对于现有机器性能已经是大数据,需要在集群环境运行。数据有只225个用户,所以模型实际意义并不大,如果有更多数据,可以将本notebook拓展到spark环境,将对模型表现有很大程度的提升。
难点和挑战
我通过可视化的方式选择了特征,但是如何判断特征是否真对于预测label有用,并没有指标作为界定。这篇文章提到,特征选择主要有两种方法:filter method 和 Wrapper methods。filter method方法使用统计技术评估每个输入变量和目标变量之间的关系,然后排序算法过滤那些有用性较低的特征,对于分类-数据类型的数据,可以使用F-检验,对于分类-分类数据,可以使用卡方检验。Wrapper methods通常通过直接测试特征对模型性能的影响来选择特征。另外一个难点是标签和某些特征是偏态的,偏态分布的尾部可以作为异常值,异常值不利于模型的表现,虽然tree-based模型对异常值有较好的鲁棒性,但也限制了我们的选择。如果标签的偏态的,模型将会大量在多数标签上训练,较少在少数标签上训练,这样模型可能会不容易识别出较少标签的分类。
改进
我提取了9个特征用来预测用户的流失,可能还有更好的特征,如果加以尝试相信会提高模型的得分。另外我对数据集的划分只做了一次,这一次划分的数据得到模型并不一定是最好的模型,可以对数据集尝试多划分几次,然后选择得分最高的模型。