数学建模竞赛实战:基于企业发票数据的信贷风险评估与决策优化
2026/8/15 3:46:30 网站建设 项目流程

1. 项目概述:一场关于信贷决策的“数据马拉松”

2020年的全国大学生数学建模竞赛C题,题目是“中小微企业的信贷决策”。这个题目一出来,当时我们团队就意识到,这绝对是一场硬仗。它不像一些纯算法优化的题目,给你一堆数据让你去拟合、去预测就完事了。这道题的核心,是把我们这些“象牙塔”里的学生,直接推到了银行信贷经理的位置上,要求我们基于真实、复杂且充满不确定性的企业数据,去构建一套完整的信贷风险评估与决策模型。说白了,就是让我们用数学模型,去回答一个现实世界里银行每天都在面对的核心问题:这笔钱,该不该贷?该贷多少?该收多少利息?

这道题的价值,远远超出了竞赛本身。它精准地切入了当时(乃至现在)金融科技领域最核心的议题之一——如何利用数据驱动的方法,解决中小微企业“融资难、融资贵”的痛点。对于参赛者而言,这不仅是一次数学和编程能力的考验,更是一次对金融逻辑、商业理解、数据处理和系统化思维的综合锤炼。你需要懂一点财务分析,知道哪些指标能反映企业的健康状况;你需要懂一点统计和机器学习,能从海量数据中挖掘出风险信号;你还需要懂一点优化理论,能把风险、收益、政策约束变成一个可求解的数学问题。

整个解题过程,就像完成一个微缩版的金融科技产品开发项目:从业务理解、数据清洗、特征工程,到模型构建、策略制定、方案评估,最后形成一份逻辑严谨、可落地的分析报告。接下来,我就结合我们当时的实战经验,把这道题的解题思路、核心方法、踩过的坑以及一些独家的建模心得,完整地拆解一遍。

2. 赛题核心需求与业务逻辑拆解

拿到题目后,切忌一头扎进数据里。第一步,也是最重要的一步,是彻底读懂题目在问什么,背后的业务逻辑是什么。2020年C题提供了123家有信贷记录的企业和302家无信贷记录企业的数据,包括进销项发票信息、信誉评级、是否违约等。题目要求我们解决四个核心问题:

2.1 问题一:信贷风险量化与评级

题目要求根据123家企业的发票数据、信誉评级和是否违约记录,建立信贷风险模型,并对这123家企业进行风险评估。这里的关键在于“量化”。信誉评级(A, B, C, D)是一个离散的、主观的标签,而“是否违约”是一个二分类结果。我们需要做的,是构建一个模型,能够输出一个连续的、更精细的风险分数,或者对原有评级进行验证和细化。

注意:这里最容易犯的错误是直接拿“是否违约”作为标签去训练一个分类模型(比如逻辑回归、随机森林),然后直接用模型预测的概率作为风险分数。这忽略了题目中“信誉评级”这个重要先验信息。更合理的思路是,将“信誉评级”作为模型的一个重要特征,或者将其与违约记录结合,构造一个更稳健的监督信号。

2.2 问题二与问题三:未知企业的信贷策略制定

这是题目的核心和难点。对于302家无信贷记录的企业,我们需要制定具体的信贷策略,包括:

  1. 是否放贷:一个二分类决策。
  2. 信贷额度:一个回归或优化问题,贷多少钱。
  3. 贷款利率:一个定价问题,风险和收益如何权衡。

题目还给出了一个非常关键的约束:银行的年度信贷总额固定(比如1亿元)。这意味着我们的决策不是孤立的,而是一个资源分配优化问题。你不能给所有低风险企业都批很高的额度,因为钱就那么多。必须在所有申请企业中,找到一个最优的分配方案,使得在总额度限制下,银行的整体预期收益最大(或风险损失最小)。

2.3 问题四:突发情况(疫情)下的策略调整

题目假设突发情况(如新冠疫情)对所有企业产生影响,但影响程度不同。要求我们分析突发情况对模型和策略的影响,并给出调整方案。这考察的是模型的稳健性可解释性。你不能说“模型失效了,重做吧”,而必须能说清楚:哪些特征可能变得不可靠?风险传导的路径是什么?如何基于有限的假设进行快速调整?

2.4 业务逻辑闭环

综合来看,整个解题过程需要构建一个逻辑闭环:数据(发票流) -> 特征(经营指标) -> 模型(风险分数) -> 策略(额度/利率) -> 优化(总额度约束) -> 评估与调整(突发情况)。 每一步都需要有坚实的数学或统计方法作为支撑,并且每一步的选择都要有明确的业务解释。

3. 数据预处理与特征工程实战

题目提供的核心数据是企业的进项和销项发票信息。这是典型的交易流水数据,原始数据非常“碎”,直接建模几乎不可能。特征工程是这里成败的关键,工作量可能占整个项目的60%以上。

