ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python机器学习贷中风险预测模型源码:特征工程与多模型对比实战

Python机器学习贷中风险预测模型源码:特征工程与多模型对比实战 简介这份资源是面向计算机相关专业学生与项目实战学习者的贷中风险预测完整项目包以Python机器学习为核心围绕金融大数据建模赛题展开适合用作毕业设计、期末大作业或技能进阶练习。包内共50个文件涵盖19个py脚本、11个csv数据集、5个ipynb笔记本、4个docx文档、3个xlsx表格及2个pptx答辩演示等压缩包约10.83MB源码均经本地编译调试可运行。项目包含赛题方案文档、数据字段说明、特征工程与多模型对比代码涉及逻辑回归、XGBoost、LightGBM、随机森林、朴素贝叶斯等多种算法实现并配有答辩PPT与结果输出文件便于理解完整建模流程。已有62人学习评审分98分适合需要参考高分项目结构、学习特征提取与模型调优思路的读者下载使用。1. 贷中风险预测这套源码到底能帮你省下多少造轮子的时间做过信贷风控建模的人都知道真正难的不是把模型跑起来而是把散落在申请、客户信息、贷款流水、征信几张表里的字段拼成一张能进模型的宽表。这套「python基于机器学习的贷中风险预测模型」源码包解决的正是这个环节——它来自 2020「江苏银行杯」金融大数据建模挑战赛的初赛作品把贷中风险预测的完整链路拆成了可运行的 Python 脚本和 Notebook。适合两类人一是正在做机器学习、金融风控方向毕业设计或期末大作业的学生需要一份结构完整、能跑通、有答辩 PPT 的参考项目二是想练手特征工程和集成模型的从业者想看看别人怎么把多表关联、特征衍生、多模型对比串成一条流水线。包里 src 目录下既有 handle_apply.py、handle_credit.py 这类数据清洗脚本也有 feature_engineering.ipynb 和 models 目录下 lgb.py、_xgb.py、randomforest.py 等一堆模型实现还有两份答辩 PPT 和赛题文档属于少见的「代码 文档 汇报材料」三件套齐全的资源。2. 先看懂数据结构和建模链路贷中预测和贷前到底差在哪2.1 贷中风险预测的业务定位贷前预测回答的是「这个人该不该放款」贷中预测回答的是「已经放出去的这笔贷款未来会不会逾期」。这个区别直接决定了标签和特征窗口的构造方式。贷中场景下你手里已经有客户的放款记录、还款流水、历史征信查询特征更多来自「行为」而不是「资质」。这套源码里 label.csv 存标签apply.txt、customer_information.txt、credit.txt、flow_chart.txt 分别对应申请信息、客户信息、征信、流水四类原始数据handle_*.py 系列脚本就是把这些 txt/csv 清洗成可用的结构化表。理解这个业务定位你才知道为什么特征工程里会有那么多基于时间窗口的统计量而不是简单地把静态属性拼一起。2.2 从原始表到宽表的处理链路整个链路可以拆成四步原始数据读取 → 单表清洗 → 多表关联 → 特征衍生。merge.py、merge_test.py、merge_task.ipynb 负责关联handle_apply.py、handle_customer_information.py、handle_credit.py、handle_flow_chart.py 负责单表清洗feature_engineering.ipynb 负责衍生。常见做法是先用 pandas 把每张表按主键去重、缺失填充、类型转换再以申请表为主表 left join 其余表。下面这段是我按这套脚本的套路还原的单表清洗骨架你可以对照 handle_apply.py 看它的真实写法import pandas as pd import numpy as np # 读取申请信息表原始为制表符分隔 apply pd.read_csv(apply.txt, sep\t, encodingutf-8) # 主键去重同一客户多次申请只保留最新一条 apply apply.sort_values(apply_time).drop_duplicates(cust_id, keeplast) # 缺失值处理数值型填中位数类别型填众数 num_cols apply.select_dtypes(include[np.number]).columns cat_cols apply.select_dtypes(include[object]).columns apply[num_cols] apply[num_cols].fillna(apply[num_cols].median()) for c in cat_cols: apply[c] apply[c].fillna(apply[c].mode()[0]) # 类型转换把申请时间转成标准 datetime方便后续算账龄 apply[apply_time] pd.to_datetime(apply[apply_time], errorscoerce) print(apply.shape, apply[cust_id].nunique())逻辑说明先去重保证一个客户一行避免关联后行数爆炸缺失填充用中位数和众数是最稳的兜底策略比直接 dropna 保留更多样本。参数上keeplast表示保留时间最新的一条如果你的业务是保留首次申请改成keepfirst。errorscoerce让非法时间变成 NaT 而不是直接报错方便后面统一处理。跑完这一步你应该能看到清洗后的行数和唯一客户数两者差距大就说明去重逻辑有问题。2.3 多表关联的主键与粒度对齐merge.py 的核心是确定关联主键和粒度。申请表、客户信息表一般以 cust_id 为主键征信和流水表可能一个客户多条记录直接 join 会导致行数膨胀。正确做法是先对多记录表做聚合比如按客户算流水笔数、征信查询次数再关联。这一步是整条链路最容易翻车的地方粒度没对齐后面模型指标全是假的。建议在 merge 之后立刻打印df.shape和df[cust_id].nunique()确认没有意外膨胀。3. 特征工程怎么落地从流水和征信里榨出可用变量3.1 时间窗口类特征的构造思路贷中场景最有价值的特征往往带时间属性近 3 个月查询次数、近 6 个月最大逾期天数、放款至今的账龄。feature_engineering.ipynb 里大量用到这类窗口统计。构造方法通常是先按客户分组再用 rolling 或条件筛选算聚合值。下面这段演示如何从贷款流水里算「近 N 期还款表现」import pandas as pd flow pd.read_csv(handle_flow_chart.csv) # 统一时间字段 flow[repay_time] pd.to_datetime(flow[repay_time], errorscoerce) # 按客户分组算历史逾期次数和最大逾期天数 flow_agg flow.groupby(cust_id).agg( overdue_cnt(overdue_days, lambda x: (x 0).sum()), max_overdue(overdue_days, max), repay_cnt(repay_time, count), last_repay(repay_time, max) ).reset_index() # 账龄最近一次还款距今天数 flow_agg[days_since_last] (pd.Timestamp(2020-06-30) - flow_agg[last_repay]).dt.days print(flow_agg.describe())逻辑说明groupby(cust_id)把流水粒度压到客户粒度这是关联前必须做的。lambda x: (x 0).sum()统计逾期次数比直接 sum 更稳因为逾期天数是连续值。days_since_last用固定基准日算账龄基准日要选在训练集时间范围内否则会引入未来信息。参数上overdue_days字段名要和你实际数据对齐如果原始字段叫别的名字改这里即可。跑完看 describe如果 max_overdue 出现异常大值先查是不是有脏数据没清。3.2 类别特征的编码与分箱apply 和 customer_information 里有大量类别字段比如职业、学历、婚姻状态。直接 one-hot 维度会炸常见做法是先用频次编码或目标编码压维度再对高基数类别做分箱。这套源码里没有用太复杂的编码器主要是 map 和 cut。我的习惯是低基数少于 10 类用 one-hot高基数用频次编码连续变量用等频分箱。分箱时注意边界要基于训练集确定再应用到测试集否则测试集的箱边界会泄露信息。3.3 特征筛选与多重共线性处理特征不是越多越好。feature_engineering.ipynb 里应该有一版基于 IV 值或树模型重要性的筛选。实操中我会先跑一遍 LightGBM看 feature_importance把重要性接近 0 的删掉再检查两两相关系数超过 0.9 的变量保留业务含义更清晰的那个。这一步能明显降低过拟合风险也能让答辩时讲特征逻辑更清楚。注意筛选要在训练集上做别拿全量数据筛完再切分那是典型的泄露。4. 多模型对比与调参为什么包里塞了七八个模型脚本4.1 models 目录下的模型清单与选型逻辑models 目录里有 dtc.py决策树、lgb.py 和 _lgb.pyLightGBM、_xgb.pyXGBoost、randomforest.py随机森林、AdaBoost.py、_GBDT.py、MNBC.py 和 _GaussianNB.py朴素贝叶斯。塞这么多模型不是为了炫技而是为了在答辩时展示「多模型对比 择优」的完整思路。金融风控表格数据里LightGBM 和 XGBoost 通常是效果最好的随机森林和 GBDT 作为 baseline朴素贝叶斯用来做快速验证。选型逻辑是先用朴素贝叶斯跑通流程验证特征有效性再用树模型调参冲指标最后用集成或 stacking 看能不能再涨一点。4.2 LightGBM 训练脚本的关键参数以 lgb.py 为例核心是构造 Dataset、设参数、交叉验证。下面是我按这套脚本风格整理的训练骨架import lightgbm as lgb from sklearn.model_selection import StratifiedKFold import pandas as pd import numpy as np train pd.read_csv(train.csv) test pd.read_csv(test.csv) features [c for c in train.columns if c not in [cust_id, label]] # 五折分层交叉验证保证每折正负样本比例一致 skf StratifiedKFold(n_splits5, shuffleTrue, random_state42) oof np.zeros(len(train)) pred np.zeros(len(test)) params { objective: binary, # 二分类任务 metric: auc, # 风控常用 AUC 评估 learning_rate: 0.05, # 学习率调小更稳但更慢 num_leaves: 31, # 叶子数控制模型复杂度 max_depth: -1, # 不限制深度靠 num_leaves 控 feature_fraction: 0.8, # 特征采样防过拟合 bagging_fraction: 0.8, min_data_in_leaf: 50, # 叶子最小样本防过拟合关键参数 verbose: -1 } for fold, (tr_idx, va_idx) in enumerate(skf.split(train[features], train[label])): tr_x, va_x train.iloc[tr_idx][features], train.iloc[va_idx][features] tr_y, va_y train.iloc[tr_idx][label], train.iloc[va_idx][label] dtrain lgb.Dataset(tr_x, tr_y) dvalid lgb.Dataset(va_x, va_y) model lgb.train(params, dtrain, num_boost_round1000, valid_sets[dvalid], callbacks[lgb.early_stopping(50)]) oof[va_idx] model.predict(va_x, num_iterationmodel.best_iteration) pred model.predict(test[features], num_iterationmodel.best_iteration) / 5 print(OOF AUC:, roc_auc_score(train[label], oof))逻辑说明分层交叉验证保证每折正负样本比例和整体一致风控数据正样本少不分层会导致某折正样本极少。early_stopping(50)表示验证集指标 50 轮不提升就停防止过拟合。min_data_in_leaf50是防过拟合的关键样本少的时候可以调到 20 到 30。feature_fraction和bagging_fraction都设 0.8是常用的折中值。跑完看 OOF AUC如果低于 0.7先回去查特征工程别急着调参。4.3 模型评估指标与阈值选择风控模型不能只看 AUC。AUC 衡量排序能力但实际业务要定一个阈值把客户分成通过和拒绝。常见做法是看 KS 值或者按通过率反推阈值。这套源码的 result.csv 和 result.xlsx 应该存了预测结果。实操中我会同时输出 AUC、KS 和按 5% 通过率下的坏账捕获率答辩时这三个指标一起讲比单说 AUC 有说服力。阈值选择要基于业务成本不是越高越好。5. 避坑与常见问题排查跑不通多半是这几个原因5.1 中文路径和编码导致读取失败现象运行 handle_apply.py 时报 UnicodeDecodeError 或 FileNotFoundError。原因原始 txt 文件可能是 GBK 编码或者路径里有中文Windows 下 pandas 读取容易出问题。解决读取时显式指定encodinggbk或encodingutf-8-sig路径尽量改成纯英文或者用os.path.join拼接避免转义。5.2 多表关联后行数暴涨现象merge 之后 df.shape 从几万变成几十万。原因被关联表里一个客户有多条记录没做聚合直接 join。解决关联前先对多记录表按 cust_id 做 groupby 聚合或者用drop_duplicates保留一条关联后立刻检查nunique是否和主表一致。5.3 训练集测试集特征分布不一致现象本地交叉验证 AUC 很高但测试集预测结果全是一个值。原因特征工程里用了全量数据算统计量比如均值、分箱边界导致测试集信息泄露到训练集。解决所有统计量只在训练集上 fit再 transform 到测试集用 sklearn 的 Pipeline 能强制这个顺序。5.4 正负样本极度不平衡导致模型摆烂现象模型把所有样本都预测为负类AUC 接近 0.5。原因风控数据正样本通常只有几个百分点模型学不到正类模式。解决LightGBM 里设is_unbalanceTrue或scale_pos_weight或者用欠采样/过采样。注意别在交叉验证前做采样要在每折训练集内部做。5.5 Notebook 里的执行顺序依赖现象单独跑 feature_engineering.ipynb 报变量未定义。原因Notebook 依赖前面 cell 的中间变量跳着跑就断。解决从上到下 Restart Run All 跑一遍或者把关键中间结果落盘成 csv脚本之间用文件传递而不是内存变量。6. 答辩 PPT 和文档怎么用把代码讲成故事的两个技巧答辩 PPT 有两份一份是「大佬的ppt特征提取十分值得学习.pptx」一份是「风险模型预测-最终版.pptx」。前者重点看特征提取的讲解逻辑后者看整体结构。我的经验是答辩时评委最想听的不是你用了多复杂的模型而是「你为什么这么选」。第一个技巧把特征工程讲成业务故事。比如「近 3 个月征信查询次数多说明客户资金紧张违约概率高」比干讲 IV 值有说服力。第二个技巧准备一页模型对比表把每个模型的 AUC、KS 列出来说明为什么最终选 LightGBM而不是只放一个最终结果。模型脚本适用场景调参重点朴素贝叶斯MNBC.py / _GaussianNB.py快速验证特征有效性几乎不用调决策树dtc.py可解释性要求高max_depth、min_samples_leaf随机森林randomforest.pybaseline 对比n_estimators、max_featuresGBDT_GBDT.py中小规模数据learning_rate、n_estimatorsXGBoost_xgb.py冲指标max_depth、subsampleLightGBMlgb.py / _lgb.py大规模表格数据首选num_leaves、min_data_in_leaf验证方法上我一般会做两件事一是把 OOF 预测结果按分数分十档看每档的实际坏账率是否单调单调性好的模型业务上更可信二是拿测试集跑一遍确认预测分布和训练集没有明显偏移。如果十档坏账率不单调说明模型过拟合或者特征有问题得回去查。从那以后我每次拿到这种多表关联的风控项目都强制先跑一遍「关联后行数检查 训练测试分布对比」这两个检查能挡掉八成翻车。希望帮到你。本文还有配套的精品资源点击获取
返回列表