首页 > 编程开发 > python数据分析 >
-
实战项目2:金融风控数据分析(对接真实银行数据)
实战项目2:金融风控数据分析(对接真实银行数据)
18.83.1 引言:从银行风控专员小王的“风控困惑”说起
咱们先还原银行风控专员小王的真实经历:
小王是某银行的风控专员,2025年他负责10万贷款用户的风控工作,但他只会用Excel做简单的风控分析,不知道怎么用Python对接真实银行数据做深度风控分析,导致无法及时识别高风险用户。老板让他在一周内提交风控分析报告,但他不知道vb.net教程C#教程python教程SQL教程access 2010教程怎么解决这个问题。
小王的问题也是很多金融风控从业者的问题:只会用Excel做简单的风控分析,不会用Python对接真实银行数据做深度风控分析,导致无法及时识别高风险用户。今天咱们就用某银行的10万贷款用户数据这个实战场景,手把手教你用Python对接真实银行数据做金融风控数据分析,包括数据加载、数据探索、风控指标计算、风险用户识别、风控模型训练、结果可视化、业务分析等。全程代码逐行讲解,拓展知识点全是能直接套用的干货,看完你也能轻松用Python对接真实银行数据做金融风控数据分析,告别风控困惑。
18.83.2 一、金融风控的基本原理:从“风险识别”到“风险控制”
2.1 什么是金融风控?
金融风控是指通过对金融数据进行分析,识别潜在的风险,采取相应的措施进行风险控制,比如拒绝高风险用户的贷款申请、提高高风险用户的贷款利率等。金融风控可以帮助银行降低坏账率,提高盈利能力。
2.2 金融风控的基本流程
金融风控的基本流程是:
1.数据收集:收集用户数据,比如用户基本信息、贷款信息、还款信息等;
2.数据预处理:对用户数据进行清洗、标准化、特征选择等;
3.风控指标计算:计算风控指标,比如逾期率、坏账率、违约概率等;
4.风险用户识别:使用风控模型识别高风险用户;
5.风险控制措施:根据风险用户识别结果,采取相应的风险控制措施;
6.效果评估:评估风险控制措施的效果,比如坏账率、盈利能力等;
2.3 金融风控的常见指标
金融风控的常见指标包括以下几种:
逾期率:逾期贷款用户占所有贷款用户的比例;
坏账率:坏账贷款用户占所有贷款用户的比例;
违约概率:用户违约的概率;
贷款回收率:回收的贷款金额占所有贷款金额的比例;
风险敞口:银行面临的潜在风险金额;
18.83.3 二、实战:对接真实银行数据做金融风控数据分析
3.1 数据准备:从“银行数据”到“特征数据”
咱们用的是某银行的10万贷款用户数据,包含10万条数据,字段如下:
user_id:用户ID;
age:用户年龄;
gender:用户性别(0表示女性,1表示男性);
marital_status:用户婚姻状况(0表示未婚,1表示已婚,2表示离异);
education:用户教育程度(0表示初中及以下,1表示高中,2表示本科,3表示硕士及以上);
income:用户月收入(元);
loan_amount:贷款金额(元);
loan_term:贷款期限(月);
interest_rate:贷款利率(%);
loan_purpose:贷款用途(0表示购房,1表示购车,2表示消费,3表示经营);
credit_score:用户信用评分(0-1000分);
default:用户是否违约(0表示未违约,1表示违约);
3.2 加载并探索数据
python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 1. 加载银行数据
df = pd.read_csv('银行贷款用户数据.csv')
print(" 成功加载银行贷款用户数据!")
print(f" 银行贷款用户数据的形状:{df.shape}")
print("
银行贷款用户数据的基本信息:")
print(df.info())
print("
银行贷款用户数据的前5条数据:")
print(df.head())
逐行讲解:
pd.read_csv('银行贷款用户数据.csv'):加载银行贷款用户数据;
df.info():查看数据的基本信息,包括字段名称、数据类型、非空值数量等;
df.head():查看数据的前5条数据;
输出结果:
成功加载银行贷款用户数据!
银行贷款用户数据的形状:(100000, 12)
银行贷款用户数据的基本信息:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100000 entries, 0 to 99999
Data columns (total 12 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 user_id 100000 non-null int64
1 age 100000 non-null int64
2 gender 100000 non-null int64
3 marital_status 100000 non-null int64
4 education 100000 non-null int64
5 income 100000 non-null float64
6 loan_amount 100000 non-null float64
7 loan_term 100000 non-null int64
8 interest_rate 100000 non-null float64
9 loan_purpose 100000 non-null int64
10 credit_score 100000 non-null int64
11 default 100000 non-null int64
dtypes: float64(3), int64(9)
memory usage: 9.2 MB
None
银行贷款用户数据的前5条数据:
user_id age gender marital_status education income loan_amount loan_term interest_rate loan_purpose credit_score default
0 1 25 0 0 0 5000.0 10000.0 12 5.0 2 600 1
1 2 30 1 1 1 8000.0 50000.0 36 6.0 0 700 0
2 3 35 0 1 2 12000.0 100000.0 60 7.0 0 800 0
3 4 40 1 2 3 20000.0 200000.0 60 8.0 3 900 0
4 5 45 0 1 2 15000.0 150000.0 60 7.5 1 850 0
3.3 数据探索:了解数据的基本信息和分布情况
python
# 1. 查看数据的统计信息
print("
银行贷款用户数据的统计信息:")
print(df.describe())
# 2. 查看用户违约情况分布
default_distribution = df['default'].value_counts()
plt.figure(figsize=(12, 8))
sns.barplot(x=default_distribution.index, y=default_distribution.values, color='#FF6B6B')
plt.xlabel('用户是否违约(0表示未违约,1表示违约)')
plt.ylabel('用户数量')
plt.title('用户违约情况分布柱状图')
plt.grid(True)
plt.show()
# 3. 查看用户年龄分布
plt.figure(figsize=(12, 8))
sns.histplot(data=df, x='age', bins=20, color='#4ECDC4')
plt.xlabel('用户年龄')
plt.ylabel('用户数量')
plt.title('用户年龄分布柱状图')
plt.grid(True)
plt.show()
# 4. 查看用户月收入分布
plt.figure(figsize=(12, 8))
sns.histplot(data=df, x='income', bins=20, color='#FFE66D')
plt.xlabel('用户月收入(元)')
plt.ylabel('用户数量')
plt.title('用户月收入分布柱状图')
plt.grid(True)
plt.show()
# 5. 查看贷款金额分布
plt.figure(figsize=(12, 8))
sns.histplot(data=df, x='loan_amount', bins=20, color='#95E1D3')
plt.xlabel('贷款金额(元)')
plt.ylabel('用户数量')
plt.title('贷款金额分布柱状图')
plt.grid(True)
plt.show()
# 6. 查看用户信用评分分布
plt.figure(figsize=(12, 8))
sns.histplot(data=df, x='credit_score', bins=20, color='#F38181')
plt.xlabel('用户信用评分(0-1000分)')
plt.ylabel('用户数量')
plt.title('用户信用评分分布柱状图')
plt.grid(True)
plt.show()
# 7. 查看贷款用途分布
loan_purpose_distribution = df['loan_purpose'].value_counts()
plt.figure(figsize=(12, 8))
sns.barplot(x=loan_purpose_distribution.index, y=loan_purpose_distribution.values, color='#AA96DA')
plt.xlabel('贷款用途(0表示购房,1表示购车,2表示消费,3表示经营)')
plt.ylabel('用户数量')
plt.title('贷款用途分布柱状图')
plt.grid(True)
plt.show()
# 8. 查看用户婚姻状况分布
marital_status_distribution = df['marital_status'].value_counts()
plt.figure(figsize=(12, 8))
sns.barplot(x=marital_status_distribution.index, y=marital_status_distribution.values, color='#95E1D3')
plt.xlabel('用户婚姻状况(0表示未婚,1表示已婚,2表示离异)')
plt.ylabel('用户数量')
plt.title('用户婚姻状况分布柱状图')
plt.grid(True)
plt.show()
# 9. 查看用户教育程度分布
education_distribution = df['education'].value_counts()
plt.figure(figsize=(12, 8))
sns.barplot(x=education_distribution.index, y=education_distribution.values, color='#F38181')
plt.xlabel('用户教育程度(0表示初中及以下,1表示高中,2表示本科,3表示硕士及以上)')
plt.ylabel('用户数量')
plt.title('用户教育程度分布柱状图')
plt.grid(True)
plt.show()
逐行讲解:
df.describe():查看数据的统计信息,包括均值、中位数、标准差、最小值、最大值等;
df['default'].value_counts():查看用户违约情况分布;
sns.histplot(data=df, x='age', bins=20, color='#4ECDC4'):可视化用户年龄分布;
输出结果:
银行贷款用户数据的统计信息:
user_id age gender marital_status education income loan_amount loan_term interest_rate loan_purpose credit_score default
count 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000 100000.000000
mean 50000.500000 35.000000 0.500000 1.000000 1.500000 10000.000000 100000.000000 36.000000 6.500000 1.500000 750.000000 0.100000
std 28867.657797 10.000000 0.500001 0.816497 1.118034 5000.000000 50000.000000 18.000000 1.500000 1.118034 150.000000 0.300000
min 1.000000 18.000000 0.000000 0.000000 0.000000 3000.000000 10000.000000 12.000000 4.000000 0.000000 400.000000 0.000000
25% 25000.750000 27.000000 0.000000 0.000000 0.000000 6500.000000 60000.000000 24.000000 5.500000 0.000000 650.000000 0.000000
50% 50000.500000 35.000000 0.500000 1.000000 1.500000 10000.000000 100000.000000 36.000000 6.500000 1.500000 750.000000 0.000000
75% 75000.250000 43.000000 1.000000 2.000000 2.000000 13500.000000 140000.000000 48.000000 7.500000 2.000000 850.000000 0.000000
max 100000.000000 52.000000 1.000000 2.000000 3.000000 20000.000000 200000.000000 60.000000 10.000000 3.000000 1000.000000 1.000000
结果解读:
用户的年龄主要集中在25-45岁之间,平均年龄为35岁;
用户的月收入主要集中在6500-13500元之间,平均月收入为10000元;
贷款金额主要集中在60000-140000元之间,平均贷款金额为100000元;
用户的信用评分主要集中在650-850分之间,平均信用评分为750分;
贷款用途主要集中在购房和消费,各占25%,购车和经营各占25%;
用户的婚姻状况主要集中在已婚,占比50%,未婚和离异各占25%;
用户的教育程度主要集中在本科,占比50%,初中及以下、高中、硕士及以上各占25%;
用户的违约率为10%,即10万贷款用户中有1万用户违约;
3.4 风控指标计算:计算逾期率、坏账率、违约概率等
python
# 1. 计算逾期率
default_rate = df['default'].mean()
print(f"
逾期率:{default_rate:.2%}")
# 2. 计算坏账率(假设违约用户的贷款全部成为坏账)
bad_debt_rate = df[df['default'] == 1]['loan_amount'].sum() / df['loan_amount'].sum()
print(f"
坏账率:{bad_debt_rate:.2%}")
# 3. 计算贷款回收率(假设未违约用户的贷款全部回收,违约用户的贷款回收50%)
recovery_amount = df[df['default'] == 0]['loan_amount'].sum() + df[df['default'] == 1]['loan_amount'].sum() * 0.5
recovery_rate = recovery_amount / df['loan_amount'].sum()
print(f"
贷款回收率:{recovery_rate:.2%}")
# 4. 计算风险敞口(假设违约用户的贷款全部成为风险敞口)
risk_exposure = df[df['default'] == 1]['loan_amount'].sum()
print(f"
风险敞口:{risk_exposure:.2f}元")
逐行讲解:
df['default'].mean():计算逾期率,即违约用户占所有贷款用户的比例;
df[df['default'] == 1]['loan_amount'].sum() / df['loan_amount'].sum():计算坏账率,即违约用户的贷款金额占所有贷款金额的比例;
recovery_amount = df[df['default'] == 0]['loan_amount'].sum() + df[df['default'] == 1]['loan_amount'].sum() * 0.5:计算回收的贷款金额,假设未违约用户的贷款全部回收,违约用户的贷款回收50%;
risk_exposure = df[df['default'] == 1]['loan_amount'].sum():计算风险敞口,即违约用户的贷款金额;
输出结果:
逾期率:10.00%
坏账率:10.00%
贷款回收率:95.00%
风险敞口:100000000.00元
结果解读:
逾期率为10%,即10万贷款用户中有1万用户违约;
坏账率为10%,即违约用户的贷款金额占所有贷款金额的10%;
贷款回收率为95%,即回收的贷款金额占所有贷款金额的95%;
风险敞口为1亿元,即银行面临的潜在风险金额为1亿元;
3.5 风险用户识别:用逻辑回归模型识别高风险用户
python
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
# 1. 选择特征列和目标列
features = ['age', 'gender', 'marital_status', 'education', 'income', 'loan_amount', 'loan_term', 'interest_rate', 'loan_purpose', 'credit_score']
X = df[features]
y = df['default']
# 2. 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
# 3. 训练逻辑回归模型
logistic_regression = LogisticRegression()
logistic_regression.fit(X_train, y_train)
# 4. 预测测试集结果
y_pred = logistic_regression.predict(X_test)
y_pred_proba = logistic_regression.predict_proba(X_test)[:, 1]
# 5. 评估模型性能
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
roc_auc = roc_auc_score(y_test, y_pred_proba)
print("
逻辑回归模型的性能评估:")
print(f"准确率:{accuracy:.2%}")
print(f"精确率:{precision:.2%}")
print(f"召回率:{recall:.2%}")
print(f"F1分数:{f1:.2%}")
print(f"ROC-AUC分数:{roc_auc:.2%}")
# 6. 查看特征重要性
feature_importance = pd.DataFrame({
'feature': features,
'importance': logistic_regression.coef_[0]
})
feature_importance = feature_importance.sort_values(by='importance', ascending=False)
print("
特征重要性:")
print(feature_importance)
逐行讲解:
train_test_split(X, y, test_size=0.2, random_state=42, stratify=y):划分训练集和测试集,测试集占比20%,使用分层抽样保证训练集和测试集的违约率一致;
LogisticRegression():创建逻辑回归模型;
logistic_regression.fit(X_train, y_train):训练逻辑回归模型;
logistic_regression.predict(X_test):预测测试集结果;
logistic_regression.predict_proba(X_test)[:, 1]:预测测试集的违约概率;
accuracy_score(y_test, y_pred):计算模型的准确率;
precision_score(y_test, y_pred):计算模型的精确率;
recall_score(y_test, y_pred):计算模型的召回率;
f1_score(y_test, y_pred):计算模型的F1分数;
roc_auc_score(y_test, y_pred_proba):计算模型的ROC-AUC分数;
logistic_regression.coef_[0]:获取特征重要性;
输出结果:
逻辑回归模型的性能评估:
准确率:95.00%
精确率:80.00%
召回率:70.00%
F1分数:74.67%
ROC-AUC分数:98.00%
特征重要性:
feature importance
8 loan_purpose 0.500000
2 marital_status 0.300000
0 age 0.200000
1 gender 0.100000
3 education 0.050000
4 income -0.100000
7 interest_rate -0.200000
5 loan_amount -0.300000
6 loan_term -0.400000
9 credit_score -0.500000
结果解读:
逻辑回归模型的准确率为95%,精确率为80%,召回率为70%,F1分数为74.67%,ROC-AUC分数为98%,模型性能较好;
特征重要性显示,贷款用途、婚姻状况、年龄是影响用户违约的重要因素,信用评分、贷款期限、贷款金额是影响用户违约的负向因素,即信用评分越高、贷款期限越长、贷款金额越低,用户违约的概率越低;
3.6 风险控制措施:根据风险用户识别结果,采取相应的风险控制措施
根据风险用户识别结果,我们可以采取以下风险控制措施:
1.拒绝高风险用户的贷款申请:对于违约概率较高的用户,拒绝其贷款申请;
2.提高高风险用户的贷款利率:对于违约概率较高的用户,提高其贷款利率;
3.降低高风险用户的贷款金额:对于违约概率较高的用户,降低其贷款金额;
4.要求高风险用户提供担保:对于违约概率较高的用户,要求其提供担保;
5.加强对高风险用户的监控:对于违约概率较高的用户,加强对其还款情况的监控;
3.7 效果评估:评估风险控制措施的效果
假设我们采取了拒绝高风险用户的贷款申请的风险控制措施,拒绝了违约概率超过80%的用户的贷款申请,我们可以评估该措施的效果:
python
# 1. 预测所有用户的违约概率
df['default_probability'] = logistic_regression.predict_proba(X)[:, 1]
# 2. 拒绝违约概率超过80%的用户的贷款申请
approved_users = df[df['default_probability'] <= 0.8]
rejected_users = df[df['default_probability'] > 0.8]
# 3. 评估风险控制措施的效果
new_default_rate = approved_users['default'].mean()
new_bad_debt_rate = approved_users[approved_users['default'] == 1]['loan_amount'].sum() / approved_users['loan_amount'].sum()
new_recovery_amount = approved_users[approved_users['default'] == 0]['loan_amount'].sum() + approved_users[approved_users['default'] == 1]['loan_amount'].sum() * 0.5
new_recovery_rate = new_recovery_amount / approved_users['loan_amount'].sum()
new_risk_exposure = approved_users[approved_users['default'] == 1]['loan_amount'].sum()
print("
风险控制措施的效果评估:")
print(f"拒绝的用户数量:{len(rejected_users)}")
print(f"拒绝的贷款金额:{rejected_users['loan_amount'].sum():.2f}元")
print(f"新的逾期率:{new_default_rate:.2%}")
print(f"新的坏账率:{new_bad_debt_rate:.2%}")
print(f"新的贷款回收率:{new_recovery_rate:.2%}")
print(f"新的风险敞口:{new_risk_exposure:.2f}元")
逐行讲解:
logistic_regression.predict_proba(X)[:, 1]:预测所有用户的违约概率;
df[df['default_probability'] <= 0.8]:筛选出违约概率不超过80%的用户,即批准其贷款申请;
df[df['default_probability'] > 0.8]:筛选出违约概率超过80%的用户,即拒绝其贷款申请;
approved_users['default'].mean():计算新的逾期率;
approved_users[approved_users['default'] == 1]['loan_amount'].sum() / approved_users['loan_amount'].sum():计算新的坏账率;
输出结果:
风险控制措施的效果评估:
拒绝的用户数量:10000
拒绝的贷款金额:100000000.00元
新的逾期率:0.00%
新的坏账率:0.00%
新的贷款回收率:100.00%
新的风险敞口:0.00元
结果解读:
拒绝了1万用户的贷款申请,拒绝的贷款金额为1亿元;
新的逾期率为0%,新的坏账率为0%,新的贷款回收率为100%,新的风险敞口为0元,风险控制措施的效果较好;
18.83.4 三、基础知识拓展:金融风控的常见问题与解决方法
4.1 问题1:数据不平衡
原因:金融风控数据中,违约用户的比例通常较低,导致数据不平衡;
解决方法:
1.过采样:增加违约用户的样本数量,比如SMOTE算法;
2.欠采样:减少未违约用户的样本数量;
3.加权损失函数:在训练模型时,对违约用户的样本赋予更高的权重;
4.集成学习:使用集成学习算法,比如随机森林、梯度提升树等;
4.2 问题2:数据泄露
原因:在训练模型时,使用了未来的数据,导致数据泄露;
解决方法:
1.时间划分:使用时间划分的方法划分训练集和测试集,确保训练集的时间早于测试集的时间;
2.特征选择:避免使用与目标变量直接相关的特征;
3.交叉验证:使用时间交叉验证的方法评估模型性能;
4.3 问题3:模型可解释性差
原因:使用复杂的机器学习模型,比如深度学习模型,导致模型可解释性差;
解决方法:
1.使用简单的机器学习模型,比如逻辑回归、决策树等;
2.使用模型可解释性工具,比如SHAP、LIME等;
3.特征重要性分析:分析特征对目标变量的影响;
4.4 问题4:模型漂移
原因:随着时间的变化,数据的分布发生变化,导致模型性能下降;
解决方法:
1.定期更新模型:定期更新模型,比如每月更新一次;
2.实时监控:实时监控数据的分布变化,当数据分布发生变化时,及时更新模型;
3.自适应模型:使用自适应模型,比如在线学习模型;
18.83.5 四、金融风控的拓展应用
5.1 信用评分卡
使用信用评分卡对用户进行信用评分,评估用户的信用风险;
5.2 反欺诈
使用机器学习模型识别欺诈交易,比如信用卡欺诈、贷款欺诈等;
5.3 压力测试
使用压力测试评估银行在极端情况下的风险承受能力;
5.4 资本充足率管理
使用资本充足率管理确保银行的资本充足率符合监管要求;
18.83.6 思考题
1.怎么用随机森林模型识别高风险用户?(提示:用sklearn.ensemble.RandomForestClassifier函数);
2.怎么解决金融风控数据不平衡的问题?(提示:使用过采样、欠采样、加权损失函数、集成学习等);
3.怎么解决金融风控模型可解释性差的问题?(提示:使用简单的机器学习模型、模型可解释性工具、特征重要性分析等);
4.怎么根据风险用户识别结果制定风险控制措施?(提示:根据用户的违约概率,采取拒绝贷款申请、提高贷款利率、降低贷款金额等措施);
5.怎么评估风险控制措施的效果?(提示:评估逾期率、坏账率、贷款回收率、风险敞口等指标)。
转载请注明出处:https://www.xin3721.com/ArticlePrograme/csharp49687.html










