摘要:
合集:AI案例-ML-泛金融业
AI问题:回归预测问题
数据集:信用评分卡建模数据集
数据集价值:信用违约概率计算、信用评分。
解决方案:特征筛选、随机森林算法、评分转换。
一、问题描述
银行在市场经济中起着至关重要的作用。他们决定谁可以获得融资,以什么条件获得资金,可以制定或中断投资决策。为了使市场和社会发挥作用,个人和公司都需要获得信贷。信用评分卡是一种广泛应用于信用风险评估领域的工具,通过数学模型和统计分析技术,根据客户的特征或行为数据生成一个数值评分,从而预测其违约风险或信用表现。
信用评分卡的核心思想是将客户的信用风险量化为一个单一的分值,通过比较分值来判断客户的信用风险。信用分值越高,违约风险越低;信用分值越低,违约风险越高。
- 数据驱动: 基于历史数据(如贷款记录、还款行为、个人特征等)构建模型,通过挖掘数据中的模式,预测未来行为。
- 统计和机器学习: 使用统计模型(如逻辑回归)或机器学习技术(如决策树)来建立变量与目标变量(如违约)的关系。
- 评分转换: 将模型的输出概率转换为直观的信用评分,通常通过线性变换实现。
二、信用数据集内容
客户信用数据可以用于猜测一客户违约的可能性,是银行用来确定是否应授予贷款的依据。基于该客户信用数据集,可通过预测未来两年内某人会遇到财务困境的可能性,来改善其信用评分的最新水平。
客户信用数据数据集包括训练数据记录数15万笔,测试数据记录数101,503笔。
数据结构
GiveMeSomeCredit目录下的信用评分卡建模数据集cs-training.csv和cs-test.csv的字段定义如下:
1. SeriousDlqin2yrs - 两年内是否出现过严重拖欠。
2. RevolvingUtilizationOfUnsecuredLines - 无抵押信贷额度利用率。
3. age - 年龄。
4. NumberOfTime30-59DaysPastDueNotWorse - 30-59天的逾期次数。
5. DebtRatio - 债务比率。
6. MonthlyIncome - 月收入。
7. NumberOfOpenCreditLinesAndLoans - 开通的信用账户和贷款数量。
8. NumberOfTimes90DaysLate - 逾期90天的次数。
9. NumberRealEstateLoansOrLines - 房地产贷款或信用额度数量。
10. NumberOfTime60-89DaysPastDueNotWorse - 60-89天的逾期次数。
11. NumberOfDependents - 家属人数。
数据样例:
SeriousDlqin2yrs | RevolvingUtilizationOfUnsecuredLines | age | NumberOfTime30-59DaysPastDueNotWorse | DebtRatio | MonthlyIncome | NumberOfOpenCreditLinesAndLoans | NumberOfTimes90DaysLate | NumberRealEstateLoansOrLines | NumberOfTime60-89DaysPastDueNotWorse | NumberOfDependents | ||
---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 1 | 0.766126609 | 45 | 2 | 0.802982129 | 9120 | 13 | 0 | 6 | 0 | 2 | |
2 | 0 | 0.957151019 | 40 | 0 | 0.121876201 | 2600 | 4 | 0 | 0 | 0 | 1 | |
3 | 0 | 0.65818014 | 38 | 1 | 0.085113375 | 3042 | 2 | 1 | 0 | 0 | 0 | |
4 | 0 | 0.233809776 | 30 | 0 | 0.036049682 | 3300 | 5 | 0 | 0 | 0 | 0 | |
5 | 0 | 0.9072394 | 49 | 1 | 0.024925695 | 63588 | 7 | 0 | 1 | 0 | 0 | |
6 | 0 | 0.213178682 | 74 | 0 | 0.375606969 | 3500 | 3 | 0 | 1 | 0 | 1 |
三、信用评分卡建模
安装
conda create -n datamining python=3.12
conda activate datamining
conda install numpy pandas matplotlib seaborn
conda install statsmodels
conda install openpyxl
参考AI基础专栏中的《安装传统机器学习开发包》。
安装后的开发包版本信息:
python 3.12.7 h14ffc60_0 anaconda
numpy 1.26.4 py312hfd52020_0 anaconda
scipy 1.13.1 py312hbb039d4_0 anaconda
pandas 2.2.2 py312h0158946_0 anaconda
scikit-learn 1.5.1 py312h0158946_0 anaconda
matplotlib 3.9.2 py312haa95532_0 anaconda
seaborn 0.13.2 py312haa95532_0 anaconda
statsmodels 0.14.2 py312h4b0e54e_0 anaconda
openpyxl 3.1.5
信用评分系统样例
利用Python进行申请评分卡的数据清洗、建模分析。对GiveMeSomeCredit目录下的数据集进行挖掘分析,包括:
- 数据的预处理(主要缺失值和异常值的处理)
- 数据分析(特征变量的选择、分箱、WOE、IV)
- 数据建模(逻辑回归模型,集成算法)
- 创建信用评分卡
- 创建了一个简单的信用评分系统
决策树是一种监督学习算法,用于解决分类和回归问题。它通过构建一个树状模型,将数据集划分为不同的子集,从而进行预测。决策树的结构包括根节点、内部节点和叶节点,每个节点代表一个特征测试,每个分支代表特征测试的结果,每个叶节点代表一个类别或预测值。
随机森林算法是一种集成学习(Ensemble Learning)方法,通过构建多个决策树(Decision Tree)并将它们的预测结果进行汇总来提高模型的准确性和稳定性。随机森林具有多种优点,如可以产生高准确度的分类器,能处理大量的输入变数,在决定类别时评估变数的重要性,对一般化后的误差产生不偏差的估计,以及能够平衡不平衡的分类资料集的误差。
工作原理
- 构建多棵决策树:随机森林包含许多独立的决策树,每棵树都在数据的随机子集上训练。
- 特征选择:在每个节点分裂时,不是使用全部特征,而是从所有特征中随机选择一个子集进行评估。
- 投票机制:对于分类问题,最终的预测结果是所有树预测类别的众数;而对于回归问题,则是所有树预测值的平均值。
参数设置
在使用随机森林算法时,你可以调整多个参数来优化模型性能:
- n_estimators:森林中树的数量,默认值为100。
- max_depth:树的最大深度,控制模型的复杂度。
- min_samples_split:内部节点再划分所需的最少样本数。
- min_samples_leaf:叶子节点最少样本数。
- max_features:寻找最佳分割时要考虑的特征数量。
- 随机状态:随机数生成器的种子,确保结果的可复现性。
以下函数用随机森林对缺失值预测填充函数:
from sklearn.ensemble import RandomForestRegressor
# 用随机森林对缺失值预测填充函数
def set_missing(df):
# 把已有的数值型特征取出来
process_df = df.iloc[:, [5,0,1,2,3,4,6,7,8,9]]
# 分成已知该特征和未知该特征两部分
known = process_df[process_df.MonthlyIncome.notnull()].to_numpy()
unknown = process_df[process_df.MonthlyIncome.isnull()].to_numpy()
# X为特征属性值
X = known[:, 1:]
# y为结果标签值
y = known[:, 0]
# fit到RandomForestRegressor之中
rfr = RandomForestRegressor(random_state=0, n_estimators=200, max_depth=3, n_jobs=-1)
rfr.fit(X, y)
# 用得到的模型进行未知特征值预测
predicted = rfr.predict(unknown[:, 1:]).round(0)
print("预测值: ", predicted)
# 用得到的预测结果填补原缺失数据
df.loc[(df.MonthlyIncome.isnull()), 'MonthlyIncome'] = predicted
return df
函数compute_score(): 这段代码的目的是根据给定的分数段(cut)和对应的分数(score),计算一个序列(series)中每个元素的信用评分
def compute_score(series, cut, score):
list = []
i = 0
while i < len(series):
value = series[i]
j = len(cut) - 2
m = len(cut) - 2
while j >= 0:
if value >= cut[j]:
j = -1
else:
j -= 1
m -= 1
list.append(score[m])
i += 1
return list
根据信用测试数据生成信用评分卡:
1、读取CSV文件 2、初始化BaseScore列 3、计算各个特征评分 4、计算总评分 5、保存结果到CSV文件
test1 = pd.read_csv('TestData.csv')
test1['BaseScore'] = Series(np.zeros(len(test1))) + baseScore
test1['x1'] = Series(compute_score(test1['RevolvingUtilizationOfUnsecuredLines'], cutx1, x1))
test1['x2'] = Series(compute_score(test1['age'], cutx2, x2))
test1['x3'] = Series(compute_score(test1['NumberOfTime30-59DaysPastDueNotWorse'], cutx3, x3))
test1['x5'] = Series(compute_score(test1['MonthlyIncome'], cutx5, x5))
test1['x6'] = Series(compute_score(test1['NumberOfOpenCreditLinesAndLoans'], cutx6, x6))
test1['x7'] = Series(compute_score(test1['NumberOfTimes90DaysLate'], cutx7, x7))
test1['x9'] = Series(compute_score(test1['NumberOfTime60-89DaysPastDueNotWorse'], cutx9, x9))
test1['Score'] = test1['x1'] + test1['x2'] + test1['x3'] + test1['x7'] +test1['x9'] + baseScore
test1.to_csv('ScoreData.csv', index=False)
评分卡ScoreData.csv数据样例:
SeriousDlqin2yrs | RevolvingUtilizationOfUnsecuredLines | age | NumberOfTime30-59DaysPastDueNotWorse | DebtRatio | MonthlyIncome | NumberOfOpenCreditLinesAndLoans | NumberOfTimes90DaysLate | NumberRealEstateLoansOrLines | NumberOfTime60-89DaysPastDueNotWorse | NumberOfDependents | BaseScore | x1 | x2 | x3 | x5 | x6 | x7 | x9 | Score |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.005190265 | 73 | 0 | 0.248842807 | 5400 | 16 | 0 | 1 | 0 | 0 | 247 | -25 | -14 | 29 | 1 | -2 | 88 | 58 | 383 |
0 | 0.801765556 | 52 | 0 | 0.997576492 | 3300 | 9 | 0 | 1 | 0 | 1 | 247 | 20 | 1 | 29 | 2 | -2 | 88 | 58 | 443 |
0 | 0.9999999 | 82 | 0 | 0 | 5356 | 1 | 0 | 0 | 0 | 0 | 247 | 20 | -14 | 29 | 1 | 5 | 88 | 58 | 428 |
0 | 0.48905071 | 30 | 0 | 0.112054329 | 5300 | 5 | 0 | 0 | 0 | 1 | 247 | -5 | 8 | 29 | 1 | -2 | 88 | 58 | 425 |
0 | 0.092283317 | 68 | 0 | 1.566520924 | 1159 | 6 | 0 | 0 | 0 | 0 | 247 | -22 | -12 | 29 | 2 | -2 | 88 | 58 | 388 |