网络知识 娱乐 2020年数学建模国赛C题思路及代码

2020年数学建模国赛C题思路及代码

问题一二的重点在于

  1. 是否贷款
  2. 贷多少款

数据清洗

我的思路主要是使用随机森林进行违约概率的预测,第一步就是需要将原始数据清洗处理,提取所需的特征。

  1. 将发票是否有效处理成 0-1数据,将信誉评级处理成(1,2,3,4)并将xlsx的文件格式转为csv的文件格式python处理起来更加方便。

  2. 选取训练特征

'进项作废比','净利润率','销项作废比','负税压力','销售交易数','客户数量','发票时间'

一共选取了七个特征进行处理

  • 作废比:分别将进项与销项的无效发票数与有效发票数作比,一定程度反应企业的交易成功率

  • 净利润率:计算每家企业的盈利能力

  • 负税压力:计算所交的所有税与销售量的比值

  • 销售交易数:有效销售发票个数

  • 客户数量:购房单位的不同数量

  • 发票时间:所有发票持续的时间天数

  1. 程序代码

    #数据转换
    # sheet1 = pd.read_excel('./data/302Loan.xlsx',sheet_name=1)
    # sheet1.to_csv('./data/302output.csv',index=False,encoding='utf8')
    # sheet2 = pd.read_excel('./data/302Loan.xlsx',sheet_name=2)
    # sheet2.to_csv('./data/302input.csv',index=False,encoding='utf8')
    # print('数据转换完成')
    #
    
    #################################
    # 数据清洗
    data_in = pd.read_csv('./data/input.csv')
    data_out = pd.read_csv('./data/output.csv')
    data_in['是否有效'] = data_in['发票状态'].apply(lambda s:1 if s=='有效发票' else 0)
    data_out['是否有效'] = data_out['发票状态'].apply(lambda s:1 if s=='有效发票' else 0)
    Conpanies = data_in['企业代号'].unique()
    
    column = ['企业代号','进项作废比','净利润率','销项作废比','负税压力','销售交易数','客户数量','发票时间']
    temp = []
    
    for i in Conpanies:
        Conpany_in = data_in.loc[data_in['企业代号'] == i, :]
        Conpany1_in = Conpany_in.loc[Conpany_in['是否有效'] == 1, :]
        count1_in = Conpany1_in.shape[0]
        sum1_in = Conpany1_in.iloc[:, 4:6].sum(axis=0)
        a1_in, b1_in = sum1_in
        Conpany0_in = Conpany_in.loc[Conpany_in['是否有效'] == 0, :]
        count0_in = Conpany0_in.shape[0]
        sum0_in = Conpany0_in.iloc[:, 4:6].sum(axis=0)
        a0_in, b0_in = sum0_in
        rate_in = count0_in /count1_in
        nums_in = Conpany1_in['销方单位代号'].unique()
    
        Conpany_out = data_out.loc[data_out['企业代号'] == i, :]
        Conpany1_out = Conpany_out.loc[Conpany_out['是否有效'] == 1, :]
        count1_out = Conpany1_out.shape[0]
        sum1_out = Conpany1_out.iloc[:, 4:6].sum(axis=0)
        a1_out, b1_out = sum1_out
        Conpany0_out = Conpany_out.loc[Conpany_out['是否有效'] == 0, :]
        count0_out = Conpany0_out.shape[0]
        sum0_out = Conpany0_out.iloc[:, 4:6].sum(axis=0)
        a0_out, b0_out = sum0_out
        rate_out = count0_out /count1_out
        rate4 = a1_out/count1_out
        nums = Conpany1_out['购方单位代号'].unique()
    
        rate2 = (a1_out-b1_out)/a1_out
        rate5 = (b1_out+b1_in)/a1_out
    
        days1 = pd.to_datetime(Conpany1_in.开票日期).max()-pd.to_datetime(Conpany1_in.开票日期).min()
        days2 = pd.to_datetime(Conpany1_out.开票日期).max()-pd.to_datetime(Conpany1_out.开票日期).min()
        temp.append((i,rate_in,rate2,rate_out,rate5,count1_out,len(nums),max(days1.days,days2.days)))
    
    df_temp = pd.DataFrame(temp,columns=column)
    df_temp.to_csv('./data/procesed_data.csv',encoding='utf8',index=False)
    print('数据处理完成')
    
    

模型拟合

选择随机森林的原因:

  1. 可以提供预测概率,作为部分后续评判标准
  2. 随机森林分类器较决策树准确率较高。在训练模型的时候首先要将数据进行标准化
def process_feature(X):
    m,n = X.shape
    scaler = StandardScaler()
    X = scaler.fit_transform(X)
    
    # scaler = MinMaxScaler(feature_range=(0,1))
    # X = scaler.fit_transform(X) # 建议不放缩,效果不理想 
    
    X = np.c_[np.ones((m,1)),X]
    return X

通过sklearn模型的拟合预测整个的准确率可以达到 99.18% 拟合的效果非常好

有了每个企业的违约率,正常情况下,显然守约概率高的企业可以贷款到更多的资金,所以将企业守约概率除以所有企业的守约概率和作为权重比例分配贷款总金额。
w i = 1 − p i ∑ i = 1 n ( 1 − p i ) w_i =frac{1-p_i}{sum_{i=1}^n(1-p_i)} wi=i=1n(1pi)1pi

年利率与流失率

将附件3中的贷款年利率信息与不同信誉值之间的客户流失率输入到SPSS软件中进行数据拟合,拟合结果

信誉等级R2关系式
A0.9977 y = 37.97 x 3 + − 258.57 x 2 + 640.994 x − 1.12 y=37.97x^3+-258.57x^2+640.994x-1.12 y=37.97x3+258.57x2+640.994x1.12
B0.9982 y = 33.995 x 3 − 225.05 x 2 + 552.829 x − 1.017 y=33.995x^3-225.05x^2+552.829x-1.017 y=33.995x3225.05x2+552.829x1.017
C0.9982 y = 32.157 x 3 − 207.386 x 2 + 504.717 x − 0973 y=32.157x^3-207.386x^2+504.717x-0973 y=32.157x3207.386x2+504.717x0973

而银行收益率:年利率(1-流失率)*,通过此关系式可以计算银行的最终收益率的最大值,从而计算出此时所需要的最优年利率

信誉等级最优年利率客户流失率
A0.0830.5030
B0.0970.5052
C0.010690.5065

信誉等级随机森林预测

将标签数据简单处理

sheet1 = pd.read_csv('./data/con_info.csv')#表一
sheet1['default_index'] = sheet1['是否违约'].apply(lambda x:1 if x=='是' else 0)

sheet1['index'] = sheet1['信誉评级'].apply(lambda x:1 if x=='A' else(2 if x=='B' else
                                                                         (3 if x=='C' else
                                                                         4)) )

同样与上面相类似的方式训练模型得到的准确率为 94.30%

模型保存

模型保存可以直接使用 joblib库直接将训练好的模型保存

import joblib
joblib.dump(model,'./model/fr.model') # 保存模型

model = joblib.load('./model/fr.model') # 读取模型

读取好模型就可以直接使用

问题二就可以直接该模型进行302家企业的相关预测并将一亿元按照权重分配贷款金额并确定贷款年利率