機器學(xué)習(xí)模型可解釋性的6種Python工具包,總有一款適合你!
點擊左上方藍字關(guān)注我們

作者 | 木瓜子@知乎
鏈接 | https://zhuanlan.zhihu.com/p/385424638
在這篇文章中,我想向大家介紹我的一些頂級機器學(xué)習(xí)可解釋性 Python 工具包,有所收獲,歡迎點贊分享。
我們開始吧!
1、Yellowbrick
Yellowbrick 是一個開源的 Python 包,它通過可視化分析和診斷工具擴展了 scikit-learn API。對數(shù)據(jù)科學(xué)家而言,Yellowbrick 用于評估模型性能和可視化模型行為。
Yellowbrick 是一個多用途軟件包,你可以在日常建模工作中使用。盡管來自 Yellowbrick 的大多數(shù)解釋API都處于基本級別,但它對于我們的第一個建模步驟仍然有用。
讓我們用一個數(shù)據(jù)集示例來嘗試 Yellowbrick 包。對于初學(xué)者,讓我們安裝軟件包。
pip install yellowbrick
安裝完成后,我們可以使用 Yellowbrick 的 dataset 示例來測試包。
#Pearson Correlation
from yellowbrick.features import rank2d
from yellowbrick.datasets import load_credit
X, _ = load_credit()
visualizer = rank2d(X)
通過一條直線,我們可以使用 Pearson 相關(guān)方法來可視化特征之間的相關(guān)性。它是可定制的,因此你可以使用另一個相關(guān)函數(shù)。
讓我們嘗試開發(fā)模型來評估模型性能并解釋模型。我將使用 Yellowbrick 用戶指南中的示例數(shù)據(jù)集,并生成一個判別閾值圖,以找到分隔二進制類的最佳閾值。
from yellowbrick.classifier import discrimination_threshold
from sklearn.linear_model import LogisticRegression
from yellowbrick.datasets import load_spam
X, y = load_spam()
visualizer = discrimination_threshold(LogisticRegression(multi_class="auto", solver="liblinear"), X,y)

使用 Yellowbrick 閾值圖,我們可以解釋模型在0.4概率閾值下表現(xiàn)最好。
如果你想知道 Yellowbrick 能做什么,請訪問主頁了解更多信息。
https://www.scikit-yb.org/en/latest/about.html
2、ELI5
ELI5 是一個 Python 包,有助于機器學(xué)習(xí)的可解釋性。取自Eli5軟件包,此軟件包的基本用法是:
檢查模型參數(shù),試圖弄清楚模型是如何全局工作的 檢查模型的單個預(yù)測,并找出模型做出決策的原因
如果 Yellowbrick 側(cè)重于特征和模型性能解釋,ELI5 側(cè)重于模型參數(shù)和預(yù)測結(jié)果。就我個人而言,我更喜歡 ELI5,因為它的解釋非常簡單,商業(yè)人士可以理解它。
讓我們用一個示例數(shù)據(jù)集和隨機森林模型分類器來嘗試 ELI5 包。我將使用 seaborn 包中的數(shù)據(jù)集,因為它是最簡單的數(shù)據(jù)集。
#Preparing the model and the dataset
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
mpg = sns.load_dataset('mpg').dropna()
mpg.drop('name', axis =1 , inplace = True)
#Data splitting
X_train, X_test, y_train, y_test = train_test_split(mpg.drop('origin', axis = 1), mpg['origin'], test_size = 0.2, random_state = 121)
#Model Training
clf = RandomForestClassifier()
clf.fit(X_train, y_train)
最基本的 ELI5 函數(shù)是表示分類器權(quán)重和分類器預(yù)測結(jié)果。讓我們嘗試這兩個函數(shù)來理解解釋是如何產(chǎn)生的。
import eli5
eli5.show_weights(clf, feature_names = list(X_test.columns))

從上圖中,可以看到分類器顯示了分類器特征的重要性及其偏差。你可以看到'displacement'特征是最重要的特征,但是它們有很高的偏差,這表明模型中存在偏差。讓我們試著展示一下預(yù)測結(jié)果的可解釋性。
eli5.show_prediction(clf, X_train.iloc[0])

