ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

银行客户认购预测实战:Python机器学习资源包与避坑指南

银行客户认购预测实战:Python机器学习资源包与避坑指南 简介这份资源面向希望进入金融风控与客户行为预测领域的数据科学学习者提供一套完整的银行客户认购产品预测实战方案。项目以Python为工具围绕客户年龄、职业、收入、历史营销记录等特征构建从数据清洗、类别编码、特征工程到模型训练与评估的全流程帮助读者理解哪些因素影响客户的产品订阅决策。压缩包共68个文件、约9.4MB包含5个py脚本、3个ipynb笔记本、5个csv数据集、2个pkl模型文件以及43张可视化图表和4份md说明文档覆盖数据探索、模型对比、结果输出与部署保存等环节。已有674人学习下载。读者可据此复现逻辑回归、随机森林、XGBoost等模型的训练与调参过程借助交叉验证与AUC-ROC评估模型表现并参考字段说明与README快速理解目录结构适合作为课程设计、竞赛练习或金融机器学习入门的实践案例。1. 银行客户认购预测项目一份能直接跑通的 Python 机器学习资源打开招聘 JD 搜“金融风控建模”十有八九会看到“熟悉银行客户行为预测”这一条。但真到动手时多数人卡在同一个地方手头没有一份结构完整、字段清晰、模型能复现的银行营销数据集。UCI 的 Bank Marketing 数据集虽然经典但原始字段是葡萄牙语缩写类别变量散落各处直接扔进 sklearn 会报一堆类型错误。这份bank_product_subscriptions-master资源包解决的正是这个断层——它把一份银行电话营销的客户认购数据从字段说明、预处理管道、特征工程脚本到训练好的模型文件全部打包好了。源码里包含preprocessing_pipeline.pkl和best_model.pkl两个持久化对象意味着你不需要从头训练就能直接加载推理。适合两类人一是想拿一个完整金融场景练手特征工程和模型调优的机器学习入门者二是需要快速验证“客户认购概率排序”这类排序业务逻辑的从业者。数据集、Notebook、模型文件、可视化图表都在压缩包里解压即用。2. 拆开资源包字段说明、预处理管道与模型文件怎么配合2.1 数据集字段与目标变量的业务含义dataset/train.csv和test.csv是这份资源的核心数据。从字段说明.xlsx和字段说明.png可以读出这是一份典型的银行电话营销记录每行代表一次客户接触目标变量是客户是否认购了定期存款产品二分类。字段大致分四类客户基本信息年龄、职业、婚姻状况、教育水平、账户与信用信息是否有房贷、是否有个人贷款、信用卡是否有违约、本次营销活动信息联系方式、联系月份、联系星期几、联系时长、活动期间联系次数、以及宏观经济指标就业变动率、消费者价格指数、消费者信心指数、银行同业拆借率。这里有个容易翻车的地方宏观经济指标是时间序列数据同一个季度内所有客户的取值相同。如果直接把它当普通数值特征扔进树模型模型会学到“某个月份的客户更容易认购”这种伪相关。常见做法是保留这些字段但配合时间交叉验证或者在特征工程阶段把它们转换成“相对于上一季度的变化量”。资源包里的feature_attribute.json应该就是用来标记字段类型的配置文件建议先打开看一眼每个字段被归为category还是numeric这直接决定后续编码方式。figures目录下的几十张 PNG 是很好的 EDA 参考。比如001_目标分布.png能让你一眼看出正负样本比例——银行营销数据通常正样本占比不到 15%这意味着 accuracy 是个欺骗性指标必须看 AUC 和 recall。003_联系时长正样本分布.png则暗示联系时长与认购结果强相关但要注意这个特征在预测时有数据泄漏风险只有联系结束后才知道时长如果业务场景是“联系前预测”这个字段必须剔除。2.2 预处理管道与模型加载的代码路径资源包里最值钱的是models/preprocessing_pipeline.pkl和models/best_model.pkl。前者是一个 sklearn Pipeline 对象封装了缺失值填充、类别编码、数值标准化等步骤后者是训练好的分类器。加载方式如下import pickle import pandas as pd from sklearn.pipeline import Pipeline # 加载预处理管道和模型 with open(models/preprocessing_pipeline.pkl, rb) as f: pipeline pickle.load(f) with open(models/best_model.pkl, rb) as f: model pickle.load(f) # 读取测试集 test_df pd.read_csv(dataset/test.csv) # 注意pipeline 可能已经包含了模型也可能只做预处理 # 先检查 pipeline 的最后一个步骤 print(pipeline.steps[-1]) # 如果 pipeline 只做预处理需要手动拼接 if pipeline.steps[-1][0] ! classifier: X_test pipeline.transform(test_df) pred_proba model.predict_proba(X_test)[:, 1] else: pred_proba pipeline.predict_proba(test_df)[:, 1] # 输出认购概率排序 result pd.DataFrame({ 客户索引: test_df.index, 认购概率: pred_proba }).sort_values(认购概率, ascendingFalse) print(result.head(20))这段代码的关键在于判断preprocessing_pipeline.pkl是否已经包含了最终模型。有些项目会把预处理和模型串成一个完整的 Pipeline 一起保存有些则分开存。pipeline.steps[-1]能告诉你答案。如果最后一步是classifier直接调predict_proba即可如果是scaler或encoder就需要先 transform 再交给best_model。资源包里的automatic_learning.py和test1.py应该包含了完整的训练和推理流程建议先读这两个脚本再动手改。logging/best_score_log.json记录了训练过程中的最优分数打开它能看到模型在验证集上的 AUC 或 F1。这个文件的价值在于当你自己重新训练时可以拿你的结果和它对比判断是特征工程退化了还是超参数没调好。results/submission_v1.3.csv是最终提交格式的示例两列——客户 ID 和预测概率排序业务直接按概率降序取 Top N 即可。2.3 Notebook 版本演进与特征工程脚本notebook目录下有认购产品_V1.1.ipynb、V1.2、V1.3三个版本。这种版本命名方式说明作者在迭代特征工程方案。V1.1 通常是基线版本用原始字段直接训练V1.2 可能加入了类别变量的目标编码或 WOE 编码V1.3 则可能引入了交互特征或时间窗口统计。建议按版本顺序读重点看每个版本新增了哪些特征、删除了哪些字段、AUC 提升了多少。category_bin.py和tree_transform_bin.py是两个特征工程脚本。从命名推测前者做类别变量的分箱或编码后者做树模型相关的特征变换可能是基于决策树叶节点索引的编码。这类脚本在金融风控场景很常见因为逻辑回归需要 WOE 编码而树模型可以直接处理类别变量但需要处理高基数问题。backup目录里可能有旧版本脚本如果当前脚本跑不通去 backup 里找找替代实现。3. 从零复现训练流程数据划分、模型训练与评估的完整操作3.1 环境准备与依赖安装这份资源基于 Python 生态核心依赖是 pandas、numpy、scikit-learn、matplotlib、seaborn。如果要用 XGBoost 或 LightGBM还需要额外安装。建议用 conda 创建独立环境避免和系统 Python 冲突conda create -n bank_ml python3.9 conda activate bank_ml pip install pandas numpy scikit-learn matplotlib seaborn jupyter pip install xgboost lightgbmPython 版本选 3.9 是因为 pickle 文件在不同版本间可能存在兼容性问题。如果加载best_model.pkl时报AttributeError或ModuleNotFoundError大概率是训练时的 sklearn 版本和当前环境不一致。解决办法是查看README.md里是否标注了版本号或者用pip install scikit-learn1.0.2这类方式降级。logging目录下的日志文件也可能记录了训练时的库版本。3.2 数据加载与训练集/验证集划分不要直接把train.csv全部拿来训练。银行营销数据有时间维度随机划分会导致未来数据泄漏到训练集。正确做法是按联系月份做时间序列划分比如用前 80% 月份的数据训练后 20% 月份的数据验证import pandas as pd from sklearn.model_selection import train_test_split df pd.read_csv(dataset/train.csv) # 假设目标列名为 y需要根据字段说明确认 target_col y X df.drop(columns[target_col]) y df[target_col] # 如果数据有时间列按时间排序后切分 # 这里假设没有明确时间列用随机划分做演示 X_train, X_val, y_train, y_val train_test_split( X, y, test_size0.2, random_state42, stratifyy ) print(f训练集正样本比例: {y_train.mean():.4f}) print(f验证集正样本比例: {y_val.mean():.4f})stratifyy保证训练集和验证集的正负样本比例一致。如果正样本只有 10%不加 stratify 可能导致验证集里正样本更少AUC 波动大。random_state42是为了结果可复现换成其他整数也行但全项目统一用一个值方便对比。3.3 模型训练与超参数调整资源包里已经有一个训练好的best_model.pkl但如果你想自己复现训练过程可以参考automatic_learning.py的逻辑。常见做法是用 GridSearchCV 或 RandomizedSearchCV 在随机森林、梯度提升树、逻辑回归之间做模型选择from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier from sklearn.linear_model import LogisticRegression from sklearn.model_selection import cross_val_score from sklearn.metrics import roc_auc_score models { 逻辑回归: LogisticRegression(max_iter1000, class_weightbalanced), 随机森林: RandomForestClassifier(n_estimators200, max_depth10, class_weightbalanced, random_state42), 梯度提升: GradientBoostingClassifier(n_estimators200, max_depth5, random_state42) } for name, model in models.items(): # 注意这里需要先对 X_train 做预处理 # 如果 preprocessing_pipeline 可用先 transform scores cross_val_score(model, X_train, y_train, cv5, scoringroc_auc) print(f{name} AUC: {scores.mean():.4f} (/- {scores.std():.4f}))class_weightbalanced是处理类别不平衡的常用手段它会让模型更关注少数类。但要注意如果用了这个参数预测概率的绝对值会偏移排序业务不受影响但如果你需要校准概率得额外做 Platt Scaling 或 Isotonic Regression。cross_val_score的cv5表示 5 折交叉验证数据量小的时候可以改成 10 折但计算时间会翻倍。3.4 模型评估为什么 AUC 比 Accuracy 更可靠银行营销数据的正样本比例通常低于 15%这意味着一个把所有客户都预测为“不认购”的模型accuracy 也能到 85% 以上。所以评估指标必须用 AUC、KS 或 recalltopKfrom sklearn.metrics import roc_auc_score, classification_report, confusion_matrix # 假设 y_pred_proba 是验证集上的预测概率 y_pred_proba model.predict_proba(X_val)[:, 1] y_pred (y_pred_proba 0.5).astype(int) print(fAUC: {roc_auc_score(y_val, y_pred_proba):.4f}) print(classification_report(y_val, y_pred)) print(confusion_matrix(y_val, y_pred))AUC 衡量的是模型把正样本排在负样本前面的能力对类别不平衡不敏感。如果 AUC 在 0.75 以上说明模型有实用价值0.8 以上算不错0.85 以上在银行营销场景算优秀。classification_report会输出 precision、recall、F1重点看正类的 recall——如果 recall 太低说明模型漏掉了太多潜在认购客户业务上不可接受。4. 避坑与排查加载模型、特征对齐和版本兼容的五个血泪教训4.1 加载 pkl 文件报 ModuleNotFoundError现象pickle.load时抛出ModuleNotFoundError: No module named xxx其中 xxx 可能是某个自定义模块或旧版 sklearn 的子模块。原因pickle 文件保存的是对象的序列化字节流其中包含了类所在的模块路径。如果训练时用了sklearn.ensemble._forest这种内部路径而当前 sklearn 版本重构了模块结构就会找不到。解决先确认训练时的 sklearn 版本。查看README.md或logging目录下的日志。如果找不到尝试用pip install scikit-learn1.0.2或0.24.2这类常见版本逐个试。另一个办法是用pickletools.dis查看 pkl 文件的模块引用但比较繁琐。最稳妥的方式是重新训练模型用当前环境的版本保存。4.2 特征列顺序不一致导致预测结果错乱现象模型能加载predict_proba也能跑通但预测结果和submission_v1.3.csv里的示例对不上AUC 只有 0.5 左右。原因sklearn 的 Pipeline 在 transform 时依赖列顺序。如果测试集的列顺序和训练集不一致标准化和编码会作用到错误的列上。更隐蔽的情况是训练时用了pd.get_dummies做 One-Hot 编码测试集缺少某个类别导致列数不一致。解决加载preprocessing_pipeline.pkl后先打印pipeline.feature_names_in_如果 sklearn 版本支持确认训练时的特征顺序。然后对测试集做test_df test_df[pipeline.feature_names_in_]强制对齐列顺序。如果列数不一致检查是否有类别变量在测试集中出现了训练集没有的取值需要用handle_unknownignore的 OneHotEncoder。4.3 宏观经济指标导致的数据泄漏现象交叉验证 AUC 很高0.9但上线后效果暴跌。原因emp_var_rate、cons_price_idx、cons_conf_idx、euribor3m、nr_employed这五个经济指标是季度级别的宏观数据。如果训练集和验证集按随机划分同一个季度的数据会同时出现在两边模型实际上记住了“这个季度客户容易认购”而不是学到了客户行为规律。解决按时间划分训练集和验证集。如果数据里没有明确的时间列可以根据contact月份和day_of_week构造一个近似的时间索引。另一个办法是直接剔除这五个字段只用客户级别特征训练看看 AUC 下降多少。如果下降不超过 0.02建议剔除因为宏观指标在预测新客户时不可控。4.4 联系时长字段的预测时不可用问题现象模型特征重要性排名第一的是duration联系时长但业务方说“联系前就要预测不可能知道通话多久”。原因duration是本次通话的时长只有通话结束后才能记录。如果预测场景是“在拨打电话之前决定打给谁”这个字段必须剔除。但它在训练数据里与目标变量高度相关模型会过度依赖它。解决训练时直接drop(columns[duration])重新训练并评估 AUC 下降幅度。通常 AUC 会从 0.9 降到 0.8 左右但这是真实可用的性能。资源包里的figures/002_上一次联系的时长分布.png和003_联系时长正样本分布.png能帮你直观看到这个字段的区分度但记住区分度高不等于可用。4.5 Notebook 版本与脚本不一致现象认购产品_V1.3.ipynb里跑出来的结果和automatic_learning.py不一致甚至特征列表都不同。原因Notebook 是探索性分析的产物作者可能在 Notebook 里试了新特征但没同步到脚本。backup目录里的旧脚本可能对应旧版 Notebook。解决以automatic_learning.py和models/下的 pkl 文件为准因为它们是最终产出。Notebook 用来理解思路不要直接复制代码到生产。如果发现 Notebook 里的某个特征工程技巧有效手动移植到脚本里重新训练并对比logging/best_score_log.json里的分数。5. 进阶技巧用 SHAP 解释模型与概率校准的实操模型能跑通只是第一步业务方更关心“为什么这个客户被预测为高认购概率”。SHAP 是目前解释树模型最实用的工具它能给出每个特征对单个预测的贡献值。安装shap后对best_model.pkl做解释import shap import matplotlib.pyplot as plt # 假设 model 是加载好的树模型X_val 是预处理后的验证集 explainer shap.TreeExplainer(model) shap_values explainer.shap_values(X_val) # 全局特征重要性 shap.summary_plot(shap_values, X_val, plot_typebar) # 单个预测的解释 shap.force_plot(explainer.expected_value, shap_values[0,:], X_val.iloc[0,:])shap.summary_plot的 bar 图能告诉你哪些特征整体上最重要而force_plot能展示单个客户的预测是怎么被各个特征推高或拉低的。比如某个客户被预测为高认购概率force_plot 可能显示contact_cellular手机联系和poutcome_success上次营销成功是主要推动力。这种解释可以直接拿给业务方看比“模型说概率是 0.87”有说服力得多。另一个进阶操作是概率校准。如果模型用了class_weightbalanced输出的概率是偏移的不能直接当真实认购率用。用CalibratedClassifierCV做 Isotonic 校准from sklearn.calibration import CalibratedClassifierCV calibrated CalibratedClassifierCV(model, methodisotonic, cv5) calibrated.fit(X_train, y_train) # 校准后的概率更接近真实认购率 calibrated_proba calibrated.predict_proba(X_val)[:, 1]校准后的概率可以直接用于业务决策比如“认购概率大于 0.3 的客户才分配人工坐席”。未校准的概率只能用于排序不能用于阈值切分。我自己的习惯是每次拿到一个新的 pkl 模型文件先不急着跑预测而是用pickletools看一眼它的模块依赖再用shap跑一遍全局解释确认特征重要性排名符合业务常识。如果duration排第一直接剔除重训。从那以后我每次加载外部模型文件都强制走一遍“版本检查 → 特征对齐 → 泄漏排查 → 校准验证”的流程省下了大量返工时间。希望帮到你。本文还有配套的精品资源点击获取
返回列表