Xgboost相对于逻辑回归模型在进行预测时往往有更好的精度,但是同时也失去了线性模型的可解释性。
Feature importance可以直观地反映出特征的重要性,看出哪些特征对最终的模型影响较大。但是无法判断特征与最终预测结果的关系是如何的。
Lundberg和Lee的论文提出了SHAP值这一广泛适用的方法用来解释各种模型(分类以及回归),如boosting和神经网络模型。
下面我们通过实战讲解SHAP。请在SofaSofa数据竞赛页面进行数据下载,下载解压这个文件。
1.1 数据处理:
import shap
from xgboost import XGBRegressor as XGBR
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('seaborn')
# 读取数据------
data = pd.read_csv(r'D:\Download\data\train.csv',parse_dates=[3])
# 分类变量编码处理------
pd.set_option('display.max_rows',500) #调整最大显示行
print(data.dtypes) # 找出分类特征,稍后进行OneHotEncoder
col = ['club', 'league', 'height_cm', 'weight_kg',
'nationality', 'potential', 'pac', 'sho', 'pas', 'dri', 'def', 'phy',
'international_reputation', 'skill_moves', 'weak_foot', 'preferred_foot', 'crossing', 'finishing',
'heading_accuracy', 'short_passing', 'volleys', 'dribbling', 'curve',
'free_kick_accuracy', 'long_passing', 'ball_control', 'acceleration',
'sprint_speed', 'agility', 'reactions', 'balance', 'shot_power',
'jumping', 'stamina', 'strength', 'long_shots', 'aggression',
'interceptions', 'positioning', 'vision', 'penalties', 'marking',
'standing_tackle', 'sliding_tackle', 'gk_diving', 'gk_handling',
'gk_kicking', 'gk_positioning', 'gk_reflexes', 'rw', 'rb', 'st', 'lw',
'cf', 'cam', 'cm', 'cdm', 'cb', 'lb', 'age'] # 去掉不相干变量
x = data[col].values
y = data['y'].values
from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder()
array_1 = enc.fit_transform(data[['work_rate_att','work_rate_def']]).toarray()
enc_lab = enc.get_feature_names(['work_rate_att','work_rate_def']).tolist() #返回新的特征列名
x_new = np.hstack([x,array_1]) # 组合好特征变量array
#col_new = [i for i in col if i not in ['work_rate_att','work_rate_def']]
col.extend(enc_lab) # 组合好特征变量列名,稍后画图待用
1.2.建模与实例化:
# 建模------
model = XGBR(max_depth=4, learning_rate=0.05, n_estimators=150)
model.fit(x_new,y)
# 特征重要性----
plt.bar(range(len(col)),model.feature_importances_)
plt.xticks(range(len(col)), col, rotation=-45, fontsize=5)
SHAP是由Shapley value启发的可加性解释模型。对于每个预测样本,模型都产生一个预测值,SHAP value就是该样本中每个特征所分配到的数值。
假设第i个样本为xi,第i个样本的第jj个特征为xi,j,模型对第i个样本的预测值为yi,整个模型的基线(通常是所有样本的目标变量的均值)为ybase,那么SHAP value服从:yi=ybase+f(xi,1)+f(xi,2)+⋯+f(xi,k),其中f(xi,1)为xi,j的SHAP值。
直观上看,f(xi,1)就是对yiyi的贡献值,当f(xi,1)>0f(xi,1)>0,说明该特征提升了预测值,也正向作用;反之,说明该特征使得预测值降低,有反作用。
2.1 单样本特征上的shap值
查看其中一位球员身价的预测值以及其特征对预测值的影响。
# SHAP实例化------
import shap
explainer = shap.TreeExplainer(model)
df = pd.DataFrame(x_new,columns=col)
shap_values = explainer.shap_values(x_new) # 计算出每个样本在66个特征上的shap值
shap_values.shape # shap值矩阵(10441, 66)
下图,蓝色表示该特征的贡献是负数,红色则表示该特征的贡献是正数。球员的身价73.46万;最长的蓝色条是潜力,身价也因此降低了180万元。
# shap可视化------
shap.initjs()
j = 0 # 以第一个样本为例,查看shap值
shap.force_plot(explainer.expected_value, shap_values[j], x_new[j])
2.2 特征在全样本的shap分析
纵轴为特征变量,横轴为shap_value(左负右正),点代表样本点。样本点红色表示特征值较高,紫色表示特征值较低。
举例来看,特征potential对预测结果的影响最大,是与value_shape正相关,potential越高会拉高shap_value。特征age与value_shape负相关,该特征值高的表示年龄较大的样本,图中为红色点,均处于纵轴左侧,即说明负向影响。
shap.summary_plot(shap_values, df)
我们也可以把一个特征对目标变量影响程度的绝对值的均值作为这个特征的重要性。
因为SHAP和feature_importance的计算方法不同,所以我们这里也得到了与modle.feature_importances_不同的重要性排序。
shap.summary_plot(shap_values,df,plot_type='bar')
https://zhuanlan.zhihu.com/p/64799119