3.1 发票数据的关键信息提取

一张发票通常包含:时间、金额、对方企业名称、商品名称等。我们需要从这些流水记录中,提炼出能反映企业“经营健康度”和“稳定性”的指标。

核心特征构建思路:

  1. 经营规模与活跃度特征

    • 交易总额/均值:进项总额、销项总额。直接反映业务量。
    • 交易频次:月度/季度发票张数。反映业务活跃度和稳定性。
    • 交易对手数量:进项/销项中不同的合作企业数量。反映客户/供应商集中度,集中度过高可能有风险。
  2. 盈利能力与现金流特征(这是重点):

    • 毛利率估算:这是一个关键衍生特征。虽然发票没有直接成本,但我们可以用(销项总额 - 进项总额) / 销项总额来近似估算毛利率。当然,这非常粗糙,因为进项和销项在时间上不匹配,且包含税费。但作为相对比较指标,在大量企业中依然有效。
    • 进销项匹配度:计算每个时间窗口(如月度)的“销项/进项”比率。长期远大于1可能虚开发票,长期远小于1可能经营萎缩。
    • 现金流波动性:计算月度净现金流(销项-进项)的标准差、变异系数。波动越大,经营风险可能越高。
  3. 稳定性与趋势特征

    • 季节性/趋势分解:对企业的月度交易额进行时间序列分解,查看其是否存在稳定的增长趋势、季节性波动,或是无规律的随机波动。稳定的增长趋势是加分项。
    • 断流检测:企业是否存在长时间(如超过2个月)无任何交易记录的情况,这可能是经营中断的危险信号。
  4. 行业与上下游特征(如果数据允许):

    • 通过对商品名称进行简单的文本分类或关键词匹配,可以大致划分企业所属行业(如“电子元件”、“纺织服装”)。
    • 分析其上下游企业(交易对手)本身的风险特征(如果对手也在样本池中)。例如,一家企业的核心供应商风险很高,那么它的风险也会被传导。

3.2 数据处理中的“坑”与技巧

  • 时间窗口对齐:发票日期是精确到日的,但我们需要聚合到月或季度。务必注意窗口的起止时间,确保每个企业都有可比的时间段。对于新成立或数据缺失的企业,要谨慎处理。
  • 异常值处理:发票数据中可能存在错漏(如金额极大或极小的发票)。我们当时采用的方法是,对于单张发票金额,计算其与企业历史交易额均值的差距,超过3倍标准差的需要人工复核(在比赛中就是根据业务逻辑判断是否剔除)。不要盲目删除,一笔巨大的进项可能是购买了设备,一笔巨大的销项可能是接到了大订单。
  • 缺失值处理:对于302家无标签企业,特征也可能缺失。我们采用了基于同类企业(行业、规模相近)的均值填充,并在特征中增加了一个“是否填充”的布尔标记,让模型知道这个信息是估算的。
  • 特征标准化:由于后续模型涉及距离计算或梯度下降(如神经网络),必须对连续特征进行标准化(Z-score)或归一化(Min-Max)。树模型(如随机森林、XGBoost)对尺度不敏感,但标准化有助于我们理解特征重要性。

实操心得:特征工程不是一蹴而就的。我们采用的是“构建-评估-筛选”的迭代方式。先基于业务理解构建一大批特征(我们当时构建了超过50个),然后使用问题一中有标签的数据,通过计算特征与目标(风险评级/违约)的相关性,以及用简单的模型(如逻辑回归)查看系数显著性,进行初步筛选。最终保留15-20个解释性强、相关性高的特征进入主模型。

4. 核心模型构建:从风险预测到策略优化

这是整个解题的“发动机”。我们将其拆解为两个核心模型:风险预测模型信贷策略优化模型

4.1 风险预测模型选型与实践

目标:输入企业的特征向量,输出一个连续的风险评分Risk_Score(例如0-100分,分数越高风险越大)。

可选模型对比:

模型优点缺点适用场景
逻辑回归可解释性极强,系数代表特征影响,稳定。线性假设,难以捕捉复杂非线性关系。基线模型,用于特征初筛和理解。
随机森林能处理非线性,抗过拟合能力强,可输出特征重要性。黑盒模型,可解释性差,可能忽略特征间细微的线性关系。作为主力预测模型,效果通常不错。
XGBoost预测精度高,能自动处理缺失值,有正则化防过拟合。比随机森林更黑盒,调参稍复杂。追求预测精度时的首选。
神经网络理论上拟合能力最强,能学习复杂模式。需要大量数据,训练不稳定,可解释性最差,易过拟合。数据量极大时考虑,本题不推荐。

