题目介绍
在银行信用卡或相关的贷款等业务中,对客户授信之前,需要先通过各种审核规则对客户的信用等级进行评定,通过评定后的客户才能获得信用或贷款资格。规则审核过程实际是经过一重或者多重组合规则后对客户进行打分,这些规则就被称为信用评分卡,每个信用评分卡又有多种阈值设置(有且只有一个阈值生效),这就使得不同的信用评分卡在不同的阈值下,对应不同的通过率和坏账率,一般通过率越高,坏账率也会越高,反之,通过率越低,坏账率也越低。
对银行来说,通过率越高,通过贷款资格审核的客户数量就越多,相应的银行获得的利息收入就会越多,但高通过率一般对应着高坏账率,而坏账意味着资金的损失风险,因此银行最终的收入可以定义为: 最终收入 = 贷款利息收入 - 坏账损失
(本简化只适用本次比赛赛题,不能完全代表实际场景)。 假设贷款资金为1000000元,银行贷款利息收入率为8%,并以上面列举的三个信用评分卡作为选定的信用评分卡组合来测算银行最终收入。 每一信用评分卡有且只可选择1个阈值。如果我们选择三重信用卡组合策略,那么这三种信用评分卡组合后的总通过率为所有信用评分卡通过率相乘。 总坏账率为三种信用评分卡对应坏账率的平均值。
基于以上条件可求得,本次贷款利息收入为: 贷款资金×利息收入率×总通过率×(1-总坏账率)
由坏账带来的坏账损失为: 贷款资金×总通过率×总坏账率
那么银行的最终收入为: 贷款利息收入-坏账损失
由此可见,选择不同的信用评分卡,不同的阈值组合,会给银行带来不同的收入与损失,由此决定银行最终收入。因此,银行的目标是选择最合理的信用评分卡组合以及其阈值,使得银行最终收入最多。
要求根据上面的赛题说明及附件1中的数据,请你们团队通过建立数学模型完成如下问题1至问题3。
问题1:在100个信用评分卡中找出1张及其对应阈值,使最终收入最多,请针对该问题进行建模,将该模型转为QUBO形式并求解。
问题2:假设赛题说明3目前已经选定了数据集中给出的信用评分卡1、信用评分卡2、信用评分卡3这三种规则,如何设置其对应的阈值,使最终收入最多,请针对该问题进行建模,将模型转为QUBO形式并求解。
问题3:从所给附录中100个信用评分卡中任选取3种信用评分卡,并设置合理的阈值,使得最终收入最多,请针对该问题进行建模,并将模型转为QUBO形式并求解。
问题1解答
对单张信用卡进行分析,将问题建模为了QUBO问题。首先定义问题中出现的量:
目标:用这个定义可以表达银行的收益:
约束:为了让求解符合实际情况,需要约束每个信用卡的只有1个阈值被选择
模型存在约束条件,需要转化为约束项添加到目标函数中:
其中,P是惩罚项的惩罚系数。
代码
import numpy as np
import kaiwu as kw
# 输入数据
cards = np.array([]) #(100,2,10)
N, Y = cards.shape[0], cards.shape[2]
m, r = 0, 0.0
# 决策变量维数
# num_var = N * Y
# 定义决策变量
x = kw.qubo.ndarray((N,Y), 'x', kw.qubo.Binary)
# 收益
profit = kw.qubo.quicksum([kw.qubo.quicksum([(m*r*x[i, j]*cards[i,0,j]*(1-cards[i,1,j])\
- m*x[i,j]*cards[i,0,j]*cards[i,1,j]) for j in range(Y)]) for i in range(N)])
# 约束条件
choose_cons = (kw.qubo.quicksum([kw.qubo.quicksum([x[i,j] for j in range(Y)])\
for i in range(N)]) - 1) ** 2
# 目标函数
obj = 10 * choose_cons + profit
# 求解
obj = kw.qubo.make(obj)
obj_ising = kw.qubo.qubo_model_to_ising_model(obj)
matrix = obj_ising.get_ising()["ising"]
output = kw.cim.SimulatedCIMOptimizer(
pump = 1.3,
noise = 0.2,
laps = 5000,
delta_time = 0.05,
normalization = 0.3,
iterations = 50)
output = output.solve(matrix)
opt = kw.sampler.optimal_sampler(matrix, output, bias=0, negtail_ff=False)
cim_best = opt[0][0]
cim_best = cim_best * cim_best[-1]
# Get the list of variable names
vars = obj_ising.get_variables()
# Substitute the spin vector and obtain the result dictionary
sol_dict = kw.qubo.get_sol_dict(cim_best, vars)
# Check the hard constraints for validity and path length
choose_val = kw.qubo.get_val(choose_cons, sol_dict)
print('choose cons: {}'.format(choose_val))
# Calculate the profit
profit_val = kw.qubo.get_val(profit, sol_dict)
print('profit: {}'.format(profit_val))
if choose_val == 0:
print('valid result')
# Get the numerical value matrix of x
x_val = kw.qubo.get_array_val(x, sol_dict)
# Print the path order
card_index = np.where(np.array(x_val) == 1)
print(f'选择第{card_index[0]}张信用卡的阈值{card_index[1]},使得最终收入最多')
else:
print('invalid result')
问题2解答
问题中出现的量与第1问基本相同,区别在于通过率和坏账率与银行卡的选择无关
定义二值决策变量:
目标:最大化银行收益
约束:为了让求解符合实际情况,需要约束每个信用卡的只有1个阈值被选择
代码
import numpy as np
import kaiwu as kw
# 输入数据
cards = np.array([]) #(3,2,10)
N, Y = cards.shape[0], cards.shape[2]
m, r = 0, 0
# 决策变量维数
# num_sij = Y * Y
# num_y3k = Y
# 定义决策变量
s = kw.qubo.ndarray((Y, Y), 's', kw.qubo.Binary)
y = kw.qubo.ndarray((N, Y), 'y', kw.qubo.Binary)
# 收益
profit = kw.qubo.quicksum([kw.qubo.quicksum([kw.qubo.quicksum(
[(m*r*s[i, j]*y[2, k]*cards[1,0,i]*cards[1,0,j]*cards[1,0,k]*\
(1-1/3*(cards[1,1,i]+cards[1,1,j]+cards[1,1,k]))\
- m*s[i,j]*y[2, k]*cards[1,0,i]*cards[1,0,j]*cards[1,0,k]*1/3*\
(cards[1,1,i]+cards[1,1,j]+cards[1,1,k])) for k in range(Y)])\
for j in range(Y)]) for i in range(Y)])
# 约束条件
choose_cons = kw.qubo.quicksum(
[(kw.qubo.quicksum([y[i,j] for j in range(Y)]) - 1) ** 2 for i in range(N)])
extra_cons = kw.qubo.quicksum([kw.qubo.quicksum([y[0, i]*y[1, j]-2*y[0, i]*s[i, j]\
-2*y[1, j]*s[i,j]+3*s[i, j] for j in range(Y)]) for i in range(Y)])
# 目标函数
obj = 10 * choose_cons + 10 * extra_cons + profit
# 求解
obj = kw.qubo.make(obj)
obj_ising = kw.qubo.qubo_model_to_ising_model(obj)
matrix = obj_ising.get_ising()["ising"]
output = kw.cim.SimulatedCIMOptimizer(
pump = 1.3,
noise = 0.2,
laps = 5000,
delta_time = 0.05,
normalization = 0.3,
iterations = 50)
output = output.solve(matrix)
opt = kw.sampler.optimal_sampler(matrix, output, bias=0, negtail_ff=False)
cim_best = opt[0][0]
cim_best = cim_best * cim_best[-1] #不太懂
# Get the list of variable names
vars = obj_ising.get_variables()
# Substitute the spin vector and obtain the result dictionary
sol_dict = kw.qubo.get_sol_dict(cim_best, vars)
print(f"{sol_dict}")
# Check the hard constraints for validity and path length
choose_val = kw.qubo.get_val(choose_cons, sol_dict)
extra_val = kw.qubo.get_val(extra_cons, sol_dict)
print('choose cons: {}'.format(choose_val))
print('extra cons: {}'.format(extra_val))
# Calculate the profit
profit_val = kw.qubo.get_val(profit, sol_dict)
print('profit: {}'.format(profit_val))
问题3解答
问题中出现的量与第1问相同
定义决策变量
目标:
约束:借助实现只能选择3种信用卡的约束。对于重复的情况可以单独考虑。
首先,只能选择3张信用卡
然后每张信用卡只能选择一个阈值
参考上述方法进行惩罚项的转化和降阶就完成了本题的建模。 |