LIME 模型解释器
LIME 即是Local Interpretable Model-agnostic Explanations模型解释器,简单来说就是将每个变量的重要性可视化,集成学习xgb等有feature_importances_,还有专门的SHARP,那么LIME有什么优势呢?
首先我们来看看它的基本操作流程
下面使用GiveMeSomeCredit,数据地址:https://www.kaggle.com/brycecf/give-me-some-credit-dataset?select=cs-test.csv
直接看代码:
import pandas as pd import numpy as np data = pd.read_csv('cs-training.csv') #删除没有用的列 data = data.iloc[:,1:]
from xgboost import XGBClassifier import shap from sklearn.model_selection import train_test_split # 训练集测试集分割 X = data.iloc[:,1:] y = data['SeriousDlqin2yrs'] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=2022) # 模型训练 params={ 'eta':0.2, #特征权重,取值范围0~1,通常最后设置eta为0.01~0.2 'max_depth':3, #树的深度,通常取值3-10,过大容易过拟合,过小欠拟合 'min_child_weight':50, #最小样本的权重,调大参数可以繁殖过拟合 'gamma':0.4, #控制是否后剪枝,越大越保守,一般0.1、 0.2的样子 'subsample':0.8, #随机取样比例 'colsample_bytree':0.8 , #默认为1,取值0~1,对特征随机采集比例 'lambda':0.8, 'alpha':0.6, 'n_estimators':50, 'booster':'gbtree', #迭代树 'objective':'binary:logistic', #逻辑回归,输出为概率 'nthread':6, #设置最大的进程量,若不设置则会使用全部资源 'scale_pos_weight':1.5, #默认为0,1可以处理类别不平衡 'seed':1234, #随机树种子 'silent':1, #0表示输出结果 'eval_metric':'auc'} #评分指标 model = XGBClassifier(**params) model.fit(X_train, y_train) score = model.score(X_test, y_test) score #预测结果 t = model.predict_proba(X_test)[:,1]
计算AUC,KS
# import matplotlib.pyplot as plt from sklearn.metrics import roc_curve,auc def plot_roc(p1, p,string): ''' 目标:计算出分类模型的ks值 变量: self:模型fit(x,y),如(self=tree.fit(x,y)) data:一般是训练集(不包括label)或者是测试集(也是不包括label) y:label的column_name 返回:训练集(或者测试集)的auc的图片 ''' fpr, tpr, p_threshold = roc_curve(p1, p, drop_intermediate=False, pos_label=1) df = pd.DataFrame({'fpr': fpr, 'tpr': tpr, 'p': p_threshold}) df.loc[0, 'p'] = max(p) ks = (df['tpr'] - df['fpr']).max() roc_auc = auc(fpr, tpr) fig = plt.figure(figsize=(2.8, 2.8), dpi=140) ax = fig.add_subplot(111) ax.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve\nAUC = %0.4f\nK-S = %0.4f' % (roc_auc, ks) ) ax.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--') ax.set_xlim([0.0, 1.0]) ax.set_ylim([0.0, 1.05]) ax.set_xlabel('False Positive Rate') ax.set_ylabel('True Positive Rate') ax.set_title(string) ax.legend(loc="lower right") plt.close() return fig
plot_roc(y_test, t,'训练集ROC Curve') #训练集
下面使用LIME
import lime from lime import lime_tabular explainer = lime_tabular.LimeTabularExplainer( training_data=np.array(X_train), feature_names=X_train.columns, class_names=['good', 'bad'], mode='classification', discretize_continuous=False #记住要加这个参数,不然会报错 )
预测概率为0的可视化
exp = explainer.explain_instance(data_row=X_test.iloc[1], predict_fn=model.predict_proba)
exp.show_in_notebook(show_table=True)
预测概率为1的可视化
exp = explainer.explain_instance(data_row=X_test.iloc[25], predict_fn=model.predict_proba)
exp.show_in_notebook(show_table=True)
那么我们来说说它的优缺点:
优点:
(1)可以使用sklearn里面的model;
(2)可以可视化每个特征的贡献
缺点:
(1)变量中有缺失值的不能可视化,需要提前做缺失值处理
(2)看不懂预测结果0和1时的差异??可能是我们这个数据不够明显
参考资料:https://blog.csdn.net/fengdu78/article/details/118384216?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-118384216-blog-116108787.pc_relevant_multi_platform_whitelistv4eslandingrelevant&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-118384216-blog-116108787.pc_relevant_multi_platform_whitelistv4eslandingrelevant&utm_relevant_index=1
https://github.com/marcotcr/lime
后面又仔细看了一下源代码,发现discretize_continuous这个参数,
(1)如果discretize_continuous=False,连续型变量就不做处理,但是这样就会和上面的结果一样,看不出来预测结果0和1时的差异,
(2)如果将discretize_continuous=True,跑下面这段代码就报错
exp = explainer.explain_instance(data_row=X_test.iloc[1], predict_fn=model.predict_proba)
exp.show_in_notebook(show_table=True)
我猜测报错原因和缺失值有关,于是尝试先处理缺失值
import pandas as pd import numpy as np data = pd.read_csv('cs-training.csv') data = data.iloc[:,1:] data = data.fillna(0) from xgboost import XGBClassifier import shap from sklearn.model_selection import train_test_split # 训练集测试集分割 X = data.iloc[:,1:] y = data['SeriousDlqin2yrs'] X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=2022) # 模型训练 params={ 'eta':0.2, #特征权重,取值范围0~1,通常最后设置eta为0.01~0.2 'max_depth':3, #树的深度,通常取值3-10,过大容易过拟合,过小欠拟合 'min_child_weight':50, #最小样本的权重,调大参数可以繁殖过拟合 'gamma':0.4, #控制是否后剪枝,越大越保守,一般0.1、 0.2的样子 'subsample':0.8, #随机取样比例 'colsample_bytree':0.8 , #默认为1,取值0~1,对特征随机采集比例 'lambda':0.8, 'alpha':0.6, 'n_estimators':50, 'booster':'gbtree', #迭代树 'objective':'binary:logistic', #逻辑回归,输出为概率 'nthread':6, #设置最大的进程量,若不设置则会使用全部资源 'scale_pos_weight':1.5, #默认为0,1可以处理类别不平衡 'seed':1234, #随机树种子 'silent':1, #0表示输出结果 'eval_metric':'auc'} #评分指标 model = XGBClassifier(**params) model.fit(X_train, y_train) score = model.score(X_test, y_test) score import lime from lime import lime_tabular explainer = lime_tabular.LimeTabularExplainer( training_data=np.array(X_train), feature_names=X_train.columns, class_names=['good', 'bad'], mode='classification', discretize_continuous=True )
预测概率为0
exp = explainer.explain_instance(data_row=X_test.iloc[1], predict_fn=model.predict_proba)
exp.show_in_notebook(show_table=True)
预测概率为1
exp = explainer.explain_instance(data_row=X_test.iloc[25], predict_fn=model.predict_proba)
exp.show_in_notebook(show_table=True)
画权重图
exp.as_pyplot_figure()
这样就能看明白了,至于柱状图里面的数值,每个变量的重要性权重,这个权重具体是什么,有空再去研究一下。