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

【竞赛系列】机器学习实操项目04——客户信用评估模型开发全流程(baseline)

上一章:机器学习实操项目03——Scikit-learn介绍及简单分类案例
下一章:
机器学习核心知识点目录:机器学习核心知识点目录
机器学习实战项目目录:【从 0 到 1 落地】机器学习实操项目目录:覆盖入门到进阶,大学生就业 / 竞赛必备

文章目录

  • 客户信用评估模型开发全流程
    • 任务总览
    • 1. 数据加载与预处理
    • 2. 划分训练集和验证集
    • 3. 特征预处理
    • 4. 模型训练与评估
    • 5. 最佳模型选择与评估
    • 6. 混淆矩阵分析
    • 7. 业务解读
    • 8. 测试集预测与提交
    • 总结
  • 完整代码及中间结果

客户信用评估模型开发全流程

任务总览

本项目旨在开发一个客户信用评估模型,通过分析客户的基本信息、账户特征等数据,预测客户是否为"好客户"(Target=1)或"坏客户"(Target=0)。这一模型可帮助金融机构在信贷审批过程中做出更合理的决策,平衡风险控制与业务发展。

整个流程包括:数据加载与预处理、数据集划分、特征工程、模型训练与评估、模型选择与解读、以及最终预测等关键步骤。

通过网盘分享的文件:用户信用评分数据集
链接: https://pan.baidu.com/s/1F2R0rOLuw4_ntaKMPL8otg?pwd=1x27 提取码: 1x27

1. 数据加载与预处理

功能说明
这一步骤的主要目的是加载原始数据并进行初步处理,为后续建模做准备。包括处理缺失值、分离特征与目标变量等。

# 读取训练数据和测试数据
train = pd.read_csv('train.csv')  # 加载训练数据集(包含目标变量)
test = pd.read_csv('test.csv')    # 加载测试数据集(不包含目标变量,用于最终预测)

pd.read_csv():pandas库的函数,用于从CSV文件中读取数据并转换为DataFrame格式,方便后续的数据处理和分析。

# 处理缺失值 - 只对分类特征进行简单填充
# 将Credit_Product列的缺失值填充为'Unknown'
train['Credit_Product'] = train['Credit_Product'].fillna('Unknown')
test['Credit_Product'] = test['Credit_Product'].fillna('Unknown')

fillna():pandas的DataFrame方法,用于填充缺失值。这里将缺失的信用产品信息标记为’Unknown’,而不是简单删除,以保留更多数据信息。

# 分离特征和目标变量
X = train.drop(['ID', 'Target'], axis=1)  # 特征数据:删除ID(无预测价值)和Target(目标变量)
y = train['Target']  # 目标变量:客户是否为好客户(1表示好客户,0表示坏客户)

drop():pandas的DataFrame方法,用于删除指定列(axis=1表示删除列)。这里移除ID列(仅作为标识)和Target列(需要预测的目标)。

2. 划分训练集和验证集

功能说明
将训练数据进一步划分为训练集(用于模型训练)和验证集(用于模型评估),避免模型过拟合并客观评估模型性能。

X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2,   # 验证集比例20%stratify=y,      # 按目标变量分层抽样random_state=42  # 设置随机种子确保结果可复现
)

train_test_split():sklearn库的函数,用于将数据集随机划分为训练集和验证集。

  • test_size=0.2:指定验证集占总数据的20%
  • stratify=y:按目标变量y的分布进行分层抽样,确保训练集和验证集中目标变量的比例一致
  • random_state=42:设置随机种子,保证每次运行代码得到相同的划分结果,便于结果复现

3. 特征预处理

功能说明
对不同类型的特征进行预处理,使特征满足模型输入要求,同时提升模型性能。主要包括对分类特征进行独热编码,对数值特征进行标准化。

# 定义分类特征和数值特征
cat_cols = ['Gender', 'Region_Code', 'Occupation', 'Channel_Code', 'Credit_Product', 'Is_Active']
num_cols = ['Age', 'Vintage', 'Avg_Account_Balance']

