当前位置: 首页 > article >正文

项目8:信用违约预测-集成学习

目录

背景说明

项目介绍

导入模块

数据加载

分析与处理数据

划分数据集

使用随机森林创建并训练模型

通过参数搜索和过采样,缓解标签不平衡问题

小结


背景说明

风险已经成为了今年金融市场的重要主题之一,银行作为贷方,随时都面临着借贷者违约的风险。传统的专家规则在金融科技时代逐渐过时,机器学习和金融业务的交叉也延伸到信贷领域。违约预测就是其中一重要应用。本实验基于信贷业务场景中一个月内的抽样数据,数据集有34个维度,Target表示客户在接下来一个月是否有违约。模型生成后可使用当前月的数据预测接下来一个月客户是否会违约。

项目介绍

违约预测只有违约和没有预约两种结果,是个二分类问题。针对二分类问题,可使用的算法有逻辑回归、朴素贝叶斯、支持向量机、树模型等。本实验选用集成学习的算法来拟合数据。考虑到样本极度不均衡,模型评价选用综合指标f1_score。

导入模块

# 数据读取、处理、分析、可视化,算法模块等
import pandas as pd
import numpy as np
#导入相关包
%matplotlib inline
# import seaborn as sns
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")

数据加载

读入数据,数据文件是dataset-credit-default.csv,定义为df。查看数据尺寸、打印信息,##查看Target的分布 ,是否违约(1是,0否)等

df = pd.read_csv('./数据集/dataset-credit-default.csv')
df

# 查看数据尺寸
print(df.shape)

# 打印信息
print(df.info())

# 查看Target的分布,是否违约(1是,0否)
print(df['Target'].value_counts(normalize=True))

分析与处理数据

观察数据缺失情况,把缺失比例超过20%的数据列删掉

data = df[df.columns[df.notnull().sum()/len(df)>0.8]].dropna(axis=0) 

划分数据集

提取特征数据X和目标数据y。

X = data.drop('Target', axis=1)
y = data['Target']

划分训练集和测试集,通过观察发现正样本与负样本非常不平衡。将数据集作3:1的划分,按照标签比例做分层抽样,分出训练集和测试集,观察每个数据集中正负样本数量。

from sklearn.model_selection import train_test_split

# 3:1的划分,按照标签比例做分层抽样
X_train, X_test, y_train, y_test = train_test_split(X, y,         test_size=0.25, stratify=y, random_state=42)

# 观察每个数据集中正负样本数量
print(y_train.value_counts())
print(y_test.value_counts())

引入StandardScaler标准化工具库,对训练集和测试集做标准化

from sklearn.preprocessing import StandardScaler

# 对训练集和测试集做标准化
std_scaler = StandardScaler().fit(X_train)
X_train_std = std_scaler.transform(X_train)
X_test_std = std_scaler.transform(X_test)

标准化后的测试集

X_train_std

X_test_std

查看X_train_std

模块化处理:对从分析与处理数据-划分数据集进行函数(模块化)处理

# 通过函数化的编程思想,把上面数据预处理的过程模块化
# 实现 分析与处理数据 -- 划分数据集 -- 对训练集和测试集做标准化
def process_data(df):
    """
    传入读入的df
    """
    # 把缺失比例超过20%的数据列删掉
    data = df[df.columns[df.notnull().sum()/len(df)>0.8]].dropna(axis=0) 

    # 提取特征数据X和目标数据y
    X = data.drop('Target', axis=1)
    y = data['Target']

    # 3:1的划分,按照标签比例做分层抽样
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, 
                                                    stratify=y, random_state=42)
    # 此时得到了return的y_train, y_test,还需标准化X_train, X_test
    # 对训练集和测试集做标准化
    std_scaler = StandardScaler().fit(X_train)
    X_train_std = std_scaler.transform(X_train)
    X_test_std = std_scaler.transform(X_test)

    # 返回标准化后的训练集、测试集和训练标签、测试标签
    return X_train_std,X_test_std,y_train, y_test

测试模块化后的函数是否可用

