FEATURED · 精选文章

量子退火在信用评分卡组合优化中的应用与建模实践

发布时间 / 2026/8/22 9:31:05
来源 / 创域科博编辑部
栏目 / 资讯中心
量子退火在信用评分卡组合优化中的应用与建模实践 1. 项目概述当量子计算遇上金融风控信用评分卡这玩意儿在银行和消费金融公司里就跟厨师手里的盐一样是风控的基石。简单说它就是一套规则根据你的年龄、收入、历史还款记录等一堆数据给你打个分预测你未来违约的可能性。一家机构通常不会只用一张评分卡而是会有一个“卡池”里面放着几十甚至上百张侧重点不同的评分卡。比如有的卡专门看你的消费流水有的卡死盯你的社保缴纳情况。那么问题来了当我们要审批一笔贷款时该从卡池里选出哪几张卡以及每张卡的权重怎么分配才能让最终的组合评分预测最准、风险最低这就是经典的“信用评分卡组合优化”问题。传统的解法比如用线性规划或者启发式算法在面对几十个变量、几百个约束条件时已经开始显得力不从心计算时间长而且容易陷在局部最优解里出不来。这时候题目里提到的“量子计算机”就登场了。别被这个名字吓到我们不是要从头造一台量子计算机而是利用一种名为“量子退火”的专用机器的计算特性。这类机器特别擅长解决一类叫做“二次无约束二值优化”的问题。我们的核心思路就是把挑选评分卡和分配权重这个复杂问题巧妙地“翻译”成QUBO模型然后扔给量子退火机去求解。这就像是你有一把复杂的密码锁组合优化问题量子退火机是一把设计来专门开这种结构锁的万能钥匙QUBO求解器。去年带队打MathorCupA题就撞上了这个前沿交叉点。当时的感觉是兴奋远大于棘手。兴奋在于这可能是很多同学第一次亲手把金融问题映射到量子计算框架棘手在于两步关键的“翻译”工作第一步如何把评分卡的“选”与“权重”用0和1的二值变量表示第二步如何把“预测精度最高”和“业务规则限制”这两个目标统一成一个QUBO公式里的“能量最低”目标。接下来我就结合当时的解题思路和后续的复盘把整个建模过程、代码实现的坑以及一些心得掰开揉碎了讲清楚。2. 问题拆解从业务描述到数学语言题目通常会提供一些历史数据包含多个样本客户在多个评分卡上的得分以及这些客户最终是否违约的真实标签。我们的任务可以分解为两个核心子问题2.1 决策变量定义用0-1变量表达选择与权重这是建模的基石。假设我们有M张候选评分卡。最直观的想法是用M个0-1变量x_i (i1,...,M)x_i1表示选中第i张卡0表示不选。但光“选”还不够我们还得决定每张被选中的卡的权重w_i。权重一般是连续变量这似乎与QUBO要求的二值变量矛盾。这里就需要一个经典的技巧权重离散化。我们不会去求一个精确到小数点后几位的连续权重而是将权重离散化为几个固定的等级。例如我们规定每张卡的权重只能从{0, 0.2, 0.4, 0.6, 0.8, 1.0}这6个值中选取。那么对于第i张卡我们可以用一组“独热编码”的二值变量来表示它的权重选择。比如用6个二值变量y_{i,1}, y_{i,2}, ..., y_{i,6}规定当且仅当y_{i,k}1时表示第i张卡的权重取第k个等级值v_k。并且这6个变量中必须有且仅有一个为1。这样一来我们的决策变量就全部变成了二值变量x_i和y_{i,k}。最终第i张卡的贡献就是x_i * (Σ_{k} v_k * y_{i,k})。当x_i0卡未选中时后面权重部分自然归零。2.2 目标函数构建最大化预测精度我们的目标是让组合评分卡的预测能力最强。在二分类违约/不违约问题中通常使用AUC曲线下面积或KS值作为评估指标。但这些指标在QUBO框架下直接表达非常困难因为它们依赖于排序。一个更可行的方法是采用逻辑回归的视角。我们可以将组合评分各卡得分加权和视为一个线性预测值然后通过一个链接函数如sigmoid去预测违约概率。最大化预测精度可以转化为最小化逻辑损失Log Loss或最小化平方误差。假设对于第j个客户第i张评分卡的得分为s_{ij}其真实标签为t_j例如违约记为1不违约记为-1或0。那么该客户的组合预测值为z_j Σ_i [x_i * (Σ_k v_k * y_{i,k}) * s_{ij}]。如果我们采用平方误差损失并引入一个偏置项b则目标函数的一部分可以写为H_obj Σ_j (z_j b - t_j)^2将z_j的表达式代入展开后我们会得到关于二值变量x_i,y_{i,k}的二次项、一次项和常数项。这正是QUBO模型所要求的形式。注意这里用平方误差损失是为了数学上的便利因为它展开后是二次型。在实际金融风控中Log Loss可能更标准但其非线性更强。在竞赛有限时间和量子退火硬件限制下平方误差是一个合理的简化。在论文中需要说明这一权衡。2.3 约束条件处理业务规则必须遵守业务不会允许我们随意组合。常见的约束有数量约束最多选择K张卡。即Σ_i x_i K。权重归一化约束所有选中卡的权重之和应为1。即Σ_i [x_i * (Σ_k v_k * y_{i,k})] 1。独热编码约束对于任何一张卡i其权重变量y_{i,k}必须有且仅有一个为1。即Σ_k y_{i,k} x_i。注意当x_i0卡未选时所有y_{i,k}必须为0当x_i1时有且仅有一个y_{i,k}1。在QUBO模型中没有传统优化中的“不等式”或“等式”约束概念。所有约束都必须以惩罚项的形式添加到目标函数中。原理是如果约束被违反就在总“能量”H上加上一个很大的惩罚值P使得违反约束的解变得“能量”很高从而不被最优解考虑。例如对于权重归一化约束Σ_i [x_i * (Σ_k v_k * y_{i,k})] 1我们将其转化为惩罚项H_penalty1 P1 * (Σ_i [x_i * (Σ_k v_k * y_{i,k})] - 1)^2同样对于数量约束Σ_i x_i K我们可以将其改写为等式Σ_i x_i s K其中s是一个非负整数松弛变量也可以二进制展开表示然后添加惩罚项P2 * (Σ_i x_i s - K)^2。独热编码约束Σ_k y_{i,k} x_i也需要为每一张卡i添加惩罚项P3 * (Σ_k y_{i,k} - x_i)^2。2.4 QUBO模型整合最终的QUBO模型哈密顿量H为H H_obj H_penalty1 H_penalty2 H_penalty3 ...我们的任务就是找到一组二值变量{x_i, y_{i,k}}的赋值使得H的值最小。这个最小化过程就交给了量子退火算法。实操心得惩罚系数P1, P2, P3的设定是门艺术。设得太小约束可能被忽略设得太大可能掩盖了原始目标H_obj导致解虽然满足约束但预测精度很差。一个经验法则是让惩罚项的数量级显著大于目标函数可能的变化范围。通常可以先试运行几次观察约束违反情况再动态调整。3. 模型构建的详细步骤与数学推导上一节我们定性地描述了框架这一节我们深入数学细节看看一个具体的QUBO矩阵是如何构建的。为了简化演示我们假设一个微型场景M2张卡权重离散化为2个等级{0.5, 1.0}最多选K1张卡有N3个样本。3.1 变量定义与编号首先为每个二值变量分配一个唯一的索引这是量子退火机输入所要求的x_1: 索引 0x_2: 索引 1y_{1,1}(权重0.5): 索引 2y_{1,2}(权重1.0): 索引 3y_{2,1}(权重0.5): 索引 4y_{2,2}(权重1.0): 索引 53.2 目标函数H_obj展开我们采用平方误差损失并忽略偏置项b以简化实际中可以加入。对于样本j其组合预测值z_j (x_1*(0.5*y_{1,1} 1.0*y_{1,2}))*s_{1j} (x_2*(0.5*y_{2,1} 1.0*y_{2,2}))*s_{2j}令W1 0.5*y_{1,1} 1.0*y_{1,2},W2 0.5*y_{2,1} 1.0*y_{2,2}则z_j x_1*W1*s_{1j} x_2*W2*s_{2j}。H_obj Σ_j (z_j - t_j)^2 Σ_j (x_1*W1*s_{1j} x_2*W2*s_{2j} - t_j)^2展开平方项 Σ_j [ (x_1*W1*s_{1j})^2 (x_2*W2*s_{2j})^2 2*(x_1*W1*s_{1j})*(x_2*W2*s_{2j}) - 2*t_j*(x_1*W1*s_{1j} x_2*W2*s_{2j}) t_j^2 ]这里有几个关键点需要处理x_i和y_{i,k}是0-1变量满足x_i^2 x_i,y_{i,k}^2 y_{i,k}。W1和W2本身是y_{i,k}的线性组合因此W1^2展开后包含y_{i,k}的平方项和交叉项。交叉项如(x_1*W1)*(x_2*W2)会产生x_1*x_2,x_1*y_{2,k},x_2*y_{1,k},y_{1,k}*y_{2,l}等多种二次项。展开过程非常繁琐但规律是最终H_obj会表达为所有二值变量q_p(p0,...,5) 的二次型H_obj Σ_{pq} Q_{obj}[p, q] * q_p * q_q其中Q_{obj}是一个上三角矩阵或对称矩阵q_p * q_q在pq时就是线性项。3.3 约束惩罚项展开权重归一化约束x_1*W1 x_2*W2 1H_pen1 P1 * (x_1*W1 x_2*W2 - 1)^2展开后同样会产生关于x_i,y_{i,k}的常数项、一次项和二次项叠加到Q矩阵的对应位置。数量约束x_1 x_2 1。引入松弛变量s(0或1)转化为x_1 x_2 s 1。s作为一个新的二值变量索引6。H_pen2 P2 * (x_1 x_2 s - 1)^2独热编码约束对于卡1y_{1,1} y_{1,2} x_1-H_pen3_1 P3 * (y_{1,1} y_{1,2} - x_1)^2对于卡2y_{2,1} y_{2,2} x_2-H_pen3_2 P3 * (y_{2,1} y_{2,2} - x_2)^23.4 QUBO矩阵Q的组装最终的总哈密顿量H H_obj H_pen1 H_pen2 H_pen3_1 H_pen3_2。我们将所有项合并整理成标准QUBO形式H Σ_{i} a_i q_i Σ_{ij} b_{ij} q_i q_j constant其中q_i ∈ {0, 1}。通常我们用一个上三角矩阵Q来表示其中对角线元素Q[i][i]对应a_i线性系数非对角线元素Q[i][j] (ij)对应b_{ij}二次项系数。常数项不影响优化可以忽略。手动推导这个Q矩阵对于稍大规模的问题是不可行的必须通过编程实现。核心是正确地计算每一项的系数并累加到Q矩阵的相应位置。注意事项在添加惩罚项时务必注意系数P的乘数效应。例如(expression)^2展开时expression中的每一个变量项都会被平方或两两相乘其系数会被P放大。编程时最容易出错的地方就是系数累加错误导致Q矩阵与理论模型不符。建议对小型样例如我们这里的2卡2权重3样本进行手算验证与程序输出对比。4. 代码实现从建模到量子求解理论打通后实现就相对清晰了。我们使用 Python主要借助dimod库用于构建QUBO模型和dwave-cloud-client用于连接D-Wave量子退火云服务或neal模拟退火器用于本地测试。这里以模拟退火为例因为量子云服务需要账户和配额。4.1 数据准备与预处理import numpy as np import pandas as pd from dimod import Binary, quicksum, ConstrainedQuadraticModel, SampleSet import neal # 假设我们有数据框 df列包括sample_id, score_card1, score_card2, ..., label # M: 评分卡数量 # N: 样本数量 # scores: N x M 的 numpy 数组 # labels: N x 1 的 numpy 数组 (取值 -1 和 1方便计算) # 权重离散化等级 weight_levels [0.0, 0.2, 0.4, 0.6, 0.8, 1.0] # 注意包含0代表不选该卡时权重为0 K 5 # 最多选择5张卡 M scores.shape[1] L len(weight_levels) # 定义决策变量 x {i: Binary(fx_{i}) for i in range(M)} # 是否选择卡i y {(i, l): Binary(fy_{i}_{l}) for i in range(M) for l in range(L)} # 卡i是否采用第l个权重等级 # 注意实际中当 x_i0 时逻辑上应强制所有 y_{i,l}0。这通过约束实现。4.2 构建目标函数最小化平方误差def build_objective_cqm(scores, labels, x, y, weight_levels): cqm ConstrainedQuadraticModel() objective 0.0 for n in range(scores.shape[0]): # 遍历每个样本 z_n 0 # 第n个样本的组合预测值 for i in range(M): # 遍历每张卡 w_i quicksum(weight_levels[l] * y[i, l] for l in range(len(weight_levels))) z_n x[i] * w_i * scores[n, i] # 计算该样本的平方误差并累加 objective (z_n - labels[n]) ** 2 cqm.set_objective(objective) return cqm这里我们使用了ConstrainedQuadraticModel(CQM)它允许我们以更自然的方式添加约束然后D-Wave的混合求解器可以处理CQM。如果使用纯QUBO求解器则需要手动将约束转化为惩罚项并加入目标。4.3 添加业务约束def add_constraints(cqm, x, y, M, L, K, weight_levels, penalty_strength100.0): # 1. 权重归一化约束所有选中卡的权重之和为1 total_weight quicksum(x[i] * quicksum(weight_levels[l] * y[i, l] for l in range(L)) for i in range(M)) cqm.add_constraint(total_weight 1, labelweight_sum_eq_1) # 2. 数量约束最多选择K张卡 # CQM支持不等式约束 num_selected quicksum(x[i] for i in range(M)) cqm.add_constraint(num_selected K, labelmax_cards) # 3. 独热编码约束对于每张卡i如果被选中(x_i1)则必须且只能选择一个权重等级 for i in range(M): weight_selection quicksum(y[i, l] for l in range(L)) # 关键约束weight_selection 必须等于 x_i # 这同时保证了如果 x_i0则所有 y_{i,l}0如果 x_i1则 sum(y_{i,l}) 1。 cqm.add_constraint(weight_selection x[i], labelfone_hot_weight_{i}) # 注意在CQM中我们不需要手动设置惩罚强度求解器会内部处理。 # 如果构建纯QUBO则需要将上述每个约束转化为 penalty_strength * (expression)^2 的形式加入目标。4.4 模型求解与结果解析def solve_model(cqm): # 使用模拟退火器进行求解本地测试 sampler neal.SimulatedAnnealingSampler() # 对于CQM我们需要使用 dimod 的 ExactCQMSolver 或 LeapHybridCQMSolver量子云 # 此处为演示我们将CQM通过惩罚项转换为BQMBinary Quadratic Model进行模拟退火 # 这是一个简化处理实际参赛应使用混合求解器直接处理CQM以获得更好效果。 # 将CQM转换为BQM通过惩罚项 from dimod import Binaries bqm, invert dimod.cqm_to_bqm(cqm, penalty_strengthpenalty_strength) # 运行模拟退火 sampleset sampler.sample(bqm, num_reads1000, num_sweeps1000) # 获取能量最低的解即最优解 best_sample sampleset.first.sample return best_sample, sampleset def interpret_solution(best_sample, M, L, weight_levels): selected_cards [] card_weights {} for i in range(M): if best_sample.get(fx_{i}, 0) 1: selected_cards.append(i) for l in range(L): if best_sample.get(fy_{i}_{l}, 0) 1: card_weights[i] weight_levels[l] break print(f选中的评分卡索引: {selected_cards}) print(f各卡权重: {card_weights}) # 验证权重和是否为1 total_weight sum(card_weights.values()) print(f总权重和: {total_weight} (应接近1)) return selected_cards, card_weights4.5 参数调优与模型评估求解得到变量赋值后我们需要在验证集上评估这个评分卡组合的性能如计算AUC、KS值这才是最终的评价标准。整个流程是一个迭代优化过程设定一组参数权重离散化等级、惩罚强度P、最大选卡数K。在训练集上构建CQM/QUBO并求解。在验证集上评估解的性能。调整参数重复步骤2-3寻找验证集性能最好的参数组合。实操心得量子退火或模拟退火是一种启发式算法它可能返回近似最优解且每次运行结果可能有细微差异。因此通常需要多次运行num_reads参数然后从所有返回的解中选取能量最低且满足约束如果使用CQM则自动满足如果使用QUBO惩罚项则需要检查的解作为最终输出。对于penalty_strength如果使用QUBO形式可以从一个较大的值如目标函数值的10-100倍开始尝试。5. 经典优化算法对比与混合策略虽然题目聚焦量子计算但在论文中与经典算法对比能体现工作的深度。我们可以实现一个经典的基准方法例如穷举法在卡数M较小如15且权重离散化等级少时可以穷举所有可能的组合作为最优解的基准。遗传算法将评分卡选择和权重等级编码为染色体以适应度函数如验证集AUC的负值为目标进行进化。模拟退火直接作用于我们的QUBO模型作为量子退火的一个经典对照。对比维度可以包括求解质量在验证集上的AUC/KS值。计算时间达到相同精度所需的时间。稳定性多次运行结果的标准差。混合策略是一个高级技巧也是论文的加分项。量子退火硬件如D-Wave目前处理的变量规模有限。对于大规模问题上百张卡我们可以采用分解策略先用经典方法如相关性分析、特征重要性排序预筛选出最相关的M张卡M在量子硬件可解范围内。对筛选后的子集使用量子退火进行精细组合优化。或者使用量子退火求解多个随机子问题再用经典元启发式算法整合结果。6. 参赛论文写作要点与避坑指南数学建模竞赛模型和代码是基础论文才是最终交付物。如何将上述复杂过程清晰、专业地呈现出来至关重要。6.1 论文结构建议问题重述与分析用自己的话精炼概括问题并明确指出其组合优化本质、难点组合爆炸、非线性评估以及引入量子计算范式的必要性。模型假设与符号说明清晰列出所有假设如权重离散化、使用平方误差损失等并给出完整的符号表。这是严谨性的体现。模型建立这是核心章节。先介绍QUBO模型和量子退火的基本原理无需过于深入物理讲清“能量最小化”与“组合优化”的对应关系即可。详细阐述决策变量的二值化编码过程x_i,y_{i,k}最好配以示意图。逐步推导目标函数从预测误差到平方和形式。详细说明约束条件的处理数量、归一化、独热并展示如何转化为惩罚项加入QUBO哈密顿量。给出最终的H表达式。可以画一个流程图展示从原始数据到QUBO矩阵的完整建模流程。求解方法说明使用的求解工具如D-Wave LeapHybridCQMSolver 或 模拟退火器neal。描述求解参数num_reads,penalty_strength等的设置及依据。如果采用了混合策略或分解策略在此详细说明。数值实验与结果分析数据描述说明使用的数据公开数据集或赛题提供数据的基本情况。实验设置明确训练集/验证集划分比例、权重离散化方案、对比的经典算法等。结果展示用表格清晰列出不同方法量子/经典在验证集上的关键指标AUC, KS, 准确率等、求解时间。用图表展示量子方法找到的评分卡组合权重分布。分析讨论分析量子方法相对于经典方法的优势求解质量、时间并讨论其局限性如问题规模受硬件限制、参数调优等。模型评价与推广客观评价本模型的优点创新性、求解效率潜力和缺点近似性、对损失函数选择的敏感性。探讨模型在其他金融优化问题如投资组合选择中的应用可能性。6.2 常见问题与避坑指南坑1混淆QUBO与Ising模型D-Wave硬件底层接受的是Ising模型变量取值为±1而QUBO是变量取值为{0, 1}。两者可以线性转换。dimod库会自动处理这个转换但自己写代码时要注意。在论文中统一使用一种表述即可建议用QUBO更直观。坑2惩罚系数设置不当这是调试中最耗时的部分。如果解总是违反约束增大惩罚系数如果解虽然满足约束但目标函数值预测误差很大可能是惩罚系数过大掩盖了原始目标。建议采用分层调整先给一个很大的P确保约束满足再微调P在约束满足的前提下优化目标。坑3忽略验证集的重要性绝对不能在训练集上评估最终模型性能必须使用独立的验证集。否则就是数据泄露结果毫无说服力。坑4对量子计算期望过高当前量子退火机并非万能它仍在发展中。在论文中要体现批判性思维。可以指出对于中等规模问题模拟退火或经典启发式算法可能已经足够好量子方法的优势在于其并行搜索的潜力为未来更大规模问题提供了一种新思路。这种客观的态度反而会让评委觉得你思考深入。坑5代码与模型描述脱节论文中的公式推导必须与代码实现严格对应。评委可能会查看代码。确保你代码中构建Q矩阵的逻辑能从论文的数学公式中清晰追溯。坑6忽视可视化一图胜千言。除了结果表格务必加入模型流程图、QUBO矩阵结构示意图可用稀疏矩阵表示、不同方法性能对比柱状图、权重分布雷达图等。这能极大提升论文的可读性和专业性。最后分享一个我们当时调试的小技巧在编写QUBO矩阵构建函数时同时写一个函数用随机生成的{0,1}变量值去手动计算H的值并与dimod库中BQM对象的energy(sample)方法计算的结果进行比对。确保两者完全一致这是验证模型编码正确性的最有效方法能帮你节省大量排查bug的时间。数学建模尤其是这种交叉前沿题目本质上是一个系统工程严谨的逻辑、清晰的表达和反复的验证比追求算法的绝对新颖性更重要。
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