特征分为两类:

  • 分类特征(cat_cols):非数值型特征,如性别、职业等
  • 数值特征(num_cols):可直接进行数值计算的特征,如年龄、账户余额等
# 对分类变量进行独热编码
encoder = OneHotEncoder(handle_unknown='ignore')  # 创建独热编码器
X_train_encoded = encoder.fit_transform(X_train[cat_cols])  # 拟合并转换训练集
X_val_encoded = encoder.transform(X_val[cat_cols])  # 转换验证集
X_test_encoded = encoder.transform(test[cat_cols])  # 转换测试集

OneHotEncoder():sklearn的预处理类,用于将分类特征转换为独热编码形式。

  • handle_unknown=‘ignore’:遇到训练集中未出现的类别时忽略,避免错误
  • fit_transform():先根据训练数据拟合编码器(学习类别信息),再进行转换
  • transform():使用已拟合的编码器对新数据(验证集/测试集)进行转换,保证编码方式一致
# 数值特征标准化(Z-score标准化)
scaler = StandardScaler()  # 创建标准化器
X_train_num = scaler.fit_transform(X_train[num_cols])  # 拟合并转换训练集
X_val_num = scaler.transform(X_val[num_cols])  # 转换验证集
X_test_num = scaler.transform(test[num_cols])  # 转换测试集

StandardScaler():sklearn的预处理类,用于对数值特征进行标准化(Z-score转换),使特征均值为0,标准差为1。

  • 标准化可以消除不同特征间的量纲影响,使模型更易收敛
# 合并处理后的特征
X_train_final = np.hstack([X_train_num, X_train_encoded.toarray()])
X_val_final = np.hstack([X_val_num, X_val_encoded.toarray()])
X_test_final = np.hstack([X_test_num, X_test_encoded.toarray()])

np.hstack():numpy库的函数,用于水平堆叠数组。这里将处理后的数值特征和编码后的分类特征合并,形成最终的特征矩阵。

4. 模型训练与评估

功能说明
训练多种分类模型,并使用验证集评估模型性能,选择最优模型。采用AUC(ROC曲线下面积)作为主要评估指标,适用于二分类问题且对不平衡数据较为稳健。

# 定义要比较的模型
models = [("Logistic Regression", LogisticRegression(max_iter=1000, random_state=42)),("Decision Tree", DecisionTreeClassifier(max_depth=5, random_state=42)),("Random Forest", RandomForestClassifier(n_estimators=100, random_state=42)),("KNN", KNeighborsClassifier(n_neighbors=30)),("Naive Bayes", GaussianNB())
]

选择了5种常见的分类算法进行比较:

  • 逻辑回归:线性模型,可解释性强
  • 决策树:非线性模型,可捕捉特征间的交互关系
  • 随机森林:集成模型,通常性能更优
  • K近邻:基于实例的学习,简单直观
  • 朴素贝叶斯:基于概率的简单模型
# 评估每个模型
for name, model in models:model.fit(X_train_final, y_train)  # 训练模型# 获取预测概率if hasattr(model, "predict_proba"):val_proba = model.predict_proba(X_val_final)[:, 1]  # 预测为1的概率else:val_proba = model.decision_function(X_val_final)val_proba = (val_proba - val_proba.min()) / (val_proba.max() - val_proba.min())  # 归一化val_auc = roc_auc_score(y_val, val_proba)  # 计算AUCprint(f"{name}: AUC = {val_auc:.4f}")

model.fit():模型训练方法,根据输入的特征矩阵和目标变量学习模型参数。

predict_proba():多数分类模型提供的方法,返回每个样本属于各个类别的概率。[:, 1]表示取样本属于类别1(好客户)的概率。

roc_auc_score():计算ROC曲线下面积(AUC)的函数。AUC取值范围为0-1,越接近1表示模型区分正负样本的能力越强。

5. 最佳模型选择与评估