利用 ELI5 的 show_prediction 函數(shù),得到特征貢獻信息。哪些特征對某些預(yù)測結(jié)果有貢獻?這些特征對概率的影響有多大。這是一個很好的函數(shù),你可以輕松地向業(yè)務(wù)人員解釋模型預(yù)測。
但是,最好記住上面的函數(shù)是基于樹的解釋(因為我們使用隨機森林模型)。它可能足夠好給你一個商業(yè)人士的解釋;然而,由于模型的原因,它可能是有偏差的。這就是為什么 ELI5 提供了另一種基于模型度量來解釋黑盒模型的方法——它被稱為置換重要性(Permutation Importance)。
讓我們先試試置換重要性函數(shù)。
#Permutation Importance
perm = PermutationImportance(clf, scoring = 'accuracy',random_state=101).fit(X_test, y_test)
show_weights(perm, feature_names = list(X_test.columns))

置換重要性背后的思想是評分(準確度、精確度、召回等)如何隨特征的存在或不存在而變化。從以上結(jié)果可以看出,displacement 的得分最高,為0.3013。當置換位移特征時,模型的精度會有0.3013的變化。正負號后面的值就是不確定值。置換重要性法的本質(zhì)上是一個隨機過程;這就是為什么我們有不確定值。
位置越高,影響得分的特征就越關(guān)鍵。底部的一些特征顯示一個負值,這很有趣,因為這意味著當我們排列特征時,該特征會增加得分。就我個人而言,ELI5 為我提供了足夠的機器學(xué)習(xí)解釋能力。如果你想了解更多,可以參考如下鏈接:
https://github.com/TeamHG-Memex/eli5
3、SHAP
我之前文章中已多次提及了,如果我們在討論機器學(xué)習(xí)的解釋性,SHAP 是繞不開的。對于從未聽說過的人,SHAP或(SHapley Additive exPlanations)是一種博弈論方法,用來解釋任何機器學(xué)習(xí)模型的輸出。簡單地說,SHAP 是使用 SHAP 值來解釋每個特性的重要性。
讓我們嘗試使用示例數(shù)據(jù)集和模型來更詳細地解釋SHAP。首先,我們需要安裝SHAP包。
#Installation via pip
pip install shap
#Installation via conda-forge
conda install -c conda-forge shap
在這個示例中,我將使用泰坦尼克號示例數(shù)據(jù)集。
#Preparing the model and the dataset
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
titanic = sns.load_dataset('titanic').dropna()
titanic = titanic[['survived', 'age', 'sibsp', 'parch']]
#Data splitting for rfc
X_train, X_test, y_train, y_test = train_test_split(titanic.drop('survived', axis = 1), titanic['survived'], test_size = 0.2, random_state = 121)
#Model Training
clf = RandomForestClassifier() clf.fit(X_train, y_train)
我們已經(jīng)用泰坦尼克號的數(shù)據(jù)訓(xùn)練了我們的數(shù)據(jù),現(xiàn)在我們可以試著用SHAP來解釋數(shù)據(jù)。讓我們使用模型的全局可解釋性來理解SHAP是如何工作的。
import shap
shap_values = shap.TreeExplainer(clf).shap_values(X_train) shap.summary_plot(shap_values, X_train)

