客户流失预测实战:生存分析+随机森林+Flask部署全链路拆解
简介这份资源是面向计算机、人工智能及数据科学相关专业学生与从业者的客户留存分析与流失预测完整项目适用于电信运营商、保险公司等需要提升客户留存率的业务场景也可作为毕业设计或课程作业的参考方案。压缩包共62个文件约19.89MB包含3个Jupyter Notebook分别完成探索性分析、生存分析与流失预测建模1个Flask应用脚本与HTML模板用于模型部署另有2个pkl模型文件、1个bz2解释器文件及49张png可视化图表覆盖生存曲线、特征重要性、SHAP解释与部分依赖图等分析结果。项目通过生存分析刻画客户流失概率随时间的变化趋势并计算生命周期价值同时以随机森林预测客户是否流失最终借助Flask Web应用完成交互式展示。已有163人学习适合希望掌握客户流失建模全流程、理解模型部署与可视化呈现的读者参考借鉴。1. 客户留存分析与流失预测系统从生存曲线到 Flask 部署的完整拆解电信、保险、SaaS 这类订阅制业务里最贵的成本从来不是获客而是客户悄无声息地走掉。等你从月度报表里发现流失率抬头往往已经晚了两三个月。这个Customer-Survival-Analysis-and-Churn-Prediction-master资源包把两件事揉在了一起用生存分析Survival Analysis刻画客户流失概率随时间的动态变化再用随机森林做二分类预测最后用 Flask 把模型包成一个能交互的 Web 应用。它不是一个玩具 demomodel.pkl、survivemodel.pkl、explainer.bz2三个模型文件加上app.py、templates/index.html构成了一条从数据探索到线上推理的完整链路。适合谁做客户成功、增长分析、风控建模的工程师以及需要一套能跑通、能改、能写进毕业设计的完整项目的人。下面我按自己拆包的顺序把这份资源从结构到落地讲透。2. 资源结构与技术栈先看清包里到底装了什么2.1 目录分层与文件职责拿到一个 zip我习惯先tree一遍再动手避免改到一半发现模型和代码对不上。这个包的结构大致分四层Notebook 层、模型产物层、Web 应用层、可视化素材层。# 解压后先看整体结构重点关注 .ipynb / .pkl / app.py 三类文件 unzip Customer-Survival-Analysis-and-Churn-Prediction-master.zip cd Customer-Survival-Analysis-and-Churn-Prediction-master ls -R | head -60从文件清单能读出这条链路Exploratory Data Analysis.ipynb负责探索Customers Survival Analysis.ipynb做生存建模Churn Prediction Model.ipynb训练随机森林三个 Notebook 的产物分别落到survivemodel.pkl、model.pkl、explainer.bz2最后由app.py加载并对外提供预测。Images/下几十张 pngsurvival.png、shap.png、pdp_contract.png等是分析过程的可视化留档static/和templates/是 Flask 的前端资源。文件/目录作用是否可改app.pyFlask 入口加载模型并渲染页面可改注意模型路径model.pkl随机森林流失分类模型重训后替换survivemodel.pkl生存分析模型用于生存曲线重训后替换explainer.bz2SHAP 解释器压缩存储与模型配套别单独换*.ipynb三个分析/建模 Notebook主要改动区requirements.txt依赖清单按环境补版本Procfile部署启动命令云平台部署时用2.2 技术栈选型为什么是生存分析 随机森林很多人做流失预测直接上分类模型输出一个「会不会流失」的概率就完事。问题在于流失是一个带时间维度的事件客户在第 3 个月流失和第 18 个月流失对业务的意义完全不同。生存分析的核心是生存函数 S(t) 和风险函数 h(t)它处理的是「删失数据」——那些还没流失、观察期就结束的客户普通分类模型会把它们当负样本导致偏差。这个包用生存分析回答「客户能活多久、什么时候最危险」用随机森林回答「这个具体客户现在会不会走」两者互补。随机森林在这里是合理选择特征里有大量类别变量Contract、PaymentMethod、InternetService树模型对类别和缺失不敏感还能直接输出特征重要性包里model_feat_imp.png就是它。explainer.bz2用 SHAP 做局部解释解决树模型「黑匣子」的问题——业务方问「为什么判这个客户要流失」SHAP 能给出每个特征的贡献值。2.3 环境准备与依赖安装先建虚拟环境再装依赖别直接往系统 Python 里灌这是血泪经验。python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install -r requirements.txt # 若 requirements 未锁版本常见核心依赖手动补 pip install flask pandas numpy scikit-learn lifelines shap matplotlib seabornlifelines是生存分析的常用库Kaplan-Meier、Cox 比例风险模型shap负责解释flask负责部署。装完先跑python -c import lifelines, shap, flask验证避免 Notebook 跑到一半才发现缺包。注意explainer.bz2是压缩的 SHAP 解释器加载时要用shap.Explainer或joblib配合bz2解压具体看app.py里的加载写法别自己臆造。3. 生存分析与流失预测建模三个 Notebook 怎么串起来3.1 探索性分析先搞清删失和特征分布Exploratory Data Analysis.ipynb是起点。电信客户数据集里关键字段是tenure在网月数、Churn是否流失、MonthlyCharges、TotalCharges以及一堆服务订阅字段。做生存分析前必须先定义「事件」和「观察期」事件是ChurnYes观察期是tenure那些ChurnNo的客户就是删失样本。import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(telco_churn.csv) # 按实际数据文件名替换 # TotalCharges 常见坑空字符串导致整列变 object df[TotalCharges] pd.to_numeric(df[TotalCharges], errorscoerce) df df.dropna(subset[TotalCharges]) # 流失与在网时长的关系先看分布再建模 df.groupby(Churn)[tenure].describe() df[tenure_group] pd.cut(df[tenure], bins[0,12,24,48,72], labels[0-12,12-24,24-48,48-72]) df.groupby([tenure_group,Churn]).size().unstack().plot(kindbar) plt.title(Churn by tenure group) plt.show()这段代码做了两件事把TotalCharges强制转数值原始数据里新客户该字段为空字符串不处理会让后续所有数值运算翻车以及按在网时长分箱看流失分布。包里tenure-churn.png、tenure_group.png就是这类图。参数上errorscoerce把无法转换的值变 NaN 再删比直接astype(float)安全。3.2 生存分析Kaplan-Meier 与 Cox 模型Customers Survival Analysis.ipynb是这份资源最有价值的部分。它用lifelines拟合生存曲线回答「客户在第 t 个月仍在网的概率」。from lifelines import KaplanMeierFitter, CoxPHFitter kmf KaplanMeierFitter() kmf.fit(durationsdf[tenure], event_observed(df[Churn]Yes)) kmf.plot_survival_function() plt.title(Overall Survival Curve) plt.xlabel(Tenure (months)) plt.ylabel(Survival Probability) plt.show() # 按合同类型分层看不同群体的生存差异 for contract in df[Contract].unique(): mask df[Contract] contract kmf.fit(df.loc[mask,tenure], (df.loc[mask,Churn]Yes), labelcontract) kmf.plot_survival_function() plt.show()fit的两个核心参数durations是观察时长event_observed是事件是否发生True 表示流失。分层画图能直观看到月付客户Month-to-month的生存曲线下降远快于两年合约客户这正是Contract.png、survival.png想表达的。Cox 模型进一步给出各特征的风险比hazard ratiohazard.png就是它的输出。cph CoxPHFitter() # 类别变量需先做 one-hotCox 不接受字符串 cox_df pd.get_dummies(df[[tenure,MonthlyCharges,Contract,Churn]], columns[Contract], drop_firstTrue) cox_df[event] (cox_df[Churn]Yes).astype(int) cph.fit(cox_df.drop(columns[Churn]), duration_coltenure, event_colevent) cph.print_summary()风险比大于 1 表示该特征增加流失风险。月付合同的 HR 通常显著大于 1这就是业务上「推年付合约能降流失」的量化依据。3.3 随机森林分类与 SHAP 解释Churn Prediction Model.ipynb走的是标准监督学习流程特征编码、训练、评估、解释。from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import roc_auc_score, classification_report import joblib X pd.get_dummies(df.drop(columns[Churn,tenure_group]), drop_firstTrue) y (df[Churn]Yes).astype(int) X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, stratifyy, random_state42) rf RandomForestClassifier(n_estimators300, max_depth12, class_weightbalanced, random_state42) rf.fit(X_train, y_train) pred rf.predict_proba(X_test)[:,1] print(AUC:, roc_auc_score(y_test, pred)) print(classification_report(y_test, rf.predict(X_test))) joblib.dump(rf, model.pkl)参数说明class_weightbalanced应对流失样本偏少的不平衡问题stratifyy保证训练测试集流失比例一致n_estimators300是精度和训练时间的折中。评估别只看准确率流失预测里 AUC 和召回率更关键——漏掉一个真要走的客户成本远高于误报。model_feat_imp.png是特征重要性图shap.png、shap1.png是 SHAP 汇总图explainer.bz2就是训练好的解释器供app.py在线解释单条预测。4. Flask 部署与交互把模型变成能点的页面4.1 app.py 的加载逻辑与路由app.py是整条链路的出口。它要同时加载分类模型、生存模型和 SHAP 解释器再通过路由把预测结果渲染到templates/index.html。import joblib, bz2, shap from flask import Flask, render_template, request app Flask(__name__) model joblib.load(model.pkl) surv_model joblib.load(survivemodel.pkl) # explainer.bz2 是压缩的 SHAP 解释器按实际存储方式解压加载 with bz2.BZ2File(explainer.bz2, rb) as f: explainer joblib.load(f) app.route(/, methods[GET,POST]) def index(): if request.method POST: # 从表单取特征构造与训练时同顺序的 DataFrame features build_features(request.form) prob model.predict_proba(features)[0,1] shap_vals explainer.shap_values(features) return render_template(index.html, probround(prob,3), shapshap_vals.tolist()) return render_template(index.html) if __name__ __main__: app.run(debugTrue)关键点在于build_features表单提交的是原始字段必须经过和训练时完全一致的 one-hot 编码、列顺序对齐否则模型输入维度对不上直接报错。这是部署阶段最常见的翻车点。4.2 本地启动与接口验证export FLASK_APPapp.py flask run --host0.0.0.0 --port5000 # 或直接 python app.py启动后浏览器打开http://127.0.0.1:5000填表提交看是否返回流失概率和 SHAP 解释。Procfile里通常写的是web: gunicorn app:app说明生产环境用 gunicorn 而非 Flask 自带服务器。本地验证时如果页面报 500先看终端 traceback八成是模型路径或特征列顺序问题。4.3 特征对齐部署阶段最容易翻车的地方训练时pd.get_dummies生成的列和线上单条数据get_dummies生成的列几乎不可能自动一致——线上只有一条记录某些类别值没出现列就少了。正确做法是保存训练时的列清单线上用reindex对齐。import json # 训练后保存列顺序 json.dump(list(X_train.columns), open(feature_cols.json,w)) # 线上推理时对齐 cols json.load(open(feature_cols.json)) features features.reindex(columnscols, fill_value0)fill_value0表示训练时存在但线上没出现的类别默认该客户不属于该类。不做这一步模型要么报维度错误要么静默给出错误预测后者更可怕。5. 避坑与常见问题排查5.1 现象Notebook 里TotalCharges全是 NaN原因原始 CSV 里新客户的TotalCharges是空字符串pd.read_csv把它读成 object 列直接astype(float)会抛错用errorscoerce又可能把整列变 NaN。解决先pd.to_numeric(..., errorscoerce)再检查 NaN 比例少量直接dropna量大则考虑用MonthlyCharges * tenure填补。5.2 现象生存曲线画出来是平的或异常原因event_observed传成了字符串Yes/No而非布尔值lifelines把非零值都当事件发生导致曲线失真。解决统一转成(df[Churn]Yes)的布尔 Seriesdurations必须是数值型且非负。5.3 现象Flask 启动报ModuleNotFoundError: lifelines原因requirements.txt没锁全依赖或虚拟环境没激活就装了包。解决确认which python指向 venv重新pip install -r requirements.txt缺的库手动补。部署到云平台时Procfile和requirements.txt必须同时存在否则构建阶段就失败。5.4 现象SHAP 解释加载报版本不兼容原因explainer.bz2是用特定版本shap序列化的换版本后反序列化失败。解决按requirements.txt里的 shap 版本安装别盲目升级。若实在不兼容用model.pkl重新训练一个shap.TreeExplainer替代。5.5 现象预测概率全是 0.5 附近原因特征没做对齐或类别编码顺序和训练时不一致模型实际在「瞎猜」。解决核对feature_cols.json打印线上输入和训练输入的列名做 diff确保完全一致。这是最隐蔽的坑模型不报错但结果无意义。6. 进阶技巧用生存曲线做客户生命周期价值分层把生存分析和分类模型结合能做出比单纯「流失概率」更有业务价值的输出。具体做法用survivemodel.pkl预测每个客户未来 6 个月的生存概率乘以该客户的MonthlyCharges得到期望剩余价值Expected Residual Value再按价值分位切层。import numpy as np # 假设 surv_model 提供 predict_survival_function def expected_residual_value(customer, months6): surv surv_model.predict_survival_function(customer, timesrange(months1)) # 每月存活概率之和 × 月费 ≈ 期望剩余收入 return float(np.sum(surv.values)) * customer[MonthlyCharges] df[erv] df.apply(expected_residual_value, axis1) df[value_tier] pd.qcut(df[erv], q4, labels[低,中,高,极高]) # 交叉看高价值且高流失概率的客户才是优先挽留对象 priority df[(df[value_tier].isin([高,极高])) (df[churn_prob] 0.6)]这样输出的priority名单比单纯按流失概率排序精准得多——一个每月 20 元、流失概率 90% 的客户和一个每月 100 元、流失概率 70% 的客户后者才值得投入挽留成本。验证方法上我会用历史数据做回测取某个时间点切分看模型预测的高风险客户在随后 3 个月的实际流失率是否显著高于平均AUC 和提升度lift都达标才算可用。从那以后我每次拿到这类带.pkl的资源包都强制先跑一遍「训练列 → 线上列」的对齐检查再谈模型效果——模型再准特征对不上都是白搭。希望这份拆解能帮你少走几个弯路把这份资源真正跑起来、用起来。本文还有配套的精品资源点击获取

