因为前天说了shap,这里涉及到数据形状尺寸问题,所以需要在这一节说清楚,后续的神经网络我们将要和他天天打交道。
知识点:
numpy数组的创建:简单创建、随机创建、遍历、运算
numpy数组的索引:一维、二维、三维
SHAP值的深入理解
作业:今日知识点比较多,好好记忆下
1.NumPy数组的创建
简单创建
NumPy 数组是一个由相同类型元素组成的多维网格。你可以使用numpy.array()函数,通过传入 Python 列表来创建数组。
简单理解,就像把单独的数字或数字组规整的放进一个容器里,一维数组就是一列数字,二维数组就像是一个表格。
随机创建
NumPy提供了许多函数用于创建随机数组,比如np.random.rand()可以创建指定形状的随机数组,数组元素是在[0, 1)区间内均匀分布的随机数。
这就像随机抓一些数字放到指定的容器里。
遍历
遍历数组就是依次访问数组中的所有元素。队医一维数组,可以使用简单的for循环。而多维数组,可能需要嵌套的for循环。
这就好比按照一定的顺序,依次查看容器中的每个数字。
运算
NumPy数组支持各种数字运算,这些运算可以对数组中的每个元素进行操作。
这就像是把两个容器中对应位置的数字进行相加,得到一个新的容器。
2.NumPy数组的索引
一维数组索引
一维数组的索引从0开始
二维数组索引
二维数组又行和列,我们需要同时指定行索引和列索引来访问元素。
三维数组索引
三维数组可以想象成多个二维数组推叠在一起,我们需要指定三个索引:层数,行索引,列索引。
3.SHAP值的深入理解
SHAP(SHapley Additive exPlanations)值是一种用于解释机器学习模型预测结果的方法。它基于博弈论中的 Shapley 值概念。 在机器学习中,每个特征对于模型的预测结果都有一定的贡献。SHAP 值的作用就是量化每个特征对于最终预测结果的贡献大小。
例如,你有一个预测房价的模型,模型会根据房屋的面积、卧室数量、位置等特征来预测房价。SHAP 值可以告诉你每个特征(如面积、卧室数量等)对最终预测房价的影响有多大。 SHAP 值有正有负,正的 SHAP 值表示该特征增加了模型的预测值,负的 SHAP 值表示该特征降低了模型的预测值。通过计算和分析 SHAP 值,你可以更好地理解模型是如何做出预测的,哪些特征对预测结果影响较大,从而提高模型的可解释性。 简单来说,SHAP 值就像是一个 “功劳簿”,记录了每个特征在模型预测中所起到的作用。
完整代码如下:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
import time
import shap
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix
# 设置中文字体(解决中文显示问题)
plt.rcParams['font.sans-serif'] = ['SimHei'] # Windows系统常用黑体字体
plt.rcParams['axes.unicode_minus'] = False # 正常显示负号
warnings.filterwarnings("ignore")
# 读取数据
data = pd.read_csv('data.csv')
# 筛选字符串变量并进行编码
discrete_features = data.select_dtypes(include=['object']).columns.tolist()
# Home Ownership 标签编码
home_ownership_mapping = {
'Own Home': 1,
'Rent': 2,
'Have Mortgage': 3,
'Home Mortgage': 4
}
data['Home Ownership'] = data['Home Ownership'].map(home_ownership_mapping)
# Years in current job 标签编码
years_in_job_mapping = {
'< 1 year': 1,
'1 year': 2,
'2 years': 3,
'3 years': 4,
'4 years': 5,
'5 years': 6,
'6 years': 7,
'7 years': 8,
'8 years': 9,
'9 years': 10,
'10+ years': 11
}
data['Years in current job'] = data['Years in current job'].map(years_in_job_mapping)
# Purpose 独热编码
data = pd.get_dummies(data, columns=['Purpose'])
data2 = pd.read_csv("data.csv") # 重新读取数据,用来做列名对比
list_final = [] # 新建一个空列表,用于存放独热编码后新增的特征名
for i in data.columns:
if i not in data2.columns:
list_final.append(i) # 这里打印出来的就是独热编码后的特征名
for i in list_final:
data[i] = data[i].astype(int) # 这里的i就是独热编码后的特征名
# Term 0 - 1 映射
term_mapping = {
'Short Term': 0,
'Long Term': 1
}
data['Term'] = data['Term'].map(term_mapping)
data.rename(columns={'Term': 'Long Term'}, inplace=True) # 重命名列
# 连续特征用中位数补全
continuous_features = data.select_dtypes(include=['int64', 'float64']).columns.tolist()
for feature in continuous_features:
mode_value = data[feature].mode()[0]
data[feature].fillna(mode_value, inplace=True)
# 划分数据集
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)
# 训练随机森林模型
start_time = time.time()
rf_model = RandomForestClassifier(random_state=42)
rf_model.fit(X_train, y_train)
rf_pred = rf_model.predict(X_test)
end_time = time.time()
print(f"训练与预测耗时: {end_time - start_time:.4f} 秒")
print("\n默认随机森林 在测试集上的分类报告:")
print(classification_report(y_test, rf_pred))
print("默认随机森林 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, rf_pred))
# 计算 SHAP 值
explainer = shap.TreeExplainer(rf_model)
shap_values = explainer.shap_values(X_test)
# 检查 SHAP 值的形状
print(type(shap_values)) # 应该是 list
print(len(shap_values)) # 对于二分类问题,应该是 2
print(shap_values[0].shape) # 应该是 (n_samples, n_features)
print(shap_values[1].shape) # 应该是 (n_samples, n_features)
# 确保 X_test 是 pandas.DataFrame
X_test_df = pd.DataFrame(X_test, columns=X.columns)
# 绘制全局特征重要性图
shap.summary_plot(shap_values[1], X_test_df, feature_names=X_test_df.columns)
# 绘制特征值与 SHAP 值的关系图
shap.dependence_plot('Years in current job', shap_values[1], X_test_df, feature_names=X_test_df.columns)
# 绘制力图
shap.force_plot(explainer.expected_value[1], shap_values[1][0, :], X_test_df.iloc[0, :], feature_names=X_test_df.columns)
# 绘制决策图
shap.decision_plot(explainer.expected_value[1], shap_values[1][0, :], X_test_df.iloc[0, :], feature_names=X_test_df.columns)
# 绘制瀑布图
shap.plots.waterfall(shap_values[1][0, :], max_display=10)
# 绘制热图
shap.plots.heatmap(shap_values[1])
@浙大疏锦行