AI 伦理实验:Python 实现信用评分模型 + SHAP/LIME 可解释性分析全流程
前言
在金融风控领域,AI 信用评分模型早已成为核心工具,但模型黑箱问题和算法歧视风险一直是 AI 伦理关注的焦点。单纯追求模型准确率远远不够,能清晰解释模型决策、保障模型公平性,才是符合行业规范与伦理要求的关键。
本篇教程基于 UCI 经典德国信用数据集,从零搭建虚拟环境,完成数据预处理、模型训练、性能评估,再用 SHAP 做全局可解释性分析、LIME 做单样本决策解释,最后开展 AI 公平性伦理检测,全程代码可直接运行,适配课程实验、毕业设计、技术分享,新手也能轻松复现!
教程关键词
AI 伦理、信用评分模型、可解释性 AI、SHAP、LIME、Python 机器学习、金融风控
一、实验环境搭建
1. 虚拟环境创建与激活
推荐使用 Anaconda 创建独立虚拟环境,避免依赖冲突,打开 Anaconda Prompt(以管理员身份运行) 执行以下命令:
# 创建名为ai_ethics的虚拟环境,指定Python3.10稳定版本
conda create -n ai_ethics python=3.10 -y
# 激活虚拟环境
conda activate ai_ethics
2. 核心依赖库安装
本实验需要数据处理、机器学习、可视化、可解释性分析相关库,一键安装:
pip install numpy pandas matplotlib seaborn scikit-learn shap lime ipykernel imbalanced-learn
3. Jupyter Notebook 内核绑定
为了让 Jupyter Notebook 能调用ai_ethics虚拟环境,需要将环境注册为 Jupyter 内核。操作步骤:
- 确保已激活
ai_ethics环境(命令行前缀显示(ai_ethics)) - 执行以下命令创建项目目录并注册内核:
# 创建项目目录 mkdir D:\AI_Ethics_Lab # 进入项目目录 cd /d D:\AI_Ethics_Lab # 注册Jupyter内核 python -m ipykernel install --user --name ai_ethics --display-name "Python (ai_ethics)" 执行成功后,打开 Jupyter Notebook,即可在「Kernel → Change kernel」中选择
Python (ai_ethics),使用该虚拟环境运行代码。jupyter notebook
复制终端运行后出现的链接到浏览器打开即可使用jupyter notebook
二、数据集介绍
本次使用的德国信用数据集(Statlog German Credit Data) 是金融风控与 AI 伦理研究的经典基准数据集,包含1000 条用户样本、20 个特征 + 1 个标签:
- 特征维度:涵盖用户账户状态、贷款期限、信用历史、贷款金额、年龄、职业、婚姻状况等财务与个人信息
- 标签含义:原始标签 1 = 好信用(用户可正常还款),2 = 坏信用(用户存在违约风险)
- 数据集特点:类别不平衡(好信用 700 条,坏信用 300 条),包含年龄、性别等敏感特征,适合做公平性检测
下载德国数据集:
import pathlib, urllib.request
folder = pathlib.Path("D:/AI_Ethics_Lab")
folder.mkdir(parents=True, exist_ok=True)
urls = {
"german.data": "https://archive.ics.uci.edu/ml/machine-learning-databases/statlog/german/german.data",
"german.doc": "https://archive.ics.uci.edu/ml/machine-learning-databases/statlog/german/german.doc"
}
for name, url in urls.items():
out = folder / name
urllib.request.urlretrieve(url, out)
print("已下载:", out)
# 3. 加载并查看数据集
import pandas as pd
df = pd.read_csv("D:/AI_Ethics_Lab/german.data", sep=" ", header=None)
print(df.shape) # 正常应输出 (1000, 21)
df.head()
三、实验全流程代码实现
Cell1 库导入与路径配置
首先导入所有需要的库,配置数据路径与结果输出目录,解决中文可视化乱码问题:
# 【Cell1】导入依赖库+基础配置
import os
import warnings
warnings.filterwarnings("ignore") # 屏蔽无关警告,让输出更整洁
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 机器学习相关
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import (classification_report, confusion_matrix,
ConfusionMatrixDisplay, balanced_accuracy_score, roc_auc_score)
# 可解释性AI库
import shap
from lime.lime_tabular import LimeTabularExplainer
from IPython.display import display
# 解决Matplotlib中文乱码+负号显示异常
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 定义数据路径与结果输出目录,自动创建目录避免报错
data_path = os.path.join(os.getcwd(), "german.data")
out_dir = os.path.join(os.getcwd(), "module1_outputs")
os.makedirs(out_dir, exist_ok=True)
print("数据集路径:", data_path)
print("结果输出目录:", out_dir)
Cell2 数据加载与字段命名
原始数据无表头,需手动添加语义化字段名,方便后续数据处理与分析:
# 【Cell2】加载数据+定义字段名
column_names = [
"账户状态", "贷款期限", "信用历史", "贷款用途", "贷款金额", "储蓄账户",
"就业时长", "分期付款率", "个人状态(性别/婚姻)", "其他债务人",
"居住时长", "资产情况", "年龄", "其他分期付款计划", "住房情况",
"现有信贷数", "工作类型", "抚养人数", "电话状态", "外籍工人", "信用标签"
]
# 读取数据,适配原始数据的多空格分隔格式
df = pd.read_csv(data_path, sep=r"\s+", header=None, names=column_names)
# 查看数据维度与前5行,验证加载结果
print("数据集维度:", df.shape)
display(df.head())
运行结果:数据集维度为(1000, 21),说明数据加载成功。
Cell3 标签转换
原始标签为 1/2,不符合机器学习 0/1 的标准格式,进行转换:
# 【Cell3】标签转换:好信用=1,坏信用=0
df["信用标签"] = df["信用标签"].map({1: 1, 2: 0})
# 查看转换后标签分布
print("转换后标签分布:")
print(df["信用标签"].value_counts())
运行结果:1(好信用)700 条,0(坏信用)300 条,与数据集原始分布一致。
Cell4 训练集与测试集划分
采用分层抽样划分,保证训练集和测试集的正负样本比例与原数据一致,避免类别分布偏差:
# 【Cell4】划分特征与标签,拆分训练集、测试集
X_raw = df.drop(columns=["信用标签"]) # 特征集:剔除标签列
y = df["信用标签"] # 标签集
# 80%训练集,20%测试集,stratify=y实现分层抽样
X_train_raw, X_test_raw, y_train, y_test = train_test_split(
X_raw, y, test_size=0.2, random_state=42, stratify=y
)
print("训练集特征维度:", X_train_raw.shape)
print("测试集特征维度:", X_test_raw.shape)
运行结果:训练集(800, 20),测试集(200, 20),划分完成。
Cell5 特征编码与对齐
数据中包含大量分类型特征,需进行 One-Hot 编码,同时保证训练集和测试集特征列完全一致:
# 【Cell5】One-Hot编码+训练集测试集特征对齐
# 对分类特征进行独热编码
X_train = pd.get_dummies(X_train_raw, drop_first=False)
X_test = pd.get_dummies(X_test_raw, drop_first=False)
# 核心步骤:特征对齐,测试集缺失的列补0,保证特征维度一致
X_train, X_test = X_train.align(X_test, join="left", axis=1, fill_value=0)
# 转换为浮点型,适配模型输入
X_train = X_train.astype(float)
X_test = X_test.astype(float)
print("编码后训练集维度:", X_train.shape)
print("编码后测试集维度:", X_test.shape)
运行结果:编码后特征维度扩展为(800, 61)、(200, 61),编码与对齐完成。
Cell6 随机森林模型训练
选择随机森林分类器,兼顾模型预测性能与可解释性,同时处理类别不平衡问题:
# 【Cell6】随机森林模型训练
# 初始化模型,class_weight="balanced"适配类别不平衡
model = RandomForestClassifier(n_estimators=100, random_state=42, class_weight="balanced")
# 模型训练
model.fit(X_train, y_train)
# 测试集预测
y_pred = model.predict(X_test)
y_pred_proba = model.predict_proba(X_test)[:, 1] # 坏信用预测概率
Cell7 模型性能评估
从分类报告、平衡准确率、AUC、混淆矩阵多维度评估模型效果:
# 【Cell7】模型评估指标计算与可视化
print("="*50)
print("模型分类报告:")
print(classification_report(y_test, y_pred, target_names=["好信用", "坏信用"]))
print("="*50)
print(f"平衡准确率:{balanced_accuracy_score(y_test, y_pred):.4f}")
print(f"AUC分值:{roc_auc_score(y_test, y_pred_proba):.4f}")
print("="*50)
# 混淆矩阵可视化
cm = confusion_matrix(y_test, y_pred)
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=["好信用", "坏信用"])
disp.plot(cmap=plt.cm.Blues)
plt.title("信用评分模型混淆矩阵")
plt.savefig(os.path.join(out_dir, "混淆矩阵.png"), dpi=300, bbox_inches="tight")
plt.show()
Cell8 SHAP 全局可解释性分析
SHAP(SHapley Additive exPlanations)基于博弈论,计算每个特征对模型决策的贡献度,全局解释模型的核心影响因素:
# 【Cell8】SHAP全局可解释性分析
# 针对树模型的SHAP解释器
explainer = shap.TreeExplainer(model)
# 计算测试集SHAP值
shap_values = explainer.shap_values(X_test)
# 二分类任务,取坏信用(1)的SHAP值
shap_pos = shap_values[:, :, 1]
# 1. SHAP特征重要性柱状图
plt.figure(figsize=(12, 8))
shap.summary_plot(shap_pos, X_test, plot_type="bar", show=False)
plt.title("SHAP特征重要性排序")
plt.tight_layout()
plt.savefig(os.path.join(out_dir, "SHAP特征重要性.png"), dpi=300, bbox_inches="tight")
plt.show()
# 2. SHAP特征贡献度摘要图
plt.figure(figsize=(12, 8))
shap.summary_plot(shap_pos, X_test, show=False)
plt.title("SHAP特征贡献度摘要")
plt.tight_layout()
plt.savefig(os.path.join(out_dir, "SHAP特征贡献度.png"), dpi=300, bbox_inches="tight")
plt.show()
结果解读:贷款金额、账户状态、贷款期限是影响模型决策的核心特征,贷款金额越高,用户被判为坏信用的概率越大。
Cell9 LIME 局部可解释性分析
LIME 专注单样本局部解释,直观展示单个用户被判定为坏信用 / 好信用的具体原因,解决 “为什么该用户被拒贷” 的问题:
# 【Cell9】LIME单样本决策解释
# 初始化LIME解释器
lime_explainer = LimeTabularExplainer(
training_data=X_train.values,
feature_names=X_train.columns.tolist(),
class_names=["好信用", "坏信用"],
mode="classification",
random_state=42
)
# 选取测试集第0个样本进行解释
idx = 0
exp = lime_explainer.explain_instance(
X_test.iloc[idx].values, model.predict_proba, num_features=6
)
# 输出样本真实标签与预测概率
print(f"样本{idx}真实标签:{y_test.iloc[idx]}(0=好信用,1=坏信用)")
print(f"模型预测概率:好信用{model.predict_proba([X_test.iloc[idx]])[0][0]:.4f},坏信用{model.predict_proba([X_test.iloc[idx]])[0][1]:.4f}")
# 可视化LIME解释结果
exp.as_pyplot_figure()
plt.title(f"LIME单样本{idx}决策解释")
plt.tight_layout()
plt.savefig(os.path.join(out_dir, f"LIME单样本解释_{idx}.png"), dpi=300, bbox_inches="tight")
plt.show()
Cell10 AI 公平性伦理检测
重点检测模型对年龄这一敏感特征是否存在歧视,分析不同年龄组的坏信用预测率差异:
# 【Cell10】基于年龄的AI公平性分析
df_test = X_test_raw.copy()
df_test["真实标签"] = y_test
df_test["预测标签"] = y_pred
# 划分年龄组:青年(<30)、中年(30-60)、老年(>60)
df_test["年龄组"] = pd.cut(df_test["年龄"], bins=[0, 30, 60, 100], labels=["青年", "中年", "老年"])
# 计算各年龄组坏信用预测率
age_fair = df_test.groupby("年龄组")["预测标签"].mean()
print("不同年龄组坏信用预测率:")
print(age_fair)
# 可视化公平性分析结果
plt.figure(figsize=(8, 5))
age_fair.plot(kind="bar", color="skyblue")
plt.title("不同年龄组坏信用预测率对比(公平性检测)")
plt.xlabel("年龄组")
plt.ylabel("坏信用预测概率")
plt.xticks(rotation=0)
plt.tight_layout()
plt.savefig(os.path.join(out_dir, "年龄公平性分析.png"), dpi=300, bbox_inches="tight")
plt.show()
伦理解读:若不同年龄组坏信用预测率差异过大,说明模型存在年龄歧视,需通过特征调整、样本重采样等方式优化,保障 AI 公平性。
四、实验总结
- 全流程复现:本教程完成了从环境搭建、数据预处理、模型训练到可解释性分析、AI 伦理检测的完整流程,代码无冗余、可直接运行。
- 可解释性落地:通过 SHAP 实现全局特征重要性分析,通过 LIME 实现单样本决策解释,打破模型黑箱,让模型决策有据可依。
- AI 伦理实践:针对敏感特征开展公平性检测,贴合当下 AI 伦理规范要求,适用于金融风控、AI 伦理相关课程实验与毕业设计。
- 拓展方向:可替换逻辑回归、XGBoost 等模型,或针对性别、外籍工人等敏感特征做进一步公平性优化,也可将模型封装为 API 实现工程化部署。
五、常见问题排查
- ModuleNotFoundError: No module named 'seaborn':激活 ai_ethics 环境,重新执行
pip install seaborn。 - 数据加载失败:检查
german.data是否放在 Jupyter 工作目录,路径是否正确。 - 训练集测试集维度不一致:必须执行
align方法做特征对齐,否则模型无法训练。 - 中文可视化乱码:确认电脑安装 SimHei 字体,或替换为系统自带中文字体。
六、写在最后
AI 的发展不仅要追求技术效率,更要坚守伦理底线。可解释性与公平性是 AI 落地金融、医疗等敏感领域的核心前提,希望本篇教程能帮助大家掌握可解释性 AI 实战方法,树立 AI 伦理意识~
原创教程,码字不易,欢迎点赞、收藏、关注,有问题可在评论区交流!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)