客户流失预测实战:从特征工程到模型落地的完整流程

发布时间:2026/10/10 10:18:29
客户流失预测实战:从特征工程到模型落地的完整流程 接到一个金融App的客户流失预测需求时业务方给我的第一句话是你能不能提前一个月告诉我哪些用户要跑这句话听着简单做起来却是一整套从数据清洗、特征工程、可视化探索到模型训练和业务落地的实战流程。客户流失行为分析预测本质就是把人快要离开的信号变成可量化的字段用python、jupyter notebook、机器学习、数据可视化、数据分析这套经典技术栈从用户历史行为中找出流失前的共性轨迹再预测未来一段时间内哪些用户大概率流失。这篇文章就把我实际做过的完整流程拆开讲从最容易被忽略的业务定义开始到最终怎么把预测结果变成运营动作没有省略关键坑。适合正在做数据分析与机器学习项目的朋友参考也适合准备做客户流失方向课题的同学当复现模板。1. 先搞清楚金融科技里的流失到底怎么定义1.1 流失的业务场景和判断标准做客户流失分析最容易犯的第一个错误就是一上来就开代码。我见过不少同学拿到一份客户数据集里面连流失列都有了于是直接开始训练模型。但现实项目里很少会有现成的是否流失标签躺在Excel里。金融科技场景下用户流失的表现形态其实非常多样一个做小额借贷的App用户连续90天没有借款记录但还在每天签到看看额度算不算流失一个理财平台用户把资金全部转出但还在登录看收益算不算流失一张信用卡持卡人6个月没刷卡但账单还在正常还款算流失吗不同业务线的答案完全不同。我当时的做法是拉着产品经理和数据运营开了半小时会把流失明确成三档高流失风险 连续30天无登录且无交易中流失风险 15到30天内登录频次下降超过50%且余额出现转出低流失风险 只登录不交易超过14天。然后根据项目目标优先建模高流失风险这一档。这一步为什么重要因为Y标签的定义直接决定了后面所有模型的结果。定义定偏了模型再漂亮给业务的判断也是错的。比如在借贷场景单纯不再借款不一定是流失可能是客户负债率下降、需求暂时消失但如果平台上还有理财、支付等其他业态而这个客户的交易习惯转移到了别处那就要认真对待了。1.2 流失前的渐变信号为什么这件事可预测有人对机器学习预测流失有天然怀疑流失不是一个瞬间决定吗怎么能提前预测实际上我拆过上千条流失用户的轨迹后得出的结论是绝大多数流失不是突然发生的而是一个渐进过程。这些渐变的信号就是模型学习和捕捉的核心。一个典型的理财用户流失轨迹可能是这样的注册后前三个月频繁登录每周都会打开收益页面看两眼第四个月登录频次从每周7次降到每周2次第五个月资金从5万逐步降到1.2万第六个月彻底不再登录。整个过程充满可供建模的量化信号——登录频率下降、浏览时长缩短、持仓金额缩水、客服投诉次数上升这些都是常见且有效的特征。金融科技和电商、内容产品最大的不同就是数据颗粒度极细几乎每个用户动作都会被后端系统记录下来这决定了用机器学习做流失预测是完全可行、而且真的能落地的事。1.3 为什么选python jupyter notebook这套组合定完业务定义接着就是技术选型。这个项目我把技术栈锁定在python jupyter notebook pandas/sklearn/lightgbm matplotlib/seaborn没有为了炫技上更复杂的架构。原因主要有三个。第一数据探索阶段大量时间花在看一眼数据长什么样上。Jupyter Notebook的单元格交互模式特别适合这种边看边想的节奏看一个维度的分布写一段结论再画一张图改个参数重新跑整个过程非常顺滑而不是像流水线脚本那样从头跑到底。第二客户流失项目通常需要产出分析报告。Notebook天然把代码、可视化图表、文字结论放在同一个文档里直接导出就是一份带完整推理过程的说明文档这比后期截图拼Word高效得多。项目做完回头看这份记录本身的价值甚至不低于模型。第三机器学习的生态基本都在Python这边sklearn提供从数据切分、预处理、建模到评估的完整链路lightgbm补上树模型的性能短板可视化用seaborn和matplotlib完全够用不用额外引入重型平台。有人会问为什么不直接用Pandas Profiling这类自动化EDA工具我的经验是自动化报告能帮你快速发现缺失值和分布情况但流失项目的核心是对业务信号的解释这一步必须人来判断自动化工具替代不了。所以我会把它们当辅助主体分析还是自己一步一步来。2. 从原始数据到训练集特征工程里的关键动作2.1 原始数据长什么样金融科技公司的底层数据一般分布在好几张表里用户信息表、登录日志表、交易流水表、资产快照表、客服工单表。建模之前需要先把它们拉出来拼在一起。拿我当时接触的消费金融App举例核心字段大致如下类型字段示例说明用户基础信息user_id, age, 注册渠道, 注册天数注册渠道是渠道质量的重要代理变量登录行为近7/30天登录次数, 最近登录距今天数活跃度衰减是流失最直接的信号交易行为近30天交易笔数、金额平均单笔金额交易频次和金额变化反映使用深度资产情况当前余额, 持仓金额, 近30天转入转出总额资产转出是强预警信号客服交互近90天工单数, 投诉次数交互体验变差往往预兆离开数据量不用太大我当时清洗后保留了几十万行级别对训练模型来说已经足够。关键是要把每个字段的来源问清楚尤其分清哪些是注册以来的累计值哪些是某个时间窗口内的值这两种口径混在一起就是灾难。2.2 Y标签怎么构造没有现成标签时需要自己用业务规则打标签。在Python里写起来非常简单但要牢牢记住观察期表现期的框架以T日为基准取过去90天的特征看未来30天内是否发生流失事件。示例代码如下import pandas as pd import numpy as np # 假设 df 包含每个用户截止 T 日的 last_login_date 和 last_txn_date ref_date pd.Timestamp(2024-06-30) df[silent_days] (ref_date - df[last_login_date]).dt.days df[no_txn_days] (ref_date - df[last_txn_date]).dt.days # 流失定义连续30天无登录 且 连续30天无交易 df[churn] ((df[silent_days] 30) (df[no_txn_days] 30)).astype(int) print(df[churn].value_counts(normalizeTrue))注意观察期和表现期必须严格错开不能把表现期的事件拿到特征里去否则就会产生标签泄漏这是后期做验证时最容易被业务方质疑的点。2.3 特征工程把原始字段变成模型能用的信号客户流失的特征工程核心思路就是把行为日志压缩成时间窗口内的数字特征。我的经验法则是一切能反映活跃度下降资产规模变化使用深度变化的字段都值得造。常用做法有时间窗口聚合近7天、14天、30天、90天的登录次数、交易笔数、交易金额、提现次数等用pandas的groupby加agg一次算出来。窗口要覆盖短、中、长三个尺度这样模型既能捕捉短期的突变信号比如突然一周不用了也能看出长期的衰减趋势比如连续三个月使用频次稳步下滑。比值和变化率近30天登录次数除以近90天登录次数形成活跃度衰减比近7天交易金额除以近30天交易金额形成金额衰减幅度。这类比率特征比绝对值更稳定对高价值用户和普通用户都有解释力。状态类特征当前是否有未结清订单、是否开通自动还款、是否绑定银行卡、是不是通过某个特定渠道注册。这些强分类变量在树模型里往往贡献很高。聚合逻辑的示例# 登录日志聚合出窗口特征 login_features ( login_log.groupby(user_id)[login_time] .agg( login_cnt_7dcount, login_cnt_30dcount, last_login_gaplambda x: (ref_date - x.max()).days ) .reset_index() )每次做完聚合一定要检查结果的行数是否和用户表对齐、缺失值比例是否异常。聚合时一个很常见的坑是日志表本身的时间范围不对比如只导出了一个月的日志导致近90天登录次数被严重低估这种问题往往要等画特征分布图时才暴露出来。2.4 两次让我印象深刻的踩坑第一个坑是时间窗口的口径不统一。我把登录频次和交易金额放进同一张训练表里后来才意识到登录日志表是从流量平台导出的时间精确到天还丢了一些低活跃用户的记录而交易流水表来自核心系统精确到秒。两张表对近30天的统计口径差了小半天直接导致部分用户的登录特征值明显偏低。检查方式其实很简单分别看两个表里近30天有记录的日期数分布一眼就能看出异常。后来我全部统一用注册日期相对天数来对齐时间窗口问题才彻底解决。第二个坑是特征泄漏。做特征重要性分析时模型给出的最高贡献特征居然是一个用户是否已注销的状态字段——答案本身就混进特征里了。那当然预测得准但没有任何实际意义。当时发现这个问题靠的是直觉为什么状态字段的贡献比活跃度高这么多一查上游数据链路果然是某张状态表被提前关联了。从那以后我会给每个字段标注数据可获取时点凡是特征形成时间晚于预测时间点的一律排除。3. EDA和可视化模型跑之前先用眼睛找信号3.1 Jupyter Notebook里做探索分析的实际体验建好特征表我习惯先不做任何建模而是用可视化把数据集摸一遍。这个阶段Jupyter Notebook的优势体现得特别明显每次跑一个单元格图表立刻渲染在代码下方我可以随手用Markdown记下一句结论下次审阅时还能想起当时的推理链路。整套分析文档导出去就是一份带完整思路的万字报告基础。探索性分析的流程通常分三步先看整体数据质量和分布再看核心特征和流失标签的关系最后做特征间的相关性排查。我的建议是不要在第一步花太多时间事无巨细地看图先挑10个和业务最相关的特征做深度查看其余用摘要统计批量过一遍就行。3.2 三张必看的图第一张是流失用户与非流失用户的注册天数分布对比。用KDE分布图叠加的方式能快速判断是新手期用户容易流失还是老用户也容易流失。这对后续策略影响很大因为如果是新手期流失重心就放在首月体验如果是老用户流失那更多要考虑竞品分流和产品老化问题。import seaborn as sns import matplotlib.pyplot as plt sns.kdeplot(datadf[df[churn] 1], xtenure_days, labelchurn, fillTrue, alpha0.4) sns.kdeplot(datadf[df[churn] 0], xtenure_days, labelnot_churn, fillTrue, alpha0.4) plt.xlim(0, 2000) plt.legend() plt.title(注册天数分布流失 vs 未流失) plt.show()我见过的大多数金融场景都会有典型的双峰现象注册前几周流失率居高不下熬过某个黏性节点之后流失率才明显下降。这说明首月激活体验是留存的第一道生命线。第二张是不同注册渠道的流失率柱状图。渠道质量不均是个普遍现象有的渠道用户群天然精准流失率低有的是投放拉新带来的羊毛党装完App领完福利就走。这张图直接指导投放策略怎么调也能让模型学到注册渠道这个强分类特征。第三张是近30天登录次数和交易金额的散点图按是否流失着色。流失用户通常会明显聚集在左下角——低频、低额。这张图最大的启发是活跃度下降和资产撤走高度相关所以在特征工程里活跃度衰减比和资产净流出这两类特征要优先保留。3.3 缺失值和异常值的可视化排查金融数据往往存在大量缺失值比如用户没绑卡、没持仓对应字段自然为空。缺失值不能简单删除要先区分是真实缺失还是数据采集问题。我会画一张缺失值比例条形图然后按比例分类处理缺失率超过80%的字段直接剔除缺失率在30%到80%之间的字段看是否属于用户未开通某服务。如果属于就保留并补充一个分类标记如果属于采集异常则要做数据修复缺失率低于30%的字段常用中位数或众数填充树模型也可以直接保留缺失让模型自己学习。异常值方面交易金额最容易被几个大额用户拉出一条长长的尾巴箱线图基本看不出有效分布。处理原则不是删用户而是做对数变换或者用分位数裁剪。我个人偏好对数变换因为既能保留趋势信息又不至于让一两个大客户把整体特征尺度带偏。4. 建模全流程从逻辑回归到LightGBM的实战选择4.1 先把数据切分做对客户行为数据的切分与普通比赛不一样不能直接随机打乱。用户流失行为会随时间变化比如某个月产品版本更新、补贴政策调整都会让数据分布漂移。严谨做法是按时间切分取前70%时间段的用户特征做训练后30%时间段做验证。即便只有横截面数据也至少要保证同一用户的特征和标签不跨到训练集和测试集两侧。from sklearn.model_selection import train_test_split # 建议按时间切分这里用 register_month 字段做示例 train df[df[register_month] 12] test df[df[register_month] 12] X_train, y_train train.drop(churn, axis1), train[churn] X_test, y_test test.drop(churn, axis1), test[churn]如果样本量很小可以再用分层抽样保证训练集和测试集里的流失占比一致。但要注意时间切分的优先级永远高于随机切分因为模型的真正价值是预测未来。4.2 逻辑回归先做基线而且不要小看它流失预测项目我习惯先跑逻辑回归不只是因为快更重要的是逻辑回归的系数天然可解释。对业务方来说注册天数每增加100天流失风险下降3%这种表达比一棵黑箱树更容易建立信任。逻辑回归还能帮忙筛特征和流失标签相关系数低、又和其他特征高度共线的可以先从候选集里剔除。from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test) lr LogisticRegression(max_iter1000, class_weightbalanced) lr.fit(X_train_scaled, y_train)注意这里设置了class_weightbalanced。在流失占比只有10%到15%的数据里这个参数能让模型不过度偏向多数类对少数类样本的记忆能力会好很多。4.3 树模型和集成模型LightGBM是默认选择逻辑回归打好基线之后真正的主力模型我一般直接上LightGBM。原因很实际特征里既有连续变量又有大量分类变量LightGBM对缺失值有原生处理机制不需要提前填充训练速度快调参相对简单配合早停基本不会出现严重过拟合。如果安装环境没有LightGBM退而求其次用sklearn的GradientBoostingClassifier也能跑只是训练时间会明显变长。import lightgbm as lgb from sklearn.metrics import roc_auc_score model lgb.LGBMClassifier( n_estimators300, learning_rate0.05, num_leaves31, max_depth-1, subsample0.8, colsample_bytree0.8, random_state42 ) model.fit( X_train, y_train, eval_set[(X_test, y_test)], eval_metricauc, callbacks[lgb.early_stopping(stopping_rounds50)] ) y_pred model.predict_proba(X_test)[:, 1] print(AUC:, roc_auc_score(y_test, y_pred))这里有一个关键细节early_stopping要用独立验证集。如果直接在测试集上做早停AUC会被高估因为你无形中在用测试集信息选择迭代轮数。更稳妥的做法是从训练集里再切一小块出来专门做早停测试集从头到尾只碰一次。4.4 类别不平衡别急着上SMOTE流失数据天然不平衡常见流失率在8%到20%之间。处理方式我按优先级排列修改评估指标不用准确率改用AUC、召回率、TopK命中率等更贴合流失场景的指标在模型里加class_weight或者调大正样本权重成本极低效果往往很明显如果前两步还不够再考虑SMOTE等过采样方法。我的经验是很多场景到第二步就够用了SMOTE并不必是必选项。SMOTE在高维稀疏特征上容易生成不符合真实业务逻辑的样本调起来反而费时间。真正的关键还是和业务对齐目标宁可多召回一些高风险用户也不要漏掉高价值用户这个取舍比单纯追求指标更重要。5. 模型评估别只看准确率AUC、KS和阈值的业务打开方式5.1 准确率是流失预测的陷阱流失率15%的数据里一个全部预测不流失的瞎猜模型准确率也有85%。所以准确率在流失预测里没有任何意义我基本不看。平时最关注两个维度模型区分度指标包括AUC和KS业务决策指标包括混淆矩阵和TopK召回率。AUC衡量的是模型把流失用户排在非流失用户前面的概率。0.5是瞎猜水平0.8以上基本可用0.85以上就算表现很好了。KS是累计正负样本分布之间的最大差值在金融风控领域常用用在流失预测场景一样有效一般超过0.3就说明有不错的区分能力。5.2 混淆矩阵和阈值选择模型输出的概率本身不是决策决策需要设定一个阈值。阈值设得低召回率高误伤多阈值设得高准确率高但会漏掉大量潜在流失用户。我一般会把阈值-召回率-误伤率曲线画出来再结合用户价值分档来选阈值。举个例子高价值用户的流失损失可能是普通用户的10倍所以对高价值用户用低阈值召回优先对长尾用户用高阈值减少不必要打扰。from sklearn.metrics import precision_recall_curve precision, recall, thresholds precision_recall_curve(y_test, y_pred) for thr in [0.3, 0.5, 0.7]: idx (thresholds thr).sum() print(fthr{thr}, precision{precision[idx]:.3f}, recall{recall[idx]:.3f})在业务交付环节我会同时给出三档名单高风险名单、中风险名单、观察名单分别对应不同的运营动作而不是扔给业务一个流失概率预测大于0.5的笼统结论。5.3 特征重要性和SHAP可解释性模型好用还不够业务方一定会追问你说这个用户要流失为什么这个问题的答案不能只是模型算出来的。我推荐用SHAP来拆解单样本预测。SHAP能给出每个特征对某个具体用户预测结果的正负贡献比如近30天登录次数减少贡献了0.12的流失概率、月交易金额下降贡献了0.08的流失概率这样业务人员不仅知道谁要走还知道用户到底是因为什么开始冷淡了后续挽留话术才有方向。同时也不能忽略全局特征重要性排序。我跑过的流失模型里排在前面的特征通常集中在近30天登录次数、最近登录距今天数、近30天交易金额、余额变化幅度、客服工单数这几类。如果发现某个奇怪字段比如用户ID编号冲到了重要性榜首基本可以断定是数据泄漏要回头查特征拼接逻辑。6. 预测结果落地从得分到运营动作6.1 把用户分层而不是抛出一堆概率模型预测完我最终交给业务方的不是一张概率表单而是一份流失风险名单。名单按概率降序排列再叠加用户当前资产量级和近90天交易频率做价值分层形成四象限高价值-高流失风险最高优先级专属客服电话、定向优惠券、产品体验官邀请所有动作的核心是快速重建用户使用习惯高价值-低流失风险维持现有权益即可防止过度营销引起反感低价值-高流失风险不投入高成本人工干预最多发一条App推送或用自动化触达策略低价值-低流失风险基本不处理保持系统自动运营。这种做法最大的好处是让业务方的资源投放到刀刃上。流失概率再高如果没有价值也不值得用高成本的短信和人工客服去挽留。6.2 用A/B实验验证效果预测模型效果的真伪最终要靠业务实验说话。把高流失风险用户随机分成实验组和对照组实验组施加挽留策略对照组维持原有运营动作然后观察未来60天两组实际流失率是否有显著差异。这个环节有两点容易出问题一是实验设计阶段就要定好观测口径和样本量否则两组天然有差异对比结果没有说服力二是挽留动作本身要给足时间如果只观察两周就说策略无效往往是因为策略的挽留效果还没有完全显现就提前下结论了。6.3 Notebook在整个项目里的角色整套项目走下来Jupyter Notebook始终是贯穿全程的载体。它不只是代码编辑器更是分析过程的完整记录。从最初整理的业务假设到特征工程每一步的处理逻辑再到模型评估表、特征重要性图、阈值选择曲线全部沉淀在一个文档里。项目交付时把Notebook导出成带目录结构的网页版报告附上关键图表和结论业务方和技术同学都能在同一份文档里找到自己要的信息。这也是我给所有做数据分析实践的人的建议过程和结论都要完整记录而不是只把模型文件丢给对方。分析过程中那些为什么排除这个字段为什么要在这个位置切分样本的记录往往比最终的预测结果更有长期参考价值。一个模型三个月后可能被替代但一份完整思路的分析文档能让下一个接手的人少走大量弯路。最后分享一点实际体会客户流失预测成功的标志从来不是AUC冲到0.9而是业务人员真的拿着名单去拨了电话、发了权益包并且在下个季度看到流失率有了肉眼可见的下降。机器学习在这件事里占的权重可能只有四成剩下六成来自数据质量和业务理解的持续交互。如果让我给刚开始做同类项目的人提一条最实在的建议那就是开工前一定花够时间把流失这两个字和业务方掰扯清楚并且把每一次探索和思考都留在Notebook里——这套沉淀下来的东西会比模型权重更值钱。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询