资讯动态

客户流失预测实战:从特征工程到XGBoost模型调优

发布时间:2026/10/15 4:35:12 来源:尧图企业网站定制
1. 客户流失判断到底在判断什么1.1 从业务问题到数据问题的翻译过程客户流失判断说白了就是回答一个很朴素的问题这个客户接下来还会不会继续用我们的产品。听起来简单但真正动手做的时候你会发现流失这个词本身就很模糊。是彻底注销账号算流失还是连续三个月不登录也算流失是停止付费算流失还是活跃度降到某个阈值以下就算流失这些问题不搞清楚后面建模全是白搭。我在实际项目里踩过的第一个坑就是业务方说帮我预测一下哪些客户要流失我问流失的定义是什么对方愣了三秒说就是不用了呗。这种对话在跨部门协作里太常见了。所以第一步不是打开代码编辑器而是拉着业务方把流失的口径对齐。通常我会给出几个候选定义让业务方选比如未来30天内未产生任何付费行为、未来60天内登录次数为0、连续两个计费周期未续费等等。不同定义对应的建模难度、数据准备方式、预测窗口都不一样。这里有个经验流失定义最好同时满足可量化、可观测、有业务意义三个条件。可量化意味着能用SQL写出来可观测意味着数据里确实有对应字段有业务意义意味着这个定义跟业务方的实际关切是对齐的。三者缺一后面都会出问题。1.2 流失预测和流失分析的差别很多人把这两件事混在一起。流失分析是事后归因看已经流失的客户有什么特征比如流失客户中70%是注册不满30天的。流失预测是事前判断给每个存量客户打一个流失概率分然后按分数排序做干预。两者的数据切分方式、特征工程思路、评估指标都不一样。流失分析更偏向描述性统计和可视化产出物是各种对比图表和结论。流失预测则需要严格的训练集/测试集划分需要处理类别不平衡需要用AUC、KS、召回率等指标来评估。我见过不少团队拿着流失分析的结论直接当预测模型用结果上线后效果一塌糊涂根本原因就是没有做时间维度的切分用了未来信息去预测过去。注意做流失预测时特征的时间窗口必须严格早于标签的时间窗口否则就是数据泄露。这个坑我踩过不止一次模型离线AUC 0.95上线后跟随机猜差不多。1.3 这个项目适合谁来参考如果你是有一定SQL基础、了解Python基本语法的数据分析师或数据科学从业者这篇文章可以直接抄作业。如果你是完全零基础的小白建议先补一下pandas和sklearn的基本用法不然代码部分看起来会比较吃力。如果你是有经验的同行可以直接跳到特征工程和模型调优部分那里有一些我在实际项目中总结的细节技巧。整个项目的技术栈我选的是Python pandas scikit-learn XGBoost没有用深度学习。原因很简单表格类结构化数据的流失预测梯度提升树基本就是天花板深度学习在这个场景下投入产出比不划算。除非你有海量的行为序列数据要做embedding否则XGBoost或LightGBM足够了。2. 数据准备与特征工程的核心细节2.1 数据表的梳理和关联逻辑做流失预测数据通常来自多个表用户基本信息表、订单/交易表、行为日志表、客服工单表、营销触达表等等。这些表需要通过用户ID关联起来形成一个以用户为粒度、以时间窗口为切分的大宽表。我一般的做法是先画一张数据血缘图把每张表的粒度、主键、时间字段、可用特征列都标清楚。比如用户表是用户粒度订单表是订单粒度行为日志是事件粒度。不同粒度的表要聚合到用户粒度才能用。聚合的时候要注意时间窗口的选取通常我会取标签时间点之前的30天、60天、90天三个窗口分别做聚合这样能捕捉到不同时间尺度上的行为变化。关联的时候有个细节不是所有用户在所有表里都有记录。比如一个新注册用户可能还没有订单记录一个沉默用户可能最近90天没有行为日志。这些缺失不能简单填0要区分真的没有发生和数据没采集到。我的做法是同时生成一个缺失指示列比如近30天是否有登录这个特征除了登录次数本身再加一列标记是否曾经登录过。2.2 特征体系的搭建思路流失预测的特征大致可以分成几类用户属性特征、交易行为特征、活跃行为特征、互动特征、趋势特征。每一类下面又有若干具体指标。用户属性特征包括注册时长、会员等级、所在渠道、设备类型等静态信息。这类特征通常区分度一般但作为基础维度不能少。交易行为特征包括最近一次消费时间、消费频次、消费金额、客单价变化趋势等这类特征在付费产品里往往是最强的预测因子。活跃行为特征包括登录次数、使用时长、功能使用广度、页面浏览深度等在免费或Freemium产品里更重要。互动特征包括客服咨询次数、投诉次数、营销活动参与率等这类特征往往能捕捉到客户的负面情绪信号。趋势特征是我个人比较看重的一类比如最近30天消费金额 / 前30天消费金额这个比值能直接反映客户的消费意愿是在上升还是下降。这里分享一个我常用的技巧对于每个数值型特征除了原始值我还会生成它的环比变化率和同比变化率。比如本月登录次数是一个特征本月登录次数 / 上月登录次数是另一个特征。后者往往比前者更有预测力因为它捕捉的是变化趋势而不是绝对水平。一个客户每月登录10次如果一直稳定在10次那流失风险不高如果从30次降到10次那风险就很大了。2.3 标签的定义和样本构造标签定义是流失预测里最需要跟业务方反复确认的环节。我通常会用观察窗口 表现窗口的方式来构造样本。观察窗口用来生成特征表现窗口用来定义标签。比如观察窗口取标签时间点前90天表现窗口取标签时间点后30天。如果客户在表现窗口内没有产生任何付费行为标签为1流失否则为0未流失。这里有个关键决策标签时间点怎么选。如果只选一个时间点样本量可能不够而且容易受季节性因素影响。我的做法是选多个时间点比如每个月的第一天作为一个标签时间点这样能构造出多期样本既增加了样本量又能让模型学到不同时期的变化模式。但要注意同一个客户在不同时间点可能出现在训练集和测试集里这会导致信息泄露。解决办法是按客户ID做分组切分确保同一个客户的所有样本只出现在训练集或测试集中的一个。样本不平衡是另一个必须处理的问题。流失客户通常只占5%到20%如果直接训练模型会倾向于预测所有客户都不流失因为这样准确率也有80%以上。但业务方关心的是能不能抓住那20%要流失的客户所以准确率在这里是个误导性指标。我一般会用AUC和KS来评估模型排序能力用召回率和精确率来评估实际干预效果。处理不平衡的方法有几种调整类别权重、过采样少数类、欠采样多数类、用focal loss等。我实测下来调整类别权重scale_pos_weight最简单有效过采样容易过拟合欠采样会丢失信息。2.4 特征筛选和降维的实操方法特征不是越多越好。我见过一个团队往模型里塞了300多个特征结果AUC还不如用30个特征的版本。原因很简单噪声特征太多模型学到了虚假相关。特征筛选我一般分三步走。第一步是去掉低方差特征和高度共线特征。低方差特征比如是否中国籍这种几乎全是同一个值的列没有区分度。高度共线特征比如登录次数和活跃天数相关系数0.95以上留一个就行。第二步是用模型做初步筛选跑一个XGBoost看feature importance把重要性为0或极低的特征去掉。第三步是用递归特征消除RFE或前向选择做精细筛选但这步比较耗时通常只在特征数量特别多的时候做。实操心得特征筛选不要一次删太多每次删10%到20%观察验证集AUC的变化。如果删完AUC没降甚至升了说明删对了如果降了超过0.01说明删多了要往回加。3. 建模流程与核心环节实现3.1 数据集切分的正确姿势时间序列相关的建模绝对不能随机切分。随机切分会导致未来信息泄露到训练集里离线指标虚高。正确的做法是按时间切分用较早时间段的数据做训练较晚时间段的数据做测试。比如用1月到9月的数据训练10月到12月的数据测试。如果要做交叉验证也不能用普通的K折要用时间序列交叉验证TimeSeriesSplit。sklearn里有现成的TimeSeriesSplit但它的用法跟普通K折不太一样需要稍微改一下代码。我一般会封装一个自己的时间序列切分函数确保每次切分都是过去训练、未来验证。from sklearn.model_selection import TimeSeriesSplit import numpy as np def time_based_split(df, time_col, n_splits5): df df.sort_values(time_col).reset_index(dropTrue) tscv TimeSeriesSplit(n_splitsn_splits) splits [] for train_idx, test_idx in tscv.split(df): splits.append((train_idx, test_idx)) return splits切分完之后还要检查一下训练集和测试集的标签分布是否一致。如果训练集流失率10%测试集流失率30%那说明时间切分导致了分布偏移模型在测试集上的表现会失真。这种情况下要考虑做样本权重调整或者重新选切分点。3.2 基线模型的快速搭建在调参之前先搭一个基线模型。基线模型不需要很复杂逻辑回归或者决策树就行。目的是建立一个性能下限后面所有复杂模型都要跟这个基线比。如果XGBoost比逻辑回归只好了0.01的AUC那可能不值得上复杂模型因为维护成本高很多。逻辑回归做基线的时候记得做标准化和独热编码。数值特征用StandardScaler类别特征用OneHotEncoder。如果类别特征基数很高比如城市有几百个值独热编码会爆炸这时候可以用目标编码Target Encoding或者频率编码代替。from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import StandardScaler from sklearn.pipeline import Pipeline from sklearn.metrics import roc_auc_score pipe Pipeline([ (scaler, StandardScaler()), (clf, LogisticRegression(class_weightbalanced, max_iter1000)) ]) pipe.fit(X_train, y_train) pred_proba pipe.predict_proba(X_test)[:, 1] print(Baseline AUC:, roc_auc_score(y_test, pred_proba))基线跑出来之后记录下AUC、KS、召回率等指标作为后续对比的参照。3.3 XGBoost模型的调参与优化XGBoost的调参我一般分两轮。第一轮用默认参数跑一遍看baseline。第二轮用网格搜索或贝叶斯优化调几个关键参数n_estimators、max_depth、learning_rate、subsample、colsample_bytree、scale_pos_weight。参数的选择逻辑是这样的n_estimators和learning_rate要配合调learning_rate小的时候n_estimators要大反之亦然。max_depth控制模型复杂度太深容易过拟合太浅容易欠拟合一般从3到8之间试。subsample和colsample_bytree控制随机性能降低过拟合风险一般取0.7到0.9。scale_pos_weight用来处理类别不平衡通常设为负样本数除以正样本数。import xgboost as xgb from sklearn.model_selection import GridSearchCV param_grid { n_estimators: [100, 200, 300], max_depth: [3, 5, 7], learning_rate: [0.01, 0.05, 0.1], subsample: [0.7, 0.8, 0.9], colsample_bytree: [0.7, 0.8, 0.9] } xgb_clf xgb.XGBClassifier( scale_pos_weightneg_count/pos_count, eval_metricauc, use_label_encoderFalse ) grid GridSearchCV(xgb_clf, param_grid, cv3, scoringroc_auc, n_jobs-1) grid.fit(X_train, y_train) print(Best params:, grid.best_params_) print(Best AUC:, grid.best_score_)调参的时候有个细节验证集要用时间序列切分不能用普通K折。GridSearchCV默认是K折需要传入自定义的cv参数。另外n_jobs-1会占满所有CPU核心如果数据量大或者机器配置低可能会卡死建议先小规模试跑。3.4 模型评估指标的选择和解读流失预测的评估指标不能只看准确率。我一般会同时看AUC、KS、召回率、精确率、F1和提升度Lift。AUC衡量的是模型排序能力KS衡量的是模型区分正负样本的最大差距召回率衡量的是抓住了多少真正要流失的客户精确率衡量的是预测要流失的客户里有多少是真的要流失的。业务方最关心的是如果我只干预前10%的高风险客户能覆盖多少真正要流失的客户这个问题对应的指标是Top 10%的召回率。我一般会画一个累积提升曲线Cumulative Lift Curve横轴是干预比例纵轴是召回率。如果模型有效曲线应该明显高于对角线。from sklearn.metrics import roc_auc_score, recall_score, precision_score def ks_score(y_true, y_pred_proba): from scipy.stats import ks_2samp return ks_2samp(y_pred_proba[y_true1], y_pred_proba[y_true0]).statistic auc roc_auc_score(y_test, pred_proba) ks ks_score(y_test, pred_proba) print(fAUC: {auc:.4f}, KS: {ks:.4f})注意AUC高不代表业务效果好。我见过AUC 0.85的模型但Top 10%的召回率只有30%意味着干预了10%的客户只抓住了30%的流失客户业务方觉得不划算。所以评估的时候一定要结合业务场景看Top K的召回率。3.5 模型上线后的监控和迭代模型上线不是终点而是起点。上线后要持续监控几个指标预测分数的分布是否漂移、实际流失率是否跟预测一致、Top K客户的干预转化率如何。如果发现分数分布明显偏移或者实际流失率跟预测偏差超过阈值就要触发模型重训。我一般会设置一个月度重训机制每月用最新数据重新训练模型同时保留旧模型做对比。如果新模型在最近一个月的数据上AUC下降超过0.03就回滚到旧模型。另外特征的重要性排序也要定期检查如果某个特征的importance突然飙升或骤降可能是数据采集出了问题要排查上游数据链路。4. 常见问题与排查技巧实录4.1 模型离线效果好但上线效果差这是最经典的问题原因通常有三个数据泄露、分布偏移、特征上线不一致。数据泄露最常见比如用了标签时间点之后的信息做特征或者训练集和测试集有重叠客户。分布偏移是指训练数据的时间段和上线后的时间段分布不同比如训练用的是旺季数据上线是淡季。特征上线不一致是指离线计算的特征和线上实时计算的特征口径不同比如离线用30天窗口线上用自然月窗口。排查方法先检查特征计算的时间窗口是否严格早于标签时间点再检查训练集和测试集的客户ID是否有重叠然后对比线上线下同一批客户的特征值是否一致。我一般会抽样100个客户把离线特征和线上特征逐列对比差异超过5%的列就要重点排查。4.2 特征重要性不符合业务直觉有时候模型给出的重要特征跟业务方的认知完全相反。比如业务方觉得客服投诉次数应该是强特征但模型显示importance很低。这种情况不一定是模型错了可能是特征的计算方式有问题。比如投诉次数可能大部分客户都是0方差极小模型学不到东西。也可能是投诉和流失之间的关系是非线性的而模型没有捕捉到。解决办法先检查特征的分布看是否有足够的区分度。如果分布太偏考虑做分箱或者取对数。如果分布正常但importance低可以尝试构造交叉特征比如投诉次数 × 会员等级看是否能提升预测力。另外可以用SHAP值来分析特征对单个预测的贡献比全局importance更有解释性。4.3 样本不平衡导致模型偏向多数类前面提过流失客户通常只占少数。如果不处理模型会倾向于预测所有客户都不流失。除了调整类别权重还可以用阈值移动的方法模型输出概率后不直接用0.5做阈值而是根据业务需求选一个更低的阈值比如0.3这样能提高召回率但会降低精确率。阈值的选择要结合干预成本。如果干预成本低比如发个优惠券可以选低阈值多抓一些如果干预成本高比如人工客服外呼要选高阈值确保干预的都是高概率流失客户。我一般会画一个阈值-召回率-精确率的曲线让业务方自己选一个平衡点。4.4 特征缺失值处理的常见误区缺失值处理没有万能方法。均值填充适合数值特征且缺失率低的情况中位数填充适合有异常值的情况众数填充适合类别特征。但流失预测里缺失本身可能就是信息。比如最近一次登录时间缺失可能意味着这个客户从来没登录过这本身就是强流失信号。我的做法是对于缺失率低于5%的特征用中位数或众数填充对于缺失率5%到30%的特征填充的同时加一个缺失指示列对于缺失率超过30%的特征考虑直接删除或者用模型预测填充。但要注意用模型预测填充容易引入偏差我一般只在特征特别重要且缺失率不高的情况下才用。4.5 模型可解释性和业务落地的平衡业务方往往不满足于模型说这个客户会流失他们想知道为什么。这时候SHAP值就很有用。SHAP能给每个预测给出特征贡献度比如这个客户流失概率高主要是因为最近30天登录次数下降了80%贡献了0.15的概率。import shap explainer shap.TreeExplainer(xgb_clf) shap_values explainer.shap_values(X_test) shap.summary_plot(shap_values, X_test)但SHAP值也不是万能的。对于高度相关的特征SHAP值可能会分散导致解释不直观。这时候可以做特征聚类把相关特征合并成一个组再看组的贡献度。另外SHAP计算量大全量数据跑一遍可能很慢我一般只对Top K高风险客户做SHAP分析既能满足业务解释需求又不会太耗时。4.6 常见问题速查表问题现象可能原因排查方法解决方案离线AUC高上线效果差数据泄露或分布偏移检查特征时间窗口和客户重叠严格时间切分定期重训模型全部预测为不流失样本不平衡未处理查看预测分数分布调整类别权重或阈值特征重要性异常特征分布偏或计算错误检查特征统计量和缺失率分箱、取对数或重新构造训练时间长特征太多或参数太复杂查看特征数量和树深度特征筛选降低max_depth预测分数集中在中间模型区分度不够查看AUC和KS增加特征或换模型新客户预测不准新客户历史数据少检查新客户特征缺失率单独建模或冷启动策略最后分享一个我在实际项目中总结的小技巧流失预测模型不要追求单模型极致效果可以尝试模型融合。把XGBoost、LightGBM、逻辑回归的预测概率做加权平均往往能提升0.01到0.02的AUC。权重可以用验证集上的AUC来定简单有效。另外模型上线后一定要做A/B测试离线指标再好也要看实际干预后的转化率提升这才是最终衡量标准。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