df2 = pd.read_csv('./数据集/dataset-credit-default.csv')

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
X_train_std,X_test_std,y_train, y_test = process_data(df2)
X_train_std,X_test_std,len(X_train_std),len(X_test_std)

使用随机森林创建并训练模型

引入随机森林的库,构建并训练模型。

from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, recall_score, precision_score, f1_score, confusion_matrix
import matplotlib.pyplot as plt
import seaborn as sns

# 创建随机森林分类器
rf_model = RandomForestClassifier(random_state=42)

# 训练模型
rf_model.fit(X_train_std, y_train)

对模型进行评价:准确率、召回率、精确率和f1分数。

# 对测试集进行预测
y_test_pred1 = rf_model.predict(X_test_std)

# 计算评估指标
accuracy = accuracy_score(y_test, y_test_pred1)
recall = recall_score(y_test, y_test_pred1)
precision = precision_score(y_test, y_test_pred1)
f1 = f1_score(y_test, y_test_pred1)

# 打印评估结果
print(f"准确率: {accuracy:.4f}")
print(f"召回率: {recall:.4f}")
print(f"精确率: {precision:.4f}")
print(f"F1分数: {f1:.4f}")

观察混淆矩阵,深入了解模型性能

from sklearn.metrics import ConfusionMatrixDisplay, confusion_matrix

cm = confusion_matrix(y_test, y_test_pred1, labels=rf_model.classes_)
disp_1 = ConfusionMatrixDisplay(confusion_matrix=cm,display_labels=rf_model.classes_)
disp_1.plot()

通过参数搜索和过采样,缓解标签不平衡问题

正反样本分开

X_train_0 = X_train[y_train==0]
y_train_0 = y_train[y_train==0]
X_train_1 = X_train[y_train==1]
y_train_1 = y_train[y_train==1]

对正样本过采样

# 过采样后的正样本数量将接近负样本数量的一半,从而一定程度上减少类别不平衡

from sklearn.utils import resample
X_train_1_res,y_train_1_res = resample(X_train_1,y_train_1,replace=True,n_samples=int(len(X_train_0)*0.5),random_state=42)
X_train_res = np.vstack([X_train_0,X_train_1_res])
y_train_res = np.hstack([y_train_0,y_train_1_res])

# 引入StandardScaler标准化工具库
from sklearn.preprocessing import StandardScaler
#对训练集和测试集做标准化
std_scaler_res = StandardScaler().fit(X_train_res)
X_train_std_res = std_scaler.transform(X_train_res)

from sklearn.model_selection import cross_val_score
cv_scores = cross_val_score(rf_model, X_train_std_res, y_train_res,  cv=5)  
print('cross validation score of model version1 {}'.format(cv_scores))

随机森林调参

参数搜索矩阵如下:

param_test0 = {'class_weight':[{0:0.8,1:0.2},{0:0.7,1:0.3},{0:0.1,1:0.9},'balanced'],
               'max_depth':[2,4,6,8],
               'n_estimators':[50,100,200]}

from sklearn.model_selection import GridSearchCV

# 创建 GridSearchCV 对象
grid_search = GridSearchCV(estimator=rf_model, param_grid=param_test0, scoring='f1', cv=5, n_jobs=-1, verbose=1)

# 执行网格搜索
grid_search.fit(X_train_std_res, y_train_res)

# 输出最佳参数
print("最佳参数:", grid_search.best_params_)
print("最佳分数:", grid_search.best_score_)

# 输出所有结果
results = grid_search.cv_results_
for mean_score, params in zip(results['mean_test_score'], results['params']):
    print(f"参数: {params}, 平均分数: {mean_score:.4f}")

随机森林模型效果评估

# 使用最佳参数构建随机森林模型
rf_model_res = RandomForestClassifier(
    class_weight='balanced',
    max_depth=8,
    n_estimators=200,
    random_state=42
)

# 训练模型(使用过采样后的数据)
rf_model_res.fit(X_train_std_res, y_train_res)

# 对测试集进行预测
y_pred_res = rf_model_res.predict(X_test_std)