從預(yù)測結(jié)果可以看出,年齡特征對預(yù)測結(jié)果的貢獻最大。如果你想查看特定的類對預(yù)測的貢獻,我們只需要稍微調(diào)整一下代碼。假設(shè)我們想看看類0,這意味著我們使用以下代碼。
shap.summary_plot(shap_values[0], X_train)
從上圖中,我們可以看到每個數(shù)據(jù)對預(yù)測概率的貢獻。顏色越紅,值越高,反之亦然。此外,當值為正時,它有助于0級預(yù)測結(jié)果概率。
SHAP不局限于全局可解釋性;它還提供了解釋單個數(shù)據(jù)集的函數(shù)。讓我們試著解釋第一行的預(yù)測結(jié)果。
explainer = shap.TreeExplainer(clf)
shap_value_single = explainer.shap_values(X = X_train.iloc[0,:])
shap.force_plot(base_value = explainer.expected_value[1],shap_values = shap_value_single[1],features = X_train.iloc[0,:])
從上圖中可以看出,預(yù)測更接近于類0,因為它是由年齡和 sibsp 特征推送的,而parch特征只提供了一點貢獻。
4、Mlxtend
Mlxtend 是一個用于數(shù)據(jù)科學(xué)日常工作的 Python 包。包中的api不僅限于可解釋性,還擴展到各種功能,如統(tǒng)計評估、數(shù)據(jù)模式、圖像提取等。但是,我們將討論我們當前文章的可解釋性API—決策區(qū)域。
Decision Regions plot API 將生成一個 Decision region plot,以可視化特征如何決定分類模型預(yù)測。讓我們嘗試使用示例數(shù)據(jù)和Mlxtend的指南。
首先,我們需要安裝 Mlxtend 包。
pip install Mlxtend
然后,我們使用示例數(shù)據(jù)集并開發(fā)一個模型來查看 MLXTEN 的操作。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import itertools
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from mlxtend.classifier import EnsembleVoteClassifier
from mlxtend.data import iris_data
from mlxtend.plotting import plot_decision_regions
# Initializing Classifiers
clf1 = LogisticRegression(random_state=0)
clf2 = RandomForestClassifier(random_state=0)
clf3 = SVC(random_state=0, probability=True)
eclf = EnsembleVoteClassifier(clfs=[clf1, clf2, clf3], weights=[2, 1, 1], voting='soft')
# Loading some example data
X, y = iris_data()
X = X[:,[0, 2]]
# Plotting Decision Regions
gs = gridspec.GridSpec(2, 2)
fig = plt.figure(figsize=(10, 8))
for clf, lab, grd in zip([clf1, clf2, clf3, eclf],['Logistic Regression', 'Random Forest','RBF kernel SVM', 'Ensemble'],itertools.product([0, 1], repeat=2)):
clf.fit(X, y)
ax = plt.subplot(gs[grd[0], grd[1]])
fig = plot_decision_regions(X=X, y=y, clf=clf, legend=2)
plt.title(lab)
plt.show()