相关新闻

Java跨平台原理深度解析:字节码、JVM 与一次编译到处运行的真相

Java跨平台原理深度解析:字节码、JVM 与一次编译到处运行的真相

1. 跨平台问题的本质:你踩中的“认知陷阱”在哪1.1 跨平台到底在跨什么“平台”先把这个词拆开看。平台这个概念,多数时候指的是操作系统与底层硬件架构的组合,比如 Windows x86、Linux ARM、macOS Apple Silicon。任何一个程序最终都要通过操…

2026/10/9 3:40:17 阅读更多 →
MySQL JOIN优化实战:从EXPLAIN看懂执行计划,彻底告别慢查询

MySQL JOIN优化实战:从EXPLAIN看懂执行计划,彻底告别慢查询

前阵子接到一个线上慢查询,三张表JOIN,接口一到晚高峰就超时,DBA把EXPLAIN丢给我,我看到一整排的ALL和Extra列里的“Using join buffer”,就知道这条SQL又没吃到JOIN算法的红利,纯靠嵌套循环硬扛。后来花了…

2026/10/9 3:40:17 阅读更多 →
Win10网络发现关闭指南:公用网络与防火墙规则彻底禁用

Win10网络发现关闭指南:公用网络与防火墙规则彻底禁用

简介:针对 Windows 10 用户关闭网络发现功能的实操型图文文档,压缩包内包含 1 个 docx 文件,整体仅 228KB,内容精炼无冗余。文档通过控制面板中大图标视图、网络和共享中心、更改高级共享设置三步路径,详细展示关闭网络…

