ARTICLE DETAIL

资讯详情

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

国赛C题一等奖秘籍:银行信贷风险评分卡建模全流程

国赛C题一等奖秘籍:银行信贷风险评分卡建模全流程 简介面向全国大学生数学建模竞赛参赛者这里提供2020年C题国赛一等奖获奖论文及完整配套实现覆盖问题1至问题3的建模思路与求解过程适合备战数模竞赛或系统学习数学建模方法的学习者。压缩包共13个文件约1.6MB包含1篇详细论文PDF、6个Excel数据处理表格以及MATLAB和Python脚本Excel文件用于原始数据清洗、行业与规模分类等预处理脚本涉及关联规则分析、权重计算和分问题模型求解。已有15228人学习浏览资料完整度较高。借助论文可掌握问题理解、模型构建与结果阐释的规范写法借助脚本可复现数据处理与计算流程是提升建模实战能力的参考样例。 2020年国赛C题我带了两次队第一次成绩一般第二次拿到了一等奖。整理这份资料的时候我把论文、代码和Excel数据处理表格重新捋了一遍发现对大多数队伍来说真正的分水岭不是模型选得多高阶而是能不能把银行信贷业务里的“风险”翻译成数学语言。2020C题给了一堆进销项发票、企业基本信息和历史信贷记录很多人一上来就想着上XGBoosting、神经网络结果模型指标倒是不错论文却说不清为什么这样授信。下面我就顺着这份资源包的脉络把从数据清洗到额度利率决策的全过程拆开讲一遍每步都会交代我当时是怎么踩坑、怎么改的。1. 赛题回顾银行信贷决策真正要你回答的三件事1.1 数据里哪些变量是“钱”的关键信号2020年高教社杯C题背景是中小微企业向银行贷款银行手里有123家老客户的三年经营数据包括订单里的销项发票、进项发票、申报信息还有这些企业过去是否违约的标签。题目还给了304家没有标签的新客户要求你设计一套信贷策略贷不贷、贷多少、利率多少。表面上是三个独立问题本质上是一个“违约概率预测 授信策略优化”的组合。我拿到数据第一件事不是建模而是先搞明白“企业真实经营状况”藏在哪张表里。企业基本信息表只有20个字段不够支撑一个稳健模型真正有含金量的是销项和进项发票。销项发票里有每笔交易的“价税合计”“税额”“受票方信息”可以算出企业的主营业务收入进项发票能看出企业向上游采购的规模进销项比对还能反映产业链位置。我还发现发票里有大量重复抬头和负金额蓝票如果不做去重和负数剔除后面的“月均销售额”特征会直接失真所以数据处理里的“清”比“算”更关键。1.2 为什么说评分卡是这道题的最优解很多团队迷信集成学习但当年一等奖论文里几乎没有用纯黑箱模型的。银行风控讲究“可解释性”客户经理需要知道为什么降额、为什么提高利率所以逻辑回归评分卡成了这道题最稳妥的答案。评分卡用WOE编码把连续变量离散化每个变量的系数可以正向解读“月开发票次数”的系数为正说明高频小票企业经营更稳定“最大客户占比”的系数为负说明客户依赖度高的企业风险更大。这种可解释性在论文展示阶段是巨大的加分项评委不需要你讲一堆特征重要性排名一张评分分布图加一段业务逻辑就能看懂你的取舍。2. Excel数据处理表格小块头里有大文章2.1 从开票记录到企业指标我做了哪些聚合操作资源包里的Excel不是简单地塞原始数据而是按处理阶段整理了四类表01原始数据从赛题附件直接导出的进项、销项、企业信息、信贷记录。02清洗后表格去重、补缺失、剔除负金额之后的干净数据。03特征衍生表按企业代码聚合出的月均销额、销售波动率、上下游集中度等指标。04利率测算表把模型预测的违约概率和额度、利率联动起来供决策直接查看。在Excel里做聚合我用的不是VBA而是透视表和SUMIFS函数。比如要算某企业月度销售额的稳定性我会先建一列“年月”字段再用SUMIFS按企业和月份把“价税合计”求和最后用STDEV.S算这三年月度销额的标准差。Excel的好处是可视化直观任何一个中间指标都可以拉到透视表里拖一下立刻看出分布有没有异常。缺点是当企业发票超过几万条时SUMIFS会卡顿这时候就要转用Python里pandas的groupby所以资源包里Excel表格主要是“分析过程”不是最终部署版本。2.2 用透视表快速验证特征与违约的关系我强烈建议在跑复杂模型前先用透视表画几个交叉频数。做法很简单把“违约状态”拖到列区把“月均销额分段”拖到行区值区用“企业代码”的计数再右键添加一个“违约占比”字段。你会立刻看到一条清晰的规律月均销额低于3万的企业违约率可能高达35%月均销额超过20万的企业违约率不到8%。这种肉眼可见的趋势一方面帮你确认特征方向另一方面也在写论文时提供了“数据观察驱动建模”的叙事素材。Excel处理时最容易忽略的坑是数据类型。赛题附件里的“开票日期”有时候是文本格式透视表按月份分组时会按字符串拼音排序导致“2020-09”排在“2020-01”前面。处理办法是新增一列用DATEVALUE转换或者用TEXT函数规范成yyyy-mm否则后面按月聚合的结果全部错乱。3. 模型代码拆解评分卡是段位和透明度的双重胜利3.1 特征分箱与WOE/IV的计算逻辑评分卡的构建流程可以拆成五步分箱、WOE编码、IV筛选、逻辑回归、分数映射。分箱是最容易拍脑袋的步骤但也是最影响稳定性的步骤。资源包里的features.py用了等频分箱而不是等宽分箱。比如“年销售额”这一列等频分箱按样本量平均切成5段每段都有差不多数量的企业和违约样本避免某一段全是零销售额导致WOE变成无穷大。代码核心是这一段import pandas as pd import numpy as np def woe_iv_transform(df, feature, target): tmp df[[feature, target]].copy() # 等频分箱duplicatesdrop防止箱子边界重合 tmp[bin] pd.qcut(tmp[feature], q5, duplicatesdrop) grouped tmp.groupby(bin, as_indexFalse).agg( good(target, lambda x: (x 0).sum()), bad(target, lambda x: (x 1).sum()) ) grouped[good_pct] grouped[good] / grouped[good].sum() grouped[bad_pct] grouped[bad] / grouped[bad].sum() grouped[woe] np.log(grouped[bad_pct] / grouped[good_pct]) grouped[iv] (grouped[bad_pct] - grouped[good_pct]) * grouped[woe] return grouped这段代码最后返回的IV值就是变量筛选的依据。当时我看到“进项税额同比增速”的IV只有0.02几乎等于不区分好坏客户直接扔掉了。“开票金额最大值”的IV有0.45于是留下来当主特征。注意训练集和测试集共享同一套分箱边界而不是各自分箱否则训练和预测的WOE区间对不上这属于评分卡实现的“暗坑”。我的做法是在训练集上生成分箱边界后用pd.cut直接映射到测试集确保口径一致。3.2 Logistic回归训练与系数校准分箱后每个原始特征变成了一个WOE数值列。接下来用逻辑回归训练违约概率。资源包里的model_train.py用的是LogisticRegression并设置了class_weightbalanced因为123家企业里实际违约的只有将近三成不调权重的话模型会倾向于把所有样本都预测为不违约。训练后我做了两件事才敢把模型放进口径里。第一件事是看每个变量的系数符号是否符合业务直觉。比如“销项发票总数”的系数应该是负数因为开票次数越多、经营活跃度越高违约风险越低如果跑出来是正数说明前面特征工程里某个环节出了问题比如把行业分组放错了。第二件事是计算KS和AUC我在交叉验证里得KS大约0.36AUC 0.81在只有一百多个样本的情况下已经算不错了足以支撑论文里的“模型具有区分度”这个结论。评分映射公式我采用标准的Score Offset - Factor * log(odds)其中odds P/(1-P)。我设基准分600分对应odds为1:1PDO20即分数每降低20分odds变为原来的2倍。这样换算后每个企业有一个300~900的分数银行可以按分数段直接划分风险等级后续授信决策直接用分数段来走规则而不是把一串浮动的概率拿给人看。4. 信贷额度与利率决策不只是模型的功劳4.1 违约概率如何映射到额度上限模型输出的是违约概率PD但银行需要的是一笔具体的钱。题目没有提供抵押物信息所以额度只能从企业经营能力向上限约束。我用了一个复合公式可授信基数 min(近一年净销额 × 行业周转系数, 上年进项税额 × 10)行业周转系数我按题目给的行业分类设定制造业0.6、批发零售业0.4、其他0.5原则是重资产行业可以贷更多轻资产纯贸易类要压降额度。然后考虑到违约风险实际建议额度 可授信基数 × (1 - PD) × 风险偏好系数。风险偏好系数我自己调成0.85代表银行整体偏保守如果想要收益更高可以调高到1.1但论文里要说明这个系数的敏感性分析不能干巴巴写一个常数。这个公式的好处是每一个乘子都有业务解释“净销额”代表企业还款能力“(1-PD)”代表风险折扣风险偏好系数代表银行态度。评委看到这种公式第一反应是你理解了业务而不只是套模型。4.2 利率定价风险补偿加行业调价利率定价是整道题里最容易扯皮的部分。我在资源包Excel的“利率测算表”里建立了一个绑定逻辑基准利率4.35%当PD在0.1以下时利率上浮20%PD在0.1到0.2之间上浮60%PD超过0.2直接拒贷。这只是一个简化版本但已经足够丰富。更严谨的做法是用预期损失覆盖法先设LGD0.45那么给定PD预期损失率ELPD×LGD。如果某家企业PD为0.15预期损失率是6.75%而银行资金成本是3%目标净息差是2.5%那么最低贷款利率就要12.25%才能达到收益目标低于这个数就不如不做这笔业务。我知道这个利率乍看很高确实因为这是只考虑违约损失、还没算运营成本和资金占用成本的上限。实际论文里可以把LGD拆成“抵押不足折损”和“追偿成本”两部分话术自然展开。更重要的是决策时不能一家一家看利率要看整体组合利润。我在代码里写了一个贪心分配先给PD最低额度最大的优质客户放贷再逐步释放剩余资金给次优客户这一步与后面的线性规划优化模型形成对照证明简洁启发式也能接近最优解。5. 论文写作中那些隐性加分项5.1 三线表与流程图之外的“美感”国赛论文评阅时间是每篇十几分钟评委最怕看到大段文字堆叠。资源包里的那篇一等奖论文我认为做得最好的地方是两张图一张是数据清洗流程流转图从原始发票到特征表每个节点都标注了处理函数名和处理后行数另一张是评分分数分布直方图横坐标是分数段纵坐标是客户数量把违约客户和非违约客户用两种颜色堆叠展示。这两张图的信息量非常大评委一眼就能看出你的数据经过了完整清洗、你的模型确实能把好坏客户分开。写公式时我也吃过亏。第一次用Word公式编辑器结果公式编号总对不齐转成PDF后会跳行。后来改用LaTeX写数学公式再导出PDF交叉排版公式字体和编号都自然统一。资源包里可以放一份公式模板.tex大家直接替换参数就行不用从零搭环境。5.2 稳健性检验评审最常挑刺的地方很多队伍只给出一张模型参数表就完事了评委问一句“你的结论对分箱数变化敏感吗”就直接卡壳。我在论文里专门加了一节“稳健性检验”内容分三段第一段把原始特征分箱数从5换成4和6重新跑模型观察KS波动不超过±0.02。第二段用Bootstrap随机抽样80%的样本训练10次记录预测违约率均值和标准差。第三段逐次剔除IV排名第一的特征看模型AUC下降幅度证明模型没有依赖某个单一变量。这三项实验加起来只占论文不到一页但把论文的“工程完成度”直接拉高一个档次。评审看到你不是只做了一遍而是系统验证过自然愿意给高分。给后来者的建议不要迷信“调参魔改”国赛论文看重的是逻辑完整性。图表格式统一、公式编号规范、结论从实验数据里生成这三点比任何炫技都能拉开差距。6. 资源包应该怎么用别让一等奖论文在磁盘里睡觉6.1 文件结构与阅读顺序我整理资料时按以下目录结构打包│ README.md │ ├─ 论文 │ 2020C题一等奖论文.pdf │ 公式模板.tex │ ├─ 代码 │ main.py │ data_clean.py │ feature_engineering.py │ model_train.py │ decision_strategy.py │ requirements.txt │ └─ Excel数据处理 01原始数据/ 02清洗后表格/ 03特征衍生表/ 04利率测算表/阅读顺序我建议是先花一晚上通读论文重点不看代码而是看他们从“问题分析”到“模型假设”再到“求解”的结构安排然后用Excel打开特征衍生表手动挑一家企业在原始表里验证它的“月均销额”和“销项发票数量”是否对得上最后再跑代码。跑代码不要用IDE直接运行要先用命令行激活虚拟环境安装依赖再逐步打断点观察data_clean.py输出的中间文件。如果时间有限至少要把README.md看完。里面记录了每个脚本的输入输出文件名、运行耗时和需要注意的硬编码路径比如file_path D:/...这样的地方必须改成自己的目录否则一运行就崩溃。6.2 避免直接照搬代码的四个原则第一条资源包里的Excel特征是基于当年赛题数据手工核过的你换任何新题都必须重新构造特征哪怕业务场景看起来类似。第二条代码里强制固定了随机种子这一点非常关键否则你每次运行结果不同论文里写AUC0.81答辩现场跑出0.79尴尬得没法收场。第三条不要因为代码能跑就以为逻辑没问题逻辑回归的系数符号是否合理永远要放在第一位我见过有人把“违约标签”编码反了导致所有系数符号颠倒模型表现却因为数据对称性依旧“好看”。第四条当你参考论文里的分数阈值时一定要先确认用的是训练集还是全量数据的分数分布来定的阈值不同口径会直接影响最终拒贷名单。数学建模不是下载一个zip然后祈祷交上去就能拿奖。拿到这份资源包正确的姿态是“读懂它、复现它、超越它”。那些真正打开过Excel逐格核对、把代码里每一个groupby和fillna都问过为什么的队伍才会在一等奖论文的基础上写出属于自己的东西。本文还有配套的精品资源点击获取
返回列表