從以上情節(jié)可以解釋模型的決策。當每個模型進行預(yù)測時,可以看到它們之間的差異。例如,一類的 Logistic 回歸模型預(yù)測結(jié)果越大,X軸值越高,但Y軸上變化不大。與隨機森林模型相比,在X軸值之后,劃分沒有很大變化,Y軸值在每次預(yù)測中都是常數(shù)。
決策區(qū)域的唯一缺點是它只限于二維特征,因此,它比實際模型本身更適合于預(yù)分析。
5、PDPBox
PDP(Partial Dependence Plot) 是一個顯示特征對機器學(xué)習(xí)模型預(yù)測結(jié)果的邊際影響的圖。它用于評估特征與目標之間的相關(guān)性是線性的、單調(diào)的還是更復(fù)雜的。
讓我們嘗試使用如下示例數(shù)據(jù)來了解PDPBox。首先,我們需要安裝PDPBox包。
pip install pdpbox
我們可以嘗試獲取更多關(guān)于:PDPBox如何幫助我們創(chuàng)建可解釋的機器學(xué)習(xí)的信息。
import pandas as pd
from pdpbox import pdp, get_dataset, info_plots
#We would use the data and model from the pdpbox
test_titanic = get_dataset.titanic()
titanic_data = test_titanic['data']
titanic_features = test_titanic['features']
titanic_model = test_titanic['xgb_model']
titanic_target = test_titanic['target']
當我們有了數(shù)據(jù)和模型后,讓我們嘗試使用 info_plots 函數(shù)檢查特征和目標之間的信息。
fig, axes, summary_df = info_plots.target_plot(df=titanic_data, feature='Sex', feature_name='gender', target=titanic_target)
_ = axes['bar_ax'].set_xticklabels(['Female', 'Male'])
你可以通過一個函數(shù)獲取目標和特征的統(tǒng)計信息,這可以讓業(yè)務(wù)方很容易解釋。讓我們檢查模型預(yù)測分布函數(shù)以及特征。
fig, axes, summary_df = info_plots.actual_plot(model=titanic_model, X=titanic_data[titanic_features], feature='Sex', feature_name='gender')
現(xiàn)在,讓我們繼續(xù)使用PDP繪圖函數(shù)來解釋我們的模型預(yù)測。
pdp_sex = pdp.pdp_isolate(model=titanic_model, dataset=titanic_data, model_features=titanic_features, feature='Sex')
fig, axes = pdp.pdp_plot(pdp_sex, 'Sex')
_ = axes['pdp_ax'].set_xticklabels(['Female', 'Male'])
從上圖中,我們可以解釋當性別特征為男性時,預(yù)測概率降低(意味著男性存活的可能性降低)。這就是我們?nèi)绾问褂?PDPbox 來實現(xiàn)模型的可解釋性。
6、InterpretML
InterpretML 是一個Python包,它包含許多機器學(xué)習(xí)可解釋性API。此包的目的是基于繪圖圖提供交互式繪圖,以了解預(yù)測結(jié)果。
InterpretML 提供了許多方法來解釋你的機器學(xué)習(xí),方法包括使用我們討論過的許多技術(shù)——即SHAP和PDP。此外,這個包擁有一個Glassbox模型API,它在開發(fā)模型時提供了一個可解釋性函數(shù)。
讓我們用一個示例數(shù)據(jù)集來嘗試這個包。首先,我們需要安裝 InterpretML。
pip install interpret
讓我們嘗試使用泰坦尼克號數(shù)據(jù)集示例來開發(fā)模型。
from sklearn.model_selection import train_test_split
from interpret.glassbox import ExplainableBoostingClassifier
import seaborn as sns
#the glass box model (using Boosting Classifier)
ebm = ExplainableBoostingClassifier(random_state=120)
titanic = sns.load_dataset('titanic').dropna()
#Data splitting
X_train, X_test, y_train, y_test = train_test_split(titanic.drop(['survived', 'alive'], axis = 1), titanic['survived'], test_size = 0.2, random_state = 121)
#Model Training
ebm.fit(X_train, y_train)

它將自動對你的特征進行熱編碼,并設(shè)計交互特性。讓我們試著得到這個模型的全局解釋。
from interpret import set_visualize_provider
from interpret.provider import InlineProvider
set_visualize_provider(InlineProvider())
from interpret import show
ebm_global = ebm.explain_global()
show(ebm_global)
從上圖中,我們可以看到模型特征重要性的總結(jié)。它根據(jù)模型特征的重要性向你顯示所有被認為重要的特征。
“可解釋”是一個交互式繪圖,可以使用它來更具體地解釋模型。如果我們只在上圖中看到摘要,我們可以選擇另一個組件來指定要查看的功能。這樣,我們就可以解釋模型中的特征是如何影響預(yù)測的。
在上圖中,我們可以看到低票價降低了生存的機會,但隨著票價越來越高,它增加了生存的機會。然而,你可以看到密度和條形圖-許多人來自較低的票價。
通常情況下,我們不僅對整體的可解釋性感興趣,而且對局部的可解釋性感興趣。在本例中,我們可以使用以下代碼來解釋它。
#Select only the top 5 rows from the test data
ebm_local = ebm.explain_local(X_test[:5], y_test[:5])
show(ebm_local)
局部可解釋性顯示了單個預(yù)測是如何進行的。這里顯示的值是來自模型的對數(shù)賠率分數(shù),它們被添加并通過 logistic 函數(shù)傳遞,以得到最終預(yù)測。在這個預(yù)測中,我們可以看到男性對降低存活率的貢獻最大。
總結(jié)
機器學(xué)習(xí)的可解釋性對于任何數(shù)據(jù)科學(xué)家來說都是一個重要的工具,因為它可以讓你更好地將模型結(jié)果傳達給業(yè)務(wù)用戶,內(nèi)容較多,希望對大家有幫助!
END
整理不易,點贊三連↓