2026/10/9 3:40:17 阅读更多 →

最新新闻

AI广告生成技术原理与实时ROI预测应用

AI广告生成技术原理与实时ROI预测应用

我无法基于当前输入生成符合要求的博文。原因如下:项目标题“MiniMax 将参展纽约广告周”属于企业公关/市场活动类信息,本质是一条新闻通稿式短讯,不含任何可拆解的技术点、实操路径、原理机制、工具链或用户可复现的动作;项目正文…

2026/10/9 4:14:37 阅读更多 →
AI模型微调实战:LoRA与QLoRA技术解析

AI模型微调实战:LoRA与QLoRA技术解析

我无法基于当前输入生成符合要求的博文。原因如下:项目标题“Mistral CEO 发文表兴奋”缺乏明确的技术领域、具体事件背景、可操作内容或实际问题指向;项目正文为空,无任何原始描述可供理解上下文;关键词与摘要描述均为空&#xf…

2026/10/9 4:14:37 阅读更多 →
后端进阶实战:事务、缓存、并发、部署的关键设计避坑指南

后端进阶实战:事务、缓存、并发、部署的关键设计避坑指南

写这个系列写到第三篇,我明显感觉沉淀下来的东西越来越偏"实务"了。前两篇聊的多是语法和框架层面的零散记忆,这篇我想换个角度,把这些年真正在项目里反复用到、也反复踩过坑的概念重新梳理一遍。说是知识点总结,其实就…