# 计算评估指标
accuracy_res = accuracy_score(y_test, y_pred_res)
recall_res = recall_score(y_test, y_pred_res)
precision_res = precision_score(y_test, y_pred_res)
f1_res = f1_score(y_test, y_pred_res)

# 打印评估结果
print("过采样后的模型性能:")
print(f"准确率: {accuracy_res:.4f}")
print(f"召回率: {recall_res:.4f}")
print(f"精确率: {precision_res:.4f}")
print(f"F1分数: {f1_res:.4f}")

观察混淆矩阵

# 计算混淆矩阵
conf_matrix_res = confusion_matrix(y_test, y_pred_res)

# 绘制混淆矩阵
plt.figure(figsize=(8, 6))
sns.heatmap(conf_matrix_res, annot=True, fmt='d', cmap='Blues', 
            xticklabels=['Predicted 0', 'Predicted 1'], 
            yticklabels=['Actual 0', 'Actual 1'])
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.title('Confusion Matrix (After Oversampling)')
plt.show()

过采样前后的结果对比

# 过采样前的模型性能(假设已经训练过并保存了结果)
print("过采样前的模型性能:")
print(f"准确率: {accuracy:.4f}")
print(f"召回率: {recall:.4f}")
print(f"精确率: {precision:.4f}")
print(f"F1分数: {f1:.4f}")

# 过采样后的模型性能
print("\n过采样后的模型性能:")
print(f"准确率: {accuracy_res:.4f}")
print(f"召回率: {recall_res:.4f}")
print(f"精确率: {precision_res:.4f}")
print(f"F1分数: {f1_res:.4f}")

过采样前后的混淆矩阵的结果对比

# 过采样前的混淆矩阵(假设已经计算过并保存为 conf_matrix)
plt.figure(figsize=(12, 5))

# 过采样前的混淆矩阵
plt.subplot(1, 2, 1)
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', 
            xticklabels=['Predicted 0', 'Predicted 1'], 
            yticklabels=['Actual 0', 'Actual 1'])
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.title('Confusion Matrix (Before Oversampling)')

# 过采样后的混淆矩阵
plt.subplot(1, 2, 2)
sns.heatmap(conf_matrix_res, annot=True, fmt='d', cmap='Blues', 
            xticklabels=['Predicted 0', 'Predicted 1'], 
            yticklabels=['Actual 0', 'Actual 1'])
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.title('Confusion Matrix (After Oversampling)')

plt.tight_layout()
plt.show()

小结

本实验主要使用Python进行数据预处理、数据分析,使用Matplotlib做可视化分析,使用过采样方法平衡正反例数据,使用随机森林建模,使用网格搜索来寻找最优参数组合。违约预测问题面临着所需数据维度多、正负样本严重不均衡等问题,在实际应用上,可以多搜集各类维度的特征,多尝试过采样、欠采样,也可以尝试使用无监督学习、深度神经网络等。


http://www.kler.cn/a/558779.html

相关文章:

  • Debian软件包重构
  • PAT甲级 1103 Integer Factorization
  • Android Loader机制解析
  • elf_loader:一个使用Rust编写的ELF加载器
  • RabbitMQ学习—day6—死信队列与延迟队列
  • 网络IP跳动问题解决详
  • flink operator v1.10部署flink v1.19.2
  • 前后端分离系统架构:基于Spring Boot的最佳实践
  • Python数据结构深度探索:树的构建与遍历
  • 跟据spring boot版本,查看对应的tomcat,并查看可支持的tomcat的版本范围
  • 高速PCB电源层
  • 跟着 Lua 5.1 官方参考文档学习 Lua (8)
  • MyBatis框架七:缓存
  • 智能测试执行 利用算法 利用图像识别、自然语言处理等技术实现自动化测试执行
  • 《操作系统 - 清华大学》8 -1:进程管理:进程的定义
  • C++入门基础课程讲解
  • 解决每次 Maven Rebuild 后 Java 编译器版本变为 1.5
  • jmeter后端监视器的妙用和实现方法
  • 【网络】如何划分子网、计算子网掩码、确定网络地址、广播地址和可用主机地址范围?
  • 通俗理解什么是云原生?