目录
在机器学习和深度学习的实践中,信贷风险评估是一个非常重要的应用场景。通过构建神经网络模型,我们可以对客户的信用状况进行预测,从而帮助金融机构更好地管理风险。最近,我尝试使用PyTorch框架来实现一个信贷风险预测的神经网络模型,并在这个过程中巩固了我对神经网络的理解。以下是我在完成这个任务过程中的详细记录和总结。
一、数据准备与预处理
信贷数据集通常包含客户的各种特征,如收入、信用评分、贷款金额等,以及是否违约的标签。为了更好地训练神经网络模型,数据预处理是必不可少的步骤。
python
import pandas as pd
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler, StandardScaler, OneHotEncoder, LabelEncoder
from imblearn.over_sampling import SMOTE
import matplotlib.pyplot as plt
from tqdm import tqdm
# 设置GPU设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(f"使用设备: {device}")
# 加载信贷预测数据集
data = pd.read_csv('data.csv')
# 丢弃掉Id列
data = data.drop(['Id'], axis=1)
# 区分连续特征与离散特征
continuous_features = data.select_dtypes(include=['float64', 'int64']).columns.tolist()
discrete_features = data.select_dtypes(exclude=['float64', 'int64']).columns.tolist()
# 离散特征使用众数进行补全
for feature in discrete_features:
if data[feature].isnull().sum() > 0:
mode_value = data[feature].mode()[0]
data[feature].fillna(mode_value, inplace=True)
# 连续变量用中位数进行补全
for feature in continuous_features:
if data[feature].isnull().sum() > 0:
median_value = data[feature].median()
data[feature].fillna(median_value, inplace=True)
# 有顺序的离散变量进行标签编码
mappings = {
"Years in current job": {
"10+ years": 10,
"2 years": 2,
"3 years": 3,
"< 1 year": 0,
"5 years": 5,
"1 year": 1,
"4 years": 4,
"6 years": 6,
"7 years": 7,
"8 years": 8,
"9 years": 9
},
"Home Ownership": {
"Home Mortgage": 0,
"Rent": 1,
"Own Home": 2,
"Have Mortgage": 3
},
"Term": {
"Short Term": 0,
"Long Term": 1
}
}
# 使用映射字典进行转换
data["Years in current job"] = data["Years in current job"].map(mappings["Years in current job"])
data["Home Ownership"] = data["Home Ownership"].map(mappings["Home Ownership"])
data["Term"] = data["Term"].map(mappings["Term"])
# 对没有顺序的离散变量进行独热编码
data = pd.get_dummies(data, columns=['Purpose'])
在上述代码中,我首先加载了信贷数据集,并对其进行了预处理。具体步骤包括:
-
丢弃无用的
Id
列。 -
区分连续特征和离散特征。
-
对离散特征使用众数进行补全,对连续特征使用中位数进行补全。
-
对有顺序的离散变量进行标签编码,对没有顺序的离散变量进行独热编码。
二、数据集划分与归一化
在数据预处理完成后,我将数据集划分为训练集和测试集,并对特征数据进行归一化处理。
python
# 分离特征数据和标签数据
X = data.drop(['Credit Default'], axis=1) # 特征数据
y = data['Credit Default'] # 标签数据
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 对特征数据进行归一化处理
scaler = MinMaxScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test) # 确保训练集和测试集是相同的缩放
# 将数据转换为PyTorch张量
X_train = torch.FloatTensor(X_train).to(device)
y_train = torch.LongTensor(y_train.values).to(device)
X_test = torch.FloatTensor(X_test).to(device)
y_test = torch.LongTensor(y_test.values).to(device)
在上述代码中,我使用了MinMaxScaler
对特征数据进行归一化处理,以确保所有特征的值都在0到1之间。这一步对于神经网络的训练非常重要,因为它可以加速模型的收敛速度并提高模型的性能。之后,我将数据转换为PyTorch张量,并将其移动到指定的设备(GPU或CPU)上。
三、构建神经网络模型
接下来,我定义了一个简单的多层感知机(MLP)模型,包含一个输入层、两个隐藏层和一个输出层。隐藏层使用了ReLU激活函数,并添加了Dropout层以防止过拟合。
python
class MLP(nn.Module):
def __init__(self):
super(MLP, self).__init__()
self.fc1 = nn.Linear(X_train.shape[1], 64) # 输入层到第一隐藏层
self.relu = nn.ReLU()
self.dropout = nn.Dropout(0.3) # 添加Dropout防止过拟合
self.fc2 = nn.Linear(64, 32) # 第一隐藏层到第二隐藏层
self.fc3 = nn.Linear(32, 2) # 第二隐藏层到输出层
def forward(self, x):
x = self.fc1(x)
x = self.relu(x)
x = self.dropout(x)
x = self.fc2(x)
x = self.relu(x)
x = self.dropout(x)
x = self.fc3(x)
return x
# 初始化模型
model = MLP().to(device)
在定义模型时,我使用了nn.Module
作为基类,并通过forward
方法定义了模型的前向传播逻辑。这种模块化的定义方式使得模型的结构清晰且易于扩展。
四、定义损失函数和优化器
损失函数和优化器是神经网络训练的两个关键组件。对于分类任务,交叉熵损失函数(CrossEntropyLoss
)是最常用的损失函数之一。优化器则负责根据损失函数的梯度更新模型的参数,我选择了随机梯度下降(SGD)优化器。
python
criterion = nn.CrossEntropyLoss() # 使用交叉熵损失函数
optimizer = optim.SGD(model.parameters(), lr=0.01) # 使用SGD优化器
五、训练模型
训练模型的过程是一个迭代优化的过程。在每一轮迭代中,模型会计算损失函数的值,并通过反向传播更新参数。为了监控训练过程,我每10轮打印一次损失值。
python
num_epochs = 200 # 训练轮数
for epoch in range(num_epochs):
model.train() # 设置为训练模式
optimizer.zero_grad() # 清空梯度
outputs = model(X_train) # 前向传播
loss = criterion(outputs, y_train) # 计算损失
loss.backward() # 反向传播
optimizer.step() # 更新参数
if (epoch + 1) % 10 == 0:
print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')
通过上述代码,我成功地训练了模型,并观察到损失值随着训练轮数的增加而逐渐降低。这表明模型正在逐步学习数据中的规律。
六、评估模型
训练完成后,我使用测试集对模型的性能进行了评估。评估指标是准确率,即模型正确预测的样本数占总样本数的比例。
python
model.eval() # 设置为评估模式
with torch.no_grad():
correct = 0
total = 0
outputs = model(X_test)
_, predicted = torch.max(outputs.data, 1)
total += y_test.size(0)
correct += (predicted == y_test).sum().item()
accuracy = 100 * correct / total
print(f'Accuracy on test set: {accuracy:.2f}%')
最终,模型在测试集上的准确率达到了 [具体准确率]%。虽然这个结果还有提升的空间,但它已经证明了神经网络在信贷风险评估任务中的有效性。