本数据集来自一家德国银行,由加州大学霍夫曼教授于 2016 年收集整理,每条记录代表了一个接受银行信贷的客户,这也就说明了,这些客户都是通过了贷款申请的,通过可视化分析对数据进行初步探索,并利用聚类分析将客户分为不同的风险群体,由于数据集中缺乏直接的客户贷款风险标签,我们无法直接评估风险分类的准确性,因此,再次采用聚类分析(不考虑客户贷款风险特征),将数据分为四个类别,分类结果与实际相符,可以构建随机森林模型来识别风险分类的关键因素,虽然无法准确评估模型的精度,但该模型仍可作为初步风险评估的有效工具,从而提高风险识别的效率。
字段 | 说明 |
---|---|
Age | 年龄 |
Sex | 性别,male(男性),female(女性) |
Job | 职业,0 - 无技能且非常驻,1 - 无技能且常驻,2 - 有技能,3 - 高技能 |
Housing | 住房类型:own(自有房产),rent(租房),free(免租赁) |
Saving accounts | 客户的储蓄账户状况 - little(少量),moderate(适中),quite rich(相对富裕),rich(富裕) |
Checking account | 支票账户,little(少量),moderate(适中),rich(富裕) |
Credit amount | 贷款金额,(单位:德国马克) |
Duration | 贷款期限,(单位:月) |
Purpose | 贷款用途,car(汽车),furniture/equipment(家具/设备),radio/TV(收音机/电视),domestic appliances(家用电器),repairs(修理),education(教育),business(商业),vacation/others(假期/其他)。 |
# 导入需要的库
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from sklearn.model_selection import train_test_split
from sklearn.utils import resample
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report,confusion_matrix
data = pd.read_csv(r"./data/german_credit_data.csv")
# 查看数据维度
data.shape
# 查看数据信息
data.info()
# 查看各列缺失值
data.isna().sum()
# 查看重复值
data.duplicated().sum()
# 处理Saving accounts和Checking account中缺失值。
# 考虑到缺失值占比比较大,不建议直接删除,同样的,也不建议用众数填充,这样可能会改变数据情况,这里先用unknown填充。
data['Saving accounts'].fillna('unknown', inplace=True)
data['Checking account'].fillna('unknown', inplace=True)
data.isna().sum()
# 查看分类特征的唯一值
characteristic = ['Sex','Job','Housing','Saving accounts','Checking account','Purpose']
for i in characteristic:
print(f'{i}:')
print(data[i].unique())
print('-'*50)
#数据集重命名
data.columns=['Id','年龄','性别','职业','住房类型','客户的储蓄账户状况','支票账户','贷款金额','贷款期限','贷款用途']
data.info()
# 因为需要进行聚类,所以需要对数据进行初步处理,这里对数值型数据,进行标准化,对分类变量处理为有序变量。
# 选择特征
features = ['年龄', '性别', '职业', '住房类型', '客户的储蓄账户状况', '支票账户', '贷款金额', '贷款期限']
new_data = data[features].copy()
# 对类别型特征进行有序编码
new_data['性别'] = new_data['性别'].map({
'female': 0,
'male': 1})
new_data['住房类型'] = new_data['住房类型'].map({
'free': 0,
'rent': 1,
'own': 2})
new_data['客户的储蓄账户状况'] = new_data['客户的储蓄账户状况'].map({
'unknown': 0,
'little': 1,
'moderate': 2,
'quite rich': 3,
'rich': 4})
new_data['支票账户'] = new_data['支票账户'].map({
'unknown': 0,
'little': 1,
'moderate': 2,
'rich': 3})
# 标准化数值型特征
scaler = StandardScaler()
num_features = ['年龄', '贷款金额', '贷款期限']
new_data[num_features] = scaler.fit_transform(new_data[num_features])
new_data.head(10)
# 模型选择:使用KMeans进行聚类
kmeans = KMeans(n_clusters=2, random_state=15)
clusters = kmeans.fit_predict(new_data)
# 将聚类结果添加到数据中
data['Risk Group'] = clusters
data.head(10)
通过三类不同情况的分析,可以初步判断,0为高风险人群,1为低风险人群,原因如下:
**用户画像:**年龄主要在20-40岁之间,职业主要在2-3级,这一类人是住免租赁或者租房的占比远高于其他三类,储蓄账户状况主要集中在未知和少量,支票账户也是如此,主要集中在未知、少量和适中,贷款金额和贷款周期远超其他三类,贷款主要用于购车,根据风险评估,这类客户全部为高风险。
**建议:**银行和金融机构可以为这个群体提供中期汽车贷款产品,并且可以通过金融教育来提升他们的储蓄和投资能力。
用户画像:年龄分布比较均匀,与类型0相近,职业主要在2级,免租赁的占比较小,储蓄账户状况远超其他三类客户,贷款金额少,周期短,贷款主要用于购买设备,根据风险评估,这类客户全部为低风险。
建议:银行和金融机构可以为这个群体提供短期信用产品,同时考虑他们较高的储蓄能力,可以推广储蓄和投资相关产品。
用户画像:平均年龄在30岁以下,最大年龄不超过45岁,比其他三类都更年轻,职业主要集中在2级,但是其他等级都有存在,租房占比高于其他三类,蓄账户状况主要集中在未知和少量,支票账户主要集中在未知、少量和适中,这类客户的资金情况与类型0类似,贷款情况与类型1类似,风险评估绝大多数为低风险。
建议:鉴于他们是信用初建者和年轻消费者,银行和金融机构可以提供小额信用卡产品和财务规划服务。
用户画像:大龄客户,职业集中在1-2级,大部分有自己的房子,少部分是免租赁,蓄账户状况主要集中在未知和少量,支票账户每个等级均有占比,贷款情况与类型1和类型2类似,也是贷款金额少,周期短,同样的风险评估大多数是低风险。
建议:针对这类客户,银行和金融机构可以提供针对成熟消费者的产品和服务,如退休规划和健康保险,同时关注其稳定的信贷需求。
# 使用肘部法则来确定最佳聚类数
inertia = []
silhouette_scores = []
k_range = range(2, 11)
for k in k_range:
kmeans = KMeans(n_clusters=k, random_state=10).fit(new_data)
inertia.append(kmeans.inertia_)
silhouette_scores.append(silhouette_score(new_data, kmeans.labels_))
这里并没有将风险评估的情况放到聚类数据中,这样可以通过原始数据更好的确定聚类数与聚类情况,并且可以根据聚类结果判断风险评估是否准确。
通过上图,可以得知:
# 执行K-均值聚类,选择4个聚类
kmeans_final = KMeans(n_clusters=4, random_state=15)
kmeans_final.fit(new_data)
# 获取聚类标签
cluster_labels = kmeans_final.labels_
# 将聚类标签添加到原始数据中以进行分析
data['Cluster'] = cluster_labels
通过构建用户画像后,可以认为客户贷款风险评估得到的结果是比较正确的,因此可以建立随机森林模型来预测客户是否存在高风险,以及探究哪个特征是划分风险的重要因素。
x = new_data
y = data['Risk Group']
#采用分层抽样来保证训练集和测试集中目标值与整体数据集的分布相似
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=10, stratify=y) #37分
#分离少数类和多数类
x_minority = x_train[y_train == 0]
y_minority = y_train[y_train == 0]
x_majority = x_train[y_train == 1]
y_majority = y_train[y_train == 1]
x_minority_resampled = resample(x_minority, replace=True, n_samples=len(x_majority), random_state=15)
y_minority_resampled = resample(y_minority, replace=True, n_samples=len(y_majority), random_state=15)
new_x_train = pd.concat([x_majority, x_minority_resampled])
new_y_train = pd.concat([y_majority, y_minority_resampled])
is_in_train = x_train.apply(lambda row: row.isin(new_x_train).all(), axis=1)
duplicates_in_test = x_train[is_in_train]
print(f"测试集中包含训练集的行数: {duplicates_in_test.shape[0]}")
rf_clf = RandomForestClassifier(random_state=15)
rf_clf.fit(new_x_train, new_y_train)
y_pred_rf = rf_clf.predict(x_test)
class_report_rf = classification_report(y_test, y_pred_rf)
print(class_report_rf)
这是相当高的评价,可惜的就是数据中并没有包含客户贷款风险性这个特征,这个特征是通过聚类划分出来的,可能与实际有偏差,我们进一步探究哪个因素是划分的重要依据。
#模型重要特征度
rf_feature_importance = rf_clf.feature_importances_
feature_names = new_x_train.columns
rf_feature_df = pd.DataFrame({
'Feature': feature_names,
'Importance': rf_feature_importance
})
sorted_rf_feature_df = rf_feature_df.sort_values(by='Importance', ascending=False).head() #筛选出前五的重要特征
可以看出来,聚类划分高风险和低风险主要取决于贷款金额和贷款期限。
本项目通过可视化分析对数据进行初步探索,并利用聚类分析将客户分为不同的风险群体,由于数据集中缺乏直接的客户贷款风险标签,我们无法直接评估风险分类的准确性,因此,再次采用聚类分析(不考虑客户贷款风险特征),将数据分为四个类别,分别描述如下:
可以发现,分类结果与实际相符,可以构建随机森林模型来识别风险分类的关键因素。分析结果显示,贷款金额和贷款期限是划分风险的主要依据。虽然无法准确评估模型的精度,但该模型仍可作为初步风险评估的有效工具,从而提高风险识别的效率。