我们的方案:融合模型我们最终没有只用一个模型。而是采用了一个两阶段融合的方案:

  1. 第一阶段 - 有监督预测:使用XGBoost模型,以123家企业的“是否违约”为主要标签,同时将“信誉评级”作为有序变量(A=1, B=2, C=3, D=4)融入损失函数进行训练,得到一个初始风险概率P_default
  2. 第二阶段 - 无监督校准:考虑到违约样本较少,直接用有监督模型预测302家无标签企业可能不稳定。我们引入了无监督的聚类分析(如K-Means或高斯混合模型GMM),基于特征空间将所有企业(包括123家和302家)进行聚类。然后观察每个簇中有标签企业的风险分布。如果一个簇里已知的高风险企业多,那么这个簇的整体风险权重就调高。最终风险分由P_default和聚类调整因子加权得到。

为什么这么做?这相当于结合了“经验”(有标签数据)和“相似度”(无监督聚类)。即使一个新企业没有任何历史信贷记录,只要它的经营模式(特征)和历史上那些“坏企业”很像,它的风险分也会被拉高。这增强了模型的泛化能力和稳健性。

4.2 信贷策略优化模型构建

有了风险分数,接下来就是制定策略。这本质上是一个带约束的优化问题

决策变量:对于每个企业i,我们需要决定:

  • x_i:是否放贷(0或1)
  • a_i:信贷额度(连续变量)
  • r_i:贷款利率(连续变量,通常在一个基准利率上浮动)

目标函数:银行希望最大化总预期收益。

Maximize: Σ [ x_i * a_i * (r_i - Cost_of_Capital) * (1 - P_default_i) - x_i * a_i * P_default_i ]

解释:收益部分 = 额度 * 利差 * 不违约的概率;损失部分 = 额度 * 违约的概率。P_default_i就是我们从风险模型得到的企业i的违约概率。

约束条件

  1. 总额度约束Σ (x_i * a_i) <= Total_Credit_Limit(题目给出的总额度,如1亿)。
  2. 额度上下限Min_Amount <= a_i <= Max_Amount, 对于不同规模企业,额度应有合理范围。
  3. 利率风险定价r_i = Base_Rate + Risk_Premium_i。风险溢价Risk_Premium_i应与P_default_i正相关,例如Risk_Premium_i = k * P_default_i。这保证了高风险高收益。
  4. 逻辑约束:如果x_i = 0(不放贷),则a_i = 0

求解方法: 这是一个混合整数非线性规划问题,直接求解较难。我们做了合理简化:

  1. 将是否放贷x_i和额度a_i的决策分开。先根据风险分数和预期收益,用一个排序规则初筛出“值得放贷”的企业池(x_i=1)。
  2. 在放贷池中,将利率r_i表示为风险分数s_i的线性函数,代入目标函数。
  3. 此时,问题简化为在总额度约束下,对放贷池中的企业分配额度a_i,以最大化一个关于a_i的线性或二次目标函数。这可以用经典的线性规划二次规划求解器(如Python的PuLP,CVXOPT)高效求解。

策略输出:求解后,我们得到一张清晰的信贷策略表:

企业ID是否放贷建议额度(万元)建议利率风险等级
E0011005.8%
E0020-
...............

5. 突发情况影响分析与模型调整

题目第四问模拟新冠疫情这类系统性冲击。我们的分析框架如下:

5.1 影响识别

系统性冲击不会同等地影响所有企业和所有特征。

  • 对特征的影响
    • 直接冲击特征:如“最近一季度交易额”、“交易频次”可能断崖式下跌。这类特征的当期数据会瞬间“失真”。
    • 间接冲击特征:如“毛利率”、“现金流波动性”,其计算依赖于多期数据,影响会滞后并持续一段时间。
    • 相对稳定特征:如企业长期的“交易对手集中度”、“历史平均规模”,可能变化不大。
  • 对模型的影响
    • 特征分布漂移:冲击后,数据的统计分布(均值、方差)与模型训练时所用数据的分布发生显著变化,导致模型预测失效。
    • 风险关联性变化:原本不重要的特征(如“是否依赖线下”)可能突然成为强风险因子。

5.2 调整策略

我们不能等有新违约数据了再重新训练模型,必须基于假设快速调整。

  1. 特征重加权:这是最快速有效的方法。在原有模型中,手动调高那些对冲击敏感的特征的权重。例如,在风险评分公式中,增加“近期交易活跃度下降比例”这个新特征的权重,同时降低“历史年均交易额”的权重。

    • Adjusted_Score = α * Original_Score + β * Impact_Indicator
    • 其中Impact_Indicator可以是行业受冲击系数(假设旅游、餐饮行业系数高)与近期经营下滑系数的乘积。
  2. 引入先验规则:在模型决策层之上,加入规则引擎。例如:“如果企业所属行业为受冲击严重行业,且近期交易额下降超过50%,则无论原模型评分如何,将其风险等级临时上调一级,并大幅降低授信额度。”

  3. 压力测试模拟:利用历史数据(如果有类似冲击时期)或蒙特卡洛模拟,模拟冲击下企业现金流断裂的概率,并将其作为额外的风险因子加入评估。

  4. 策略的弹性调整:信贷策略优化模型中的约束条件需要动态调整。例如,总额度不变,但可以临时增设“对特定行业的集中度限制”,或提高所有企业的利率风险溢价基础值k,以覆盖更高的系统性风险。