功能说明
基于验证集的AUC值选择性能最优的模型,并进行更详细的评估,包括分类报告和混淆矩阵分析。

# 选择最佳模型
best_model_name, best_auc, best_model = max(results, key=lambda x: x[1])

通过比较各模型的AUC值,选择性能最优的模型(此处为决策树,AUC=0.8595)。

# 详细评估最佳模型
val_pred = best_model.predict(X_val_final)  # 预测类别
print(classification_report(y_val, val_pred))  # 生成分类报告

predict():模型预测方法,返回样本的预测类别(0或1)。

classification_report():生成包含精确率(precision)、召回率(recall)、F1分数等指标的分类报告:

  • 精确率:预测为正的样本中实际为正的比例
  • 召回率:实际为正的样本中被正确预测的比例
  • F1分数:精确率和召回率的调和平均

6. 混淆矩阵分析

功能说明
通过混淆矩阵更直观地分析模型的预测结果,了解模型在不同类别上的表现。

cm = confusion_matrix(y_val, val_pred)
tn, fp, fn, tp = cm.ravel()

confusion_matrix():计算混淆矩阵的函数,矩阵元素含义:

  • TP(True Positive):真正例,实际为好客户且被正确预测
  • FP(False Positive):假正例,实际为坏客户但被错误预测为好客户
  • FN(False Negative):假反例,实际为好客户但被错误预测为坏客户
  • TN(True Negative):真反例,实际为坏客户且被正确预测

7. 业务解读

功能说明
将模型的技术指标转化为业务指标,从业务角度解读模型表现,评估模型对实际业务的影响。

accuracy = (tp + tn) / (tp + tn + fp + fn)  # 总体准确率
good_recall = tp / (tp + fn)  # 好客户识别率(召回率)
bad_recall = tn / (tn + fp)   # 坏客户识别率

从业务角度看:

  • 假阳性(FP):将坏客户误判为好客户,可能导致坏账损失
  • 假阴性(FN):将好客户误判为坏客户,会损失潜在收益
  • 模型需要在两者之间找到平衡,根据业务策略调整阈值

8. 测试集预测与提交

功能说明
使用最佳模型对测试集进行预测,生成符合要求的提交文件,用于模型部署或竞赛提交。

# 测试集预测
test_proba = best_model.predict_proba(X_test_final)[:, 1]# 生成提交文件
submission = pd.DataFrame({'ID': test['ID'],'Target': test_proba
})
submission.to_csv('submission.csv', index=False)

生成包含客户ID和对应好客户概率的提交文件,概率值可用于业务决策(如设定阈值来确定是否批准信贷)。

总结

本项目通过完整的机器学习流程,从数据预处理到模型评估,最终构建了一个客户信用评估模型。决策树模型在本数据集上表现最佳,AUC达到0.8595,能够较好地区分好客户和坏客户。模型的业务解读帮助将技术结果转化为实际业务价值,为信贷决策提供数据支持。

完整代码及中间结果

# 导入必要的数据处理和机器学习库
import pandas as pd  # 用于数据处理和分析
import numpy as np   # 用于数值计算
import matplotlib.pyplot as plt  # 用于数据可视化
from sklearn.model_selection import train_test_split  # 用于划分训练集和验证集
from sklearn.preprocessing import StandardScaler, OneHotEncoder  # 用于特征预处理
from sklearn.metrics import roc_auc_score, confusion_matrix, classification_report  # 用于模型评估
# 1. 数据加载与预处理
# 读取训练数据和测试数据
train = pd.read_csv('train.csv')  # 加载训练数据集
test = pd.read_csv('test.csv')    # 加载测试数据集# 处理缺失值 - 只对分类特征进行简单填充
# 将Credit_Product列的缺失值填充为'Unknown'
train['Credit_Product'] = train['Credit_Product'].fillna('Unknown')
test['Credit_Product'] = test['Credit_Product'].fillna('Unknown')# 分离特征和目标变量
# 训练数据中删除ID列和Target列作为特征
X = train.drop(['ID', 'Target'], axis=1)
# 提取目标变量(客户是否为好客户)
y = train['Target']
# 2. 划分训练集和验证集
# 将数据分为训练集和验证集,验证集占20%
# 使用分层抽样确保训练集和验证集的目标变量分布一致
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2,   # 验证集比例20%stratify=y,      # 按目标变量分层抽样random_state=42  # 设置随机种子确保结果可复现
)
print(X)