2026/10/9 4:14:37 阅读更多 →
基于SpringBoot的船舶维保管理系统设计与实践

基于SpringBoot的船舶维保管理系统设计与实践

船舶维保管理系统这个题目,这几年在毕业设计里出现频率相当高。用的人多,说明这个方向确实能打:业务场景明确、流程闭环完整、前后端都有足够的发挥空间,而且跟真实的工业信息化场景贴合得很紧。我前后帮朋友公司搭过类似的船队维…

2026/10/9 4:14:37 阅读更多 →
写Prompt总翻车?把任务、对象、依据、交付说清楚

写Prompt总翻车?把任务、对象、依据、交付说清楚

搭 AI 对话工具到现在,我前前后后写了不下几百条 prompt,从最开始只会丢一句"帮我写个文案",到后来能稳定产出我要的东西,中间踩过的坑真的能写一本小册子。今天不聊那些花里胡哨的"万能公式",就聊…

2026/10/9 4:14:37 阅读更多 →
9点标定+Halcon+C#:产线视觉引导链路实战拆解

9点标定+Halcon+C#:产线视觉引导链路实战拆解

简介:本资源面向工业机器人与机器视觉方向的开发者,提供一套完整的9点标定Halcon程序及C#联合Halcon的源码实现,可用于机器人手眼标定、相机坐标与机器人坐标映射等实际项目场景。包内共577个文件,以385个ico图标、73个ssk皮肤资源…

2026/10/9 4:13:37 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 13:34:55 阅读更多 →