注意事项:在论文中阐述这部分时,重点不在于你调整得多么精确(因为无法验证),而在于你的分析逻辑的完整性和合理性。你需要清晰地展示:a) 识别了哪些可能受影响的环节;b) 提出了哪些具体的、可操作的调整方法;c) 解释了这些方法如何缓解冲击带来的问题。

6. 建模全流程中的常见陷阱与应对技巧

回顾整个解题过程,有几个地方特别容易出错,这里集中分享一下:

6.1 数据理解与清洗陷阱

  • 陷阱:忽视发票数据中的“负数”金额。在实际中,负数可能代表红字发票(退货、折让)。如果直接求和,会低估交易额。我们一开始就漏掉了,导致一些企业的特征计算错误。

  • 应对:在数据清洗的第一步,就单独统计正负金额,分析负数发票的比例和原因。在计算交易总额时,使用绝对值求和或净额计算,需根据业务含义决定,并在论文中说明。

  • 陷阱:简单按企业ID分组计算特征,忽略了集团企业的关联交易。如果两家企业是母子关系或关联公司,它们之间的交易可能虚增经营规模。

  • 应对:这是一个高级技巧。如果时间允许,可以对交易对手名称进行模糊匹配或网络分析,识别出频繁交易且名称相似的企业群,将它们视为一个整体进行风险评估。

6.2 特征工程与模型过拟合

  • 陷阱:构建了大量复杂、高维的特征(如各种交互项、多项式特征),直接在123条小样本数据上训练复杂模型(如深度网络),导致严重的过拟合。模型在训练集上表现完美,但泛化能力为零。
  • 应对
    1. 特征筛选是必须的:使用方差阈值、相关性分析、基于模型的特征重要性(如XGBoost的feature_importances_)进行筛选。
    2. 坚决使用交叉验证:在123条数据上,采用留一法或5折交叉验证来评估模型性能,而不是看训练集准确率。
    3. 优先选择简单模型:在数据量小时,逻辑回归加精心构建的特征,其效果和可解释性往往优于一个过拟合的黑盒模型。

6.3 优化模型求解的可行性

  • 陷阱:设计的优化模型过于复杂(如非线性、非凸),自己无法求解,或者求解时间过长。
  • 应对
    1. 一定要做简化:像我们前面做的那样,将是否放贷和额度分配分步进行。先用一个清晰的规则(如风险分数低于阈值且预期收益为正)筛选出候选集,大大减少决策变量。
    2. 验证解的质量:对于求出的解,要检查其是否满足所有约束条件。可以设计一个简单的贪婪算法作为基线(例如,按“单位风险收益比”从高到低分配额度),对比优化解的效果,证明优化是有效的。
    3. 利用成熟求解器:Python的PuLP(对接多种开源/商业求解器)或SciPy.optimize对于线性/二次规划问题非常可靠,代码也简洁。

6.4 论文写作与结果展示

  • 陷阱:论文通篇是模型公式和代码,没有业务解释;或者结果只有一堆数字表格,没有可视化。
  • 应对
    1. 每一部分都要有“为什么”:为什么选这个特征?为什么用这个模型?为什么这样设定约束?这是评委最看重的逻辑链。
    2. 可视化是关键:企业风险得分的分布直方图、特征重要性条形图、额度分配前后的对比饼图、聚类结果散点图……一图胜千言。使用MatplotlibSeaborn制作清晰、专业的图表。
    3. 结果要可解释:对于最终的信货策略表,可以附上一些典型企业的案例分析。例如:“企业E123,因其毛利率持续下滑且交易波动大,被模型评为高风险,故不予授信。”这能让你的模型结果落地。

最后想说的是,数模竞赛和真实的数据科学项目一样,没有唯一的标准答案。我们的这套方案——融合模型、两阶段优化、系统性风险分析——只是众多可行路径中的一种。它的优势在于逻辑层次清晰,兼顾了监督与非监督学习,并且将业务约束很好地融入了数学建模。在实际比赛中,更重要的是你思考的深度、解决问题的完整度,以及将复杂问题清晰呈现的能力。这道题就像一个微缩的金融科技沙盘,走完一遍,你对如何用数据驱动商业决策,会有完全不一样的理解。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询