输出结果:

GenderAgeRegion_CodeOccupationChannel_CodeVintageCredit_ProductAvg_Account_BalanceIs_Active
0Male58RG264Self_EmployedX219No552449Yes
1Female45RG271Self_EmployedX3104Yes525206No
2Female30RG278OtherX125No724718No
3Female52RG283Self_EmployedX143Yes1452453No
4Female76RG254OtherX157No1895762No
..............................
195720Female39RG279Self_EmployedX219Unknown1595992No
195721Female46RG283Self_EmployedX227Yes1220029No
195722Male68RG268OtherX3104Yes1789781No
195723Male30RG277Self_EmployedX215No722822Yes
195724Female60RG268Self_EmployedX398Yes1837992Yes

195725 rows × 9 columns

# 3. 特征预处理
# 定义分类特征和数值特征
# 分类特征列表
cat_cols = ['Gender', 'Region_Code', 'Occupation', 'Channel_Code', 'Credit_Product', 'Is_Active']
# 数值特征列表
num_cols = ['Age', 'Vintage', 'Avg_Account_Balance']# 对分类变量进行独热编码
# 创建独热编码器,忽略未知类别
encoder = OneHotEncoder(handle_unknown='ignore')
# 在训练集上拟合并转换分类特征
X_train_encoded = encoder.fit_transform(X_train[cat_cols])
# 在验证集上转换分类特征(使用训练集拟合的编码器)
X_val_encoded = encoder.transform(X_val[cat_cols])
# 在测试集上转换分类特征
X_test_encoded = encoder.transform(test[cat_cols])# 数值特征标准化(Z-score标准化)
# 创建标准化器
scaler = StandardScaler()
# 在训练集上拟合并转换数值特征
X_train_num = scaler.fit_transform(X_train[num_cols])
# 在验证集上转换数值特征(使用训练集拟合的标准化器)
X_val_num = scaler.transform(X_val[num_cols])
# 在测试集上转换数值特征
X_test_num = scaler.transform(test[num_cols])# 合并处理后的特征
# 水平堆叠数值特征和编码后的分类特征
X_train_final = np.hstack([X_train_num, X_train_encoded.toarray()])
X_val_final = np.hstack([X_val_num, X_val_encoded.toarray()])
X_test_final = np.hstack([X_test_num, X_test_encoded.toarray()])
# 打印形状检查
print(f"训练集形状: {X_train_final.shape}")
print(f"验证集形状: {X_val_final.shape}")
print(f"测试集形状: {X_test_final.shape}")

输出结果:

训练集形状: (156580, 53)
验证集形状: (39145, 53)
测试集形状: (50000, 53)
# 4. 模型训练与评估
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB# 定义要比较的模型
models = [("Logistic Regression", LogisticRegression(max_iter=1000, random_state=42)),("Decision Tree", DecisionTreeClassifier(max_depth=5, random_state=42)),("Random Forest", RandomForestClassifier(n_estimators=100, random_state=42)),("KNN", KNeighborsClassifier(n_neighbors=30)),("Naive Bayes", GaussianNB())
]# 评估每个模型
results = []
for name, model in models:# 训练模型model.fit(X_train_final, y_train)# 在验证集上预测概率# 对于不支持predict_proba的模型,使用decision_functionif hasattr(model, "predict_proba"):val_proba = model.predict_proba(X_val_final)[:, 1]else:# 对于SVM等模型,使用decision_functionval_proba = model.decision_function(X_val_final)# 将决策函数值缩放到0-1范围val_proba = (val_proba - val_proba.min()) / (val_proba.max() - val_proba.min())# 计算AUCval_auc = roc_auc_score(y_val, val_proba)# 保存结果results.append((name, val_auc, model))print(f"{name}: AUC = {val_auc:.4f}")

