
1. 项目概述一次完整的数学建模竞赛实战复盘2020年的全国大学生数学建模竞赛C题题目是“中小微企业的信贷决策”。这个题目一出来当时我们团队的微信群就炸了。为什么因为它太“接地气”了。不像一些纯理论推导或者物理仿真题这道题直接把我们拉进了银行信贷部门面对的是123家真实或模拟真实的中小微企业手里有他们的进销发票、信贷记录甚至还有突发公共事件比如疫情的影响。我们的任务就是扮演“银行风控AI”给这些企业打分、定额度、做决策。这不仅仅是数学更是经济学、管理学、数据分析的交叉实战。今天我就以当年参赛者的身份抛开那些官方论文的“八股”格式从头到尾拆解我们队当时拿了国一解决这道题的完整思路、核心模型、编程实现以及那些踩过的坑和灵光一现的技巧。无论你是正在备赛的学弟学妹还是对数据建模感兴趣的朋友这篇复盘都能给你一套可以直接“抄作业”的方法论。2. 核心问题拆解从银行风控视角看题目拿到题目切忌一头扎进数据里。第一步永远是站在出题人或者说问题所有者的角度把大问题拆解成一个个可量化、可建模的子问题。2020年C题的本质是一个基于时序交易数据的信用风险评估与信贷策略优化问题。2.1 题目给出的“棋盘”与“棋子”题目数据就是我们的棋盘和棋子必须吃透企业信息123家企业的代号、类型如零售、科技等。这是静态标签。进项发票企业作为购买方收到的发票。核心字段日期、金额、税额、销方单位谁卖给我的。这笔数据的关键在于刻画企业的“采购行为”和“现金流流出”。一个健康的企业其采购应该有规律、合作方稳定。销项发票企业作为销售方开出的发票。核心字段日期、金额、税额、购方单位我卖给谁。这笔数据是企业的“生命线”直接反映其经营能力、营收状况和现金流流入。信贷记录部分企业有历史信贷记录包括贷款金额、违约情况。这是宝贵的“标签”数据用于训练和验证我们的风险评估模型。突发因素题目提到了突发公共事件如疫情对企业的可能影响。这要求模型不能是静态的必须具备一定的抗冲击韧性或情景分析能力。2.2 我们需要回答的“四道大题”题目要求最终输出四个结果这就是我们建模的四个核心目标企业信贷风险量化对123家企业分别给出一个信用评分或风险等级如A、B、C、D。这是所有后续决策的基础。信贷额度策略制定在银行总信贷额度固定的约束下如何给每家企业分配贷款额度风险低的可以多给但也要考虑其实际需求营收规模。利率浮动策略不同风险等级的企业应该适用怎样的贷款利率高风险高收益但也要考虑企业承受力和市场竞争力。突发情景下的策略调整如果发生突发公共事件上述策略应该如何动态调整这是体现模型实用性和创新性的关键。我们的整体思路就是从数据中提炼特征 → 构建风险评估模型 → 基于风险评分进行额度与利率的优化决策 → 引入外部冲击进行稳健性测试与策略调整。3. 特征工程从发票流水到企业“体检报告”这是整个项目最耗时、最见功底也最容易出彩的部分。原始发票数据是流水账我们需要把它加工成能描述企业健康状况的“指标”。我们团队当时构建了四大类特征超过50个具体指标。3.1 经营规模与稳定性特征这类特征直接从发票的金额和时间序列中提取。营收能力基于销项发票。计算月度、季度总销售额、平均每笔销售额。我们不仅算均值还算了变异系数标准差/均值用来衡量营收的波动性。一个波动巨大的企业风险显然更高。采购规模基于进项发票。计算月度采购总额、平均采购额。同时我们计算了“进销比”采购额/销售额的时序均值与波动用来判断企业是处于扩张期进销比高还是收缩期。业务活跃度计算每月有交易的天数、每月发票张数。一个健康的企业应该有持续、稳定的交易活跃度而不是某个月爆单、下个月归零。实操心得直接对原始金额加总会有问题。因为发票数据包含“作废发票”和“负数发票”红冲。我们的预处理第一步就是清洗掉状态为“作废”的发票并将负数发票视为冲减在按企业-月份汇总时进行正负抵消。这一步没做好后续所有金额特征都会失真。3.2 上下游关系与网络特征这是本题的亮点所在。企业不是孤立的它的合作伙伴上下游质量深刻反映了其自身风险。供应商集中度统计进项发票中前N大供应商的采购额占比如赫芬达尔指数HHI。如果一家企业超过80%的采购都来自单一供应商那么该供应商出问题这家企业立刻就会陷入困境风险极高。客户集中度同样统计销项发票中前N大客户的销售额占比。客户集中度高意味着对少数大客户依赖严重抗风险能力弱。合作伙伴稳定性计算每个合作方供应商或客户的合作时长首次交易到最后一次交易、合作频率。我们构建了一个“稳定合作方占比”指标合作时长超过6个月且交易频率高于月均1次的合作方数量占总合作方数量的比例。交易网络位置我们将所有企业及其交易对手部分对手不在123家企业内视为节点交易关系视为边构建了一个有向加权交易网络。然后为每个企业计算了网络中心性指标如度中心性连接数、加权入度/出度采购/销售总额、介数中心性是否处于关键枢纽位置。我们发现在网络中处于核心位置的企业其经营往往更稳定。3.3 财务健康度与欺诈风险特征这部分需要一些财务知识从发票数据中模拟财务指标。现金流健康状况这是核心中的核心。我们模拟了企业的月度经营性现金流净额 月度销项总额 - 月度进项总额。然后计算了现金流波动率、现金流为负的月数占比、最大连续现金流为负月数。连续多月现金流为负是破产的强烈先兆。发票行为异常检测大额发票突增某个单月出现远超历史平均水平的大额销项发票可能是突击营收粉饰报表也可能是虚假交易。小额高频发票存在大量金额极小、频率极高的发票可能是拆单行为值得警惕。交易时间异常大量交易发生在深夜或节假日可能涉及非正常经营。关联交易圈利用企业代号和交易对手名称通过名称模糊匹配如包含相同关键字和交易闭环检测尝试识别潜在的关联企业群。关联企业间互开发票虚增营收是常见的欺诈手段。税务相关特征计算增值税税负率应纳税额/销售额的时序均值和波动。税负率异常偏低或波动巨大可能暗示财务问题。3.4 宏观与突发情景特征为了应对题目中的“突发公共事件”我们引入了外部和衍生特征。行业韧性标签我们根据企业名称和经营类型手动结合常识或利用简单关键词匹配将其归入“受影响严重行业”如线下餐饮、旅游、“受影响一般行业”如零售、“受益或影响较小行业”如在线教育、医疗物资。这是一个0-1哑变量或有序分类变量。疫情期间行为模式我们假设了2020年1-3月为“突发期”。计算了企业在“突发期”相对于“突发前期”如2019年10-12月的关键指标变化率如销售额变化率、采购额变化率、活跃交易天数变化率。抗跌甚至增长的企业韧性更强。4. 风险评估模型构建从特征到信用分特征准备好后就是选择模型进行“学习”和“预测”。我们采用了“分阶段、多模型融合”的策略以兼顾可解释性和预测精度。4.1 第一阶段基于专家规则的初步筛选硬门槛在动用复杂模型前我们先设置了一些“一票否决”或“高风险警示”规则。这类似于银行信贷的初筛。规则1连续现金流断裂。如果企业历史数据中出现连续4个月及以上经营性现金流为负直接标记为“高风险(D级)”。因为这种情况在现实中极难持续经营。规则2严重欺诈嫌疑。如果企业被检测出存在高度疑似关联交易闭环且该闭环内交易额占其总销售额比例超过50%标记为“高风险(D级)”。规则3客户/供应商极度集中。如果最大客户销售额占比 80% 或最大供应商采购占比 80%标记为“中高风险(C级)”。这些规则筛出的企业后续模型可能会“救”回来但我们必须给予极高权重。这保证了模型的风险厌恶底线。4.2 第二阶段机器学习模型量化评分对于通过初筛的企业我们使用有信贷记录的企业的数据作为训练集构建监督学习模型。这里有几个关键选择模型选型我们没有选择当时最火的深度神经网络而是选择了LightGBM。原因有三第一我们的特征大部分是数值型和类别型表格数据正是树模型的强项第二LightGBM训练速度快能高效处理上百个特征第三模型具备一定的可解释性可以通过特征重要性排序这对金融风控场景至关重要。标签构造题目给出的信贷记录是“是否违约”。我们将其直接作为二分类标签0未违约1违约。同时为了得到更精细的评分我们也尝试了基于信贷金额和期限构造的“违约损失率”作为连续型标签进行回归但最终发现分类模型更稳定。特征选择在训练前我们使用了基于LightGBM内置的特征重要性gain排序并结合了SHAP值分析。SHAP值能告诉我们每个特征对于单个预测结果的贡献方向和大小。我们剔除了重要性接近零且SHAP值分布混乱的特征防止过拟合。处理样本不均衡违约企业是少数。我们使用了SMOTE过采样与随机欠采样结合的方法在训练集中平衡正负样本并在验证时使用AUC-PR精确率-召回率曲线下面积作为主要评估指标因为它对不均衡数据更敏感。训练好的LightGBM模型会输出每个企业“违约”的概率。我们将这个概率映射到0-100分概率越低分数越高。这就是我们的核心信用分S_core。4.3 第三阶段引入突发情景调整因子信用分S_core是基于历史数据的“静态”评分。我们需要一个调整因子F_shock来反映突发公共事件的影响。 我们设计了一个简单的加权调整公式S_final S_core * (1 - α) S_resilience * α其中S_resilience是抗冲击韧性得分由“行业韧性标签”权重0.4和“疫情期间行为模式变化率”权重0.6综合计算得出。行为模式中销售额降幅小、活跃度保持好的企业得分高。α是调整系数模拟事件的严重程度。在基准情景下设α0.2即历史信用占80%抗冲击能力占20%在严重冲击情景下可调高至α0.4甚至更高。最终我们根据S_final的分布进行分箱确定了A、B、C、D四个风险等级。5. 信贷策略优化额度与利率的数学规划有了风险等级接下来就是制定策略。这本质上是一个带约束的资源优化分配问题。5.1 信贷额度分配模型银行总信贷额度为1亿元题目假设。我们的分配原则是风险越低、经营规模越大需求越大的企业获得额度应越多。 我们建立了一个优化模型目标最大化总预期收益或最小化总预期风险。决策变量给每家企业i分配的额度L_i。约束条件总额度约束ΣL_i ≤ 总额度1亿非负约束L_i ≥ 0企业需求上限约束L_i ≤ k * 该企业年均销售额。这里k是一个系数如0.3表示银行通常不会给予超过企业年销售额一定比例的贷款这是基于“实际需求”的风控。风险等级额度指引约束例如D级企业额度为0C级企业单户额度不超过100万等这些阈值需要根据历史数据和政策设定。目标函数的具体形式我们尝试了两种最大化风险调整后收益Max Σ [L_i * r_i - L_i * PD_i * LGD_i]。其中r_i是给企业i的利率与风险挂钩PD_i是违约概率来自模型LGD_i是违约损失率假设值。这个函数直接最大化银行的期望利润。最大化信贷覆盖质量Max Σ [L_i * (1 - PD_i) / (该企业所属等级的平均PD)]。这个函数倾向于把额度更多地分配给违约概率低的企业同时考虑了同等级内的差异更侧重于资产质量。我们使用线性规划或简单的启发式算法如按(1-PD_i)*年销售额排序后按比例分配来求解。最终采用了后者因为更直观且结果易于解释。5.2 差异化利率定价模型利率r_i需要与风险等级挂钩同时考虑基准利率和银行的目标收益。 我们采用了基准利率加点模型r_i r_base spread_grade β * (PD_i - PD_grade_avg)其中r_base央行基准利率或银行资金成本。spread_grade根据风险等级设定的固定利差。例如A级1% B级2% C级4% D级不贷款。PD_i企业i的个体违约概率。PD_grade_avg该企业所属风险等级的平均违约概率。β调节系数。这一项β * (PD_i - PD_grade_avg)实现了等级内的进一步差异化定价。同一个B级里违约概率偏高的企业利率会再上浮一点更精确地反映风险。5.3 突发情景下的策略调整当突发公共事件发生时我们的策略不是推倒重来而是进行参数调整额度调整降低高风险行业如餐饮旅游企业的需求上限系数k甚至暂时将其设为0抽贷或停贷。同时可以适当提高抗冲击行业如医疗、在线服务的系数k。利率调整整体上浮spread_grade以覆盖系统性风险上升带来的潜在损失。但对于韧性得分S_resilience特别高的企业可以给予一定的利率优惠如减少spread_grade加点作为支持。引入临时性宽限政策在模型中可以为受冲击严重但历史信用良好的企业A、B级设计一个“观察期”在观察期内不立即下调其信用等级或额度而是观察其后续数据恢复情况。这需要在动态监控框架下实现。6. 编程实现、可视化与论文写作要点6.1 数据处理与特征工程代码框架我们主要使用Python的Pandas和NumPy。核心代码结构如下import pandas as pd import numpy as np # 1. 数据加载与清洗 df_in pd.read_excel(进项发票.xlsx) df_out pd.read_excel(销项发票.xlsx) # 清洗作废发票、处理负数发票 df_in_valid df_in[df_in[发票状态] ! 作废] df_in_valid[金额] df_in_valid[金额].abs() # 假设负数发票已单独处理 # 2. 按企业-月份聚合生成基础特征 def create_monthly_features(df, prefix): df[月份] df[开票日期].dt.to_period(M) monthly df.groupby([企业代号, 月份]).agg({金额:sum, 税额:sum}).reset_index() # 计算月度销售额/采购额环比同比等... return monthly_features # 3. 构建上下游网络特征使用networkx import networkx as nx G nx.DiGraph() # 添加节点和边权重为交易金额 # ... 构建网络代码 # 计算每个企业的网络中心性 centrality nx.degree_centrality(G) betweenness nx.betweenness_centrality(G, weightamount) # 将中心性指标合并到企业特征表 # 4. 特征合并与最终数据集构建 all_features pd.merge(scale_features, network_features, on企业代号, howleft) all_features pd.merge(all_features, financial_features, on企业代号, howleft)6.2 模型训练与评估import lightgbm as lgb from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report, roc_auc_score, average_precision_score # 准备数据 X all_features.drop([企业代号, label], axis1) # label来自信贷记录 y all_features[label] X_train, X_val, y_train, y_val train_test_split(X, y, test_size0.2, stratifyy) # 定义模型处理不均衡 lgb_model lgb.LGBMClassifier( objectivebinary, is_unbalanceTrue, # 使用内置平衡参数 metricaverage_precision, num_leaves31, learning_rate0.05, n_estimators200 ) lgb_model.fit(X_train, y_train, eval_set[(X_val, y_val)], early_stopping_rounds20) # 评估 y_pred_proba lgb_model.predict_proba(X_val)[:, 1] print(AUC-PR:, average_precision_score(y_val, y_pred_proba))6.3 可视化呈现在论文中可视化至关重要它能直观展示你的工作。企业风险分布图用散点图或雷达图展示不同风险等级企业的特征分布如销售额vs现金流稳定性。交易网络图使用Gephi或PyVis绘制企业交易网络用节点颜色表示风险等级节点大小表示交易规模一眼看出高风险企业在网络中的位置。特征重要性图展示LightGBM和SHAP总结的特征重要性条形图证明你的模型是可靠的。额度分配结果图用堆叠柱状图展示不同风险等级企业获得的总额度占比体现策略的风险偏好。6.4 论文写作避坑指南摘要不是引言摘要必须精炼用300字左右概括“问题、方法、模型、结果、结论”。避免背景描述直接上干货“本文针对中小微企业信贷决策问题构建了基于交易网络与多维度时序特征的信用风险评估模型LightGBM并建立了以风险调整后收益最大化为目标的信贷额度优化分配模型...”模型假设要合理且明确在模型建立章节开头就清晰列出你的关键假设。例如“假设1企业历史交易行为能有效预测其未来信用风险假设2突发公共事件对行业的影响可通过先验标签和短期行为变化量化...”灵敏度分析必不可少证明你的模型和策略是稳健的。比如改变额度分配模型中的系数k看结果如何变化调整突发情景的权重α观察最终风险等级分布的变化。这能极大提升论文的说服力。模型检验要全面对于风险评估模型除了AUC值还要报告精确率、召回率、F1-score特别是在不均衡数据下的表现。对于优化模型要分析约束条件松紧对结果的影响。优缺点分析要诚恳在结论部分客观指出模型的不足。例如“本文模型主要依赖历史数据对首次融资或无交易数据的新企业评估能力有限网络特征构建时未考虑交易对手的自身风险...” 并提出改进方向这体现了思考的深度。7. 常见问题与实战踩坑记录发票数据时间窗口不一致怎么办有些企业数据是3年有些只有1年。直接比较绝对值不公平。我们的处理方法是使用比率指标和年均化指标。例如计算“月均销售额”、“现金流波动率”等而不是直接用销售总额。对于时间序列特征只取所有企业共有的时间区间进行分析。交易对手名称不规范如何识别关联企业这是一个难题。我们采用了“模糊匹配人工核查”的策略。先用正则表达式提取名称中的核心字段如“科技”、“贸易”、“有限公司”等再通过编辑距离Levenshtein distance计算相似度。对于相似度高的企业对结合其是否存在密切交易如交易额大、频次高进行判断。虽然不能100%准确但能有效筛选出高风险嫌疑对象。机器学习模型预测出的违约概率普遍偏低或偏高怎么办这可能是样本不均衡或模型校准问题。我们做了两件事第一在训练时使用scale_pos_weight参数或SMOTE过采样第二在模型预测后使用Platt Scaling或Isotonic Regression进行概率校准使预测概率的分布更接近真实违约率。优化模型求解复杂怎么办对于线性规划我们使用了PuLP或SciPy库可以高效求解。如果模型非线性或者约束复杂可以退而求其次采用规则排序比例分配的启发式方法。例如按信用分 * 年均销售额对所有企业排序然后按排名分配额度。这种方法虽然不一定是最优解但结果直观、稳定、易于解释在数学建模竞赛中是完全可接受的。论文篇幅有限如何取舍内容国赛论文有页数限制。我们的策略是核心模型特征工程、风险评估、额度优化必须详细每一步推导和结果都要清晰展示。对于编程实现细节、部分中间结果可以放在附录或简要说明。可视化图表要精致且信息量大一图胜千言。将最精华的模型思路、创新点和结果分析放在正文最显眼的位置。回过头看2020年C题的成功解决关键在于没有停留在简单的统计分析上而是真正构建了一个从数据到决策的闭环系统。它考验的是综合能力数据敏感度、多学科知识融合、模型化思维和解决实际问题的能力。最大的体会是数学建模竞赛中清晰的逻辑链条和合理的假设往往比使用一个极其复杂的“黑箱”模型更重要。你的每一个特征、每一个参数、每一个约束都要能讲出商业逻辑或风控道理。这份经历与其说是一次竞赛不如说是一次浓缩版的金融科技项目实战其中学到的数据思维和问题拆解方法让我在之后的工作中受益无穷。