输出结果:

Logistic Regression: AUC = 0.8540
Decision Tree: AUC = 0.8595
Random Forest: AUC = 0.8477
KNN: AUC = 0.8509
Naive Bayes: AUC = 0.7988
# 5. 选择最佳模型
best_model_name, best_auc, best_model = max(results, key=lambda x: x[1])
print(f"\n最佳模型: {best_model_name}, AUC: {best_auc:.4f}")# 在验证集上详细评估最佳模型
val_pred = best_model.predict(X_val_final)# 对于支持概率预测的模型,获取概率
if hasattr(best_model, "predict_proba"):val_proba = best_model.predict_proba(X_val_final)[:, 1]
else:val_proba = best_model.decision_function(X_val_final)val_proba = (val_proba - val_proba.min()) / (val_proba.max() - val_proba.min())print("\n分类报告:")
print(classification_report(y_val, val_pred))

输出结果:

最佳模型: Decision Tree, AUC: 0.8595分类报告:precision    recall  f1-score   support0       0.85      0.98      0.91     298401       0.85      0.47      0.60      9305accuracy                           0.85     39145macro avg       0.85      0.72      0.76     39145
weighted avg       0.85      0.85      0.84     39145
# 6. 混淆矩阵分析
cm = confusion_matrix(y_val, val_pred)
tn, fp, fn, tp = cm.ravel()print("\n混淆矩阵:")
print(f"真正例(TP): {tp} - 实际好客户被正确识别为好客户")
print(f"假正例(FP): {fp} - 实际坏客户被错误识别为好客户")
print(f"假反例(FN): {fn} - 实际好客户被错误识别为坏客户")
print(f"真反例(TN): {tn} - 实际坏客户被正确识别为坏客户")

输出结果:

混淆矩阵:
真正例(TP): 4328 - 实际好客户被正确识别为好客户
假正例(FP): 737 - 实际坏客户被错误识别为好客户
假反例(FN): 4977 - 实际好客户被错误识别为坏客户
真反例(TN): 29103 - 实际坏客户被正确识别为坏客户
confusion_matrix(y_val, val_pred)

输出结果:

array([[29103,   737],[ 4977,  4328]], dtype=int64)
# 7. 业务解读
accuracy = (tp + tn) / (tp + tn + fp + fn)
good_recall = tp / (tp + fn)
bad_recall = tn / (tn + fp)print("\n业务解读:")
print(f"- 假阳性(FP): {fp} 个实际坏客户被错误分类为好客户,可能导致坏账损失")
print(f"- 假阴性(FN): {fn} 个实际好客户被错误分类为坏客户,损失潜在收益")
print(f"- 模型准确率: {accuracy:.2%}")
print(f"- 好客户识别率: {good_recall:.2%} (正确识别好客户的能力)")
print(f"- 坏客户识别率: {bad_recall:.2%} (正确识别坏客户的能力)")

输出结果:

业务解读:
- 假阳性(FP): 737 个实际坏客户被错误分类为好客户,可能导致坏账损失
- 假阴性(FN): 4977 个实际好客户被错误分类为坏客户,损失潜在收益
- 模型准确率: 85.40%
- 好客户识别率: 46.51% (正确识别好客户的能力)
- 坏客户识别率: 97.53% (正确识别坏客户的能力)
# 8. 测试集预测与提交
# 在测试集上预测
if hasattr(best_model, "predict_proba"):test_proba = best_model.predict_proba(X_test_final)[:, 1]
else:test_proba = best_model.decision_function(X_test_final)test_proba = (test_proba - test_proba.min()) / (test_proba.max() - test_proba.min())# 生成提交文件
submission = pd.DataFrame({'ID': test['ID'],'Target': test_proba
})
# submission.to_csv('submission.csv', index=False)
print("\n提交文件已生成: submission.csv")

输出结果:

提交文件已生成: submission.csv

上一章:机器学习实操项目03——Scikit-learn介绍及简单分类案例
下一章:
机器学习核心知识点目录:机器学习核心知识点目录
机器学习实战项目目录:【从 0 到 1 落地】机器学习实操项目目录:覆盖入门到进阶,大学生就业 / 竞赛必备


文章转载自:

http://M2FCPM1g.kbdzh.cn
http://VfaHoMRL.kbdzh.cn
http://9MtPqkfy.kbdzh.cn
http://9daRfvz9.kbdzh.cn
http://Tq9jECTv.kbdzh.cn
http://CD1suzYO.kbdzh.cn
http://59yf6bo7.kbdzh.cn
http://5VKWIlNe.kbdzh.cn
http://NEdPTe5k.kbdzh.cn
http://8L0AJCYT.kbdzh.cn
http://QlqG8fIa.kbdzh.cn
http://rSWNqYgL.kbdzh.cn
http://W4z6z77c.kbdzh.cn
http://Xad66U61.kbdzh.cn
http://M21JSA7u.kbdzh.cn
http://3zl0QaIC.kbdzh.cn
http://P5XLSGVX.kbdzh.cn
http://Y45NhTZw.kbdzh.cn
http://dRA1j4Mw.kbdzh.cn
http://3t5lMMV6.kbdzh.cn
http://fYj1oNid.kbdzh.cn
http://50bYrmAQ.kbdzh.cn
http://9iAafCop.kbdzh.cn
http://nyiFjzH3.kbdzh.cn
http://TQTY1gH3.kbdzh.cn
http://EpTnKu3K.kbdzh.cn
http://b4tMslwH.kbdzh.cn
http://fAfNRXyj.kbdzh.cn
http://9oxxNkLc.kbdzh.cn
http://6msHjiSE.kbdzh.cn
http://www.dtcms.com/a/377030.html

相关文章:

  • 爆破mysql登录密码
  • PG-210-HI 山洪预警系统呼叫端:筑牢山区应急预警 “安全防线”
  • 工业 CT 检测服务公司转型:扫描图像 AI 重构系统与客户检测需求智能匹配中台
  • 【CVPR2021】《Unbiased mean teacher for cross-domain object detection》译读笔记
  • AI时代技术面试重构:谷歌如何用Vibe Coding与抗作弊革命重塑招聘
  • 【Python/Pytorch】-- 贝叶斯定理
  • .NET Framework 和 .NET 的核心差异
  • Spring组件注解详解:@Component、@Service、@Repository、@Controller
  • STM32初始化串口重定向后printf调试信息不输出的问题
  • Monorepo 全面解析:优势、挑战与适用场景
  • 领码方案|Linux 下 PLT → PDF 转换服务超级完整版:异步、权限、进度(一气呵成)
  • TCP内网穿透:将局域网内部的TCP/HTTP服务暴露在公网上
  • day40 SQLite3单词查询程序设计与实现
  • 华为FreeBuds 7i其他手机能用空间音频吗?如何开启?
  • Java — Lambda 表达式与函数式接口解析
  • Apache Commons Math3 使用指南:强大的Java数学库
  • 数据结构中的 二叉树
  • SoC分区
  • 先买实现烦过
  • Qt C++ 图形绘制完全指南:从基础到进阶实战
  • 我在嘉顺达蓝海的安全坚守
  • fastadmin安装后后台提示putenv()报错,不显示验证码
  • macOS苹果电脑运行向日葵远程控制软件闪退
  • 平衡车 -- 倒立摆
  • 利用OpenCV实现模板与多个对象匹配
  • 机器学习的发展与应用:从理论到现实
  • 软考系统架构设计师之软件系统建模
  • leedcode 算法刷题第三十一天
  • IDEA下载安装图文教程(非常详细,适合新手)
  • Spark 性能优化全攻略:内存管理、shuffle 优化与参数调优