決策樹模型在機器學習中應用廣泛,但其預測邏輯的理解往往不夠直觀。為此,可解釋性分析變得至關重要。本文將探討如何利用 SHAP、LIME 等技術,結合 Python 程式碼及視覺化工具,深入理解決策樹模型的決策過程。文章首先介紹決策樹的非線性擬合能力和結構,接著示範如何使用 Python 程式碼建構、訓練和評估決策樹模型,並詳細解釋程式碼的每個步驟。然後,文章重點闡述如何使用 SHAP 函式庫生成部分相依圖(PDP)和計算 SHAP 值,以理解特徵對預測結果的影響。此外,文章還介紹瞭如何使用 LIME 技術解釋區域性預測結果,並提供相關 Python 程式碼示例。最後,文章總結了不同可解釋性技術的應用場景和優缺點,並強調了可解釋性分析在提升模型透明度和可信度方面的重要性。
決策樹模型的可解釋性分析
決策樹是一種常見的機器學習模型,用於處理分類別和迴歸問題。與線性模型不同,決策樹能夠捕捉資料中的非線性關係,因此在許多實際應用中具有很高的價值。然而,決策樹的複雜性也使得其可解釋性成為一個挑戰。
決策樹的非線性擬合能力
如圖 4-1 所示,決策樹能夠透過增加最大深度引數來近似非線性關係。隨著最大深度引數從 2 增加到 5,所有不在曲線上的點也成為模型的一部分,因此它們出現在由決策樹模型生成的規則集中。
決策樹的結構解析
圖 4-2 描述了決策樹的起始部分。決策樹從根節點開始,透過選擇最佳特徵進行分支。終端節點是樹建構停止的位置。為了預測特定記錄的結果,使用整體資料的平均結果。
模型可解釋性的方法
如圖 4-3 所示,模型可解釋性可以透過兩種方式實作:使用 XAI 函式庫或基本的機器學習函式庫。兩者的區別在於,如果使用父級機器學習函式庫,可以直接使用已經訓練好的模型。否則,如果使用 XAI 函式庫,可能需要重新訓練機器學習模型。
決策樹模型的資料準備
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn import tree, metrics, model_selection, preprocessing
from IPython.display import Image, display
from sklearn.metrics import confusion_matrix, classification_report
# 載入資料
df_train = pd.read_csv('ChurnData.csv')
del df_train['Unnamed: 0']
# 資料預處理
tras = LabelEncoder()
df_train['area_code_tr'] = tras.fit_transform(df_train['area_code'])
del df_train['area_code']
# 處理目標變數
df_train['target_churn_dum'] = pd.get_dummies(df_train.churn, prefix='churn', drop_first=True)
del df_train['international_plan']
del df_train['voice_mail_plan']
del df_train['churn']
# 分割資料集為訓練集和測試集
X = df_train[['account_length', 'number_vmail_messages', 'total_day_minutes',
'total_day_calls', 'total_day_charge', 'total_eve_minutes',
'total_eve_calls', 'total_eve_charge', 'total_night_minutes',
'total_night_calls', 'total_night_charge', 'total_intl_minutes',
'total_intl_calls', 'total_intl_charge',
'number_customer_service_calls', 'area_code_tr']]
Y = df_train['target_churn_dum']
xtrain, xtest, ytrain, ytest = train_test_split(X, Y, test_size=0.20, stratify=Y)
程式碼解密:
- 載入必要的函式庫:首先載入了 pandas、numpy、matplotlib 等必要的函式庫,用於資料處理和視覺化。
- 資料預處理:使用
LabelEncoder將類別變數area_code轉換為數值型變數,以便於模型訓練。 - 目標變數處理:將目標變數
churn轉換為虛擬變數,並刪除原始的churn欄位。 - 資料集分割:將資料集分割為訓練集和測試集,用於模型的訓練和評估。
決策樹模型的建立與評估
# 建立決策樹模型
dt1 = tree.DecisionTreeClassifier()
dt1.fit(xtrain, ytrain)
# 評估模型效能
print(dt1.score(xtrain, ytrain))
print(dt1.score(xtest, ytest))
# 設定最大深度引數的決策樹模型
dt2 = tree.DecisionTreeClassifier(max_depth=3)
dt2.fit(xtrain, ytrain)
# 評估模型效能
print(dt2.score(xtrain, ytrain))
print(dt2.score(xtest, ytest))
程式碼解密:
- 建立決策樹模型:使用
DecisionTreeClassifier建立決策樹模型,並對訓練資料進行擬合。 - 評估模型效能:分別計算模型在訓練集和測試集上的準確率,以評估模型的效能。
- 設定最大深度引數:透過設定
max_depth引數控制決策樹的複雜度,防止過擬合。 - 比較不同模型的效能:比較無限制深度和限制深度為 3 的兩個模型的效能差異。
超引數說明
| 超引數 | 說明 |
|---|---|
| class_weight | 各類別的權重 |
| criterion | 用於衡量分割品質的函式,如 gini 或 entropy |
| max_depth | 樹的最大深度 |
| max_features | 在尋找最佳分割時考慮的特徵數量 |
| max_leaf_nodes | 以最佳優先的方式生成具有 max_leaf_nodes 的樹 |
| min_samples_leaf | 葉節點所需的最小樣本數 |
| min_samples_split | 分割內部節點所需的最小樣本數 |
超引數解密:
class_weight:為不同類別分配不同的權重,以處理類別不平衡問題。criterion:選擇用於評估分割品質的標準,如 Gini 不純度或熵。max_depth:控制樹的最大深度,以防止過擬合。max_features:限制在尋找最佳分割時考慮的特徵數量,以提高模型的泛化能力。
決策樹模型的可解釋性分析
在機器學習領域中,決策樹是一種廣泛使用的非線性模型。決策樹模型的優點在於其可解釋性強,能夠以規則的形式呈現預測結果。然而,當決策樹過於龐大時,其可解釋性就會下降,並且難以在實際專案中實施。
決策樹視覺化
決策樹可以使用GraphViz或plot_tree函式進行視覺化。以下程式碼展示瞭如何使用GraphViz進行視覺化:
dot_data = tree.export_graphviz(dt1, out_file=None, filled=True, rounded=True,
feature_names=list(xtrain.columns),
class_names=['yes','no'])
graph = pydotplus.graph_from_dot_data(dot_data)
display(Image(graph.create_png()))
內容解密:
tree.export_graphviz函式用於將決策樹模型匯出為GraphViz格式的資料。feature_names引數指定了特徵名稱,class_names引數指定了類別名稱。pydotplus.graph_from_dot_data函式用於將GraphViz格式的資料轉換為圖形物件。display(Image(graph.create_png()))用於顯示決策樹的視覺化結果。
剪枝的重要性
預設的決策樹模型可能會產生一個龐大的樹,這不僅難以解讀,也難以在實際專案中實施。透過限制最大深度引數,可以對決策樹進行剪枝,得到一個更小、更穩健的模型。
dt2 = DecisionTreeClassifier(max_depth=3)
內容解密:
max_depth引數限制了決策樹的最大深度,從而避免了過度擬合。
決策樹規則提取
決策樹模型可以提取出規則文字,用於解讀和實施。以下程式碼展示瞭如何提取規則文字:
from sklearn.tree import export_text
r = export_text(dt2, feature_names=list(xtrain.columns))
print(r)
內容解密:
export_text函式用於將決策樹模型匯出為規則文字。feature_names引數指定了特徵名稱。
特徵重要性分析
決策樹模型可以提供特徵重要性分析,用於瞭解哪些特徵對預測結果有較大的影響。以下程式碼展示瞭如何進行特徵重要性分析:
list(zip(dt1.feature_importances_, xtrain.columns))
內容解密:
feature_importances_屬性提供了特徵重要性的評估值。zip函式用於將特徵重要性評估值與特徵名稱進行配對。
決策樹結構分析
決策樹模型具有一個名為tree_的屬性,可以用於取得模型的詳細結構資訊。以下程式碼展示瞭如何取得決策樹的結構資訊:
children_left = dt2.tree_.children_left
children_right = dt2.tree_.children_right
features = dt2.tree_.feature
thresholds = dt2.tree_.threshold
values = dt2.tree_.value.reshape(dt2.tree_.value.shape[0], 2)
node_sample_weight = dt2.tree_.weighted_n_node_samples
內容解密:
children_left和children_right屬性提供了左右子節點的ID。features屬性提供了每個節點所使用的特徵。thresholds屬性提供了每個節點的閾值。values屬性提供了每個節點的預測值。node_sample_weight屬性提供了每個節點的樣本權重。
使用SHAP解釋決策樹模型
決策樹是一種常見的機器學習模型,用於分類別和迴歸任務。然而,理解決策樹的預測結果並不容易。SHAP(SHapley Additive exPlanations)是一種解釋機器學習模型的方法,可以幫助我們理解決策樹模型的預測結果。
決策樹的低階屬性提取
在開始使用SHAP之前,我們需要了解決策樹的一些低階屬性。這些屬性包括:
node_count:樹中的節點總數children_left[i]:節點i的左子節點的IDchildren_right[i]:節點i的右子節點的IDfeature[i]:用於分割節點i的特徵threshold[i]:節點i的閾值n_node_samples[i]:到達節點i的訓練樣本數量impurity[i]:節點i的不純度
這些屬性可以幫助我們瞭解決策樹的結構和預測過程。
使用SHAP解釋決策樹模型
要使用SHAP解釋決策樹模型,我們需要建立一個TreeExplainer物件,並將決策樹模型作為引數傳遞給它。然後,我們可以使用model_churn_proba函式來計算預測機率。
import shap
# 定義自定義樹模型
tree_dict = {
"children_left": children_left,
"children_right": children_right,
"children_default": children_default,
"features": features,
"thresholds": thresholds,
"values": values,
"node_sample_weight": node_sample_weight
}
model = {
"trees": [tree_dict]
}
explainer = shap.TreeExplainer(model)
# 提供機率作為輸出
def model_churn_proba(x):
return dt2.predict_proba(x)[:,1]
# 提供對數機率作為輸出
def model_churn_log_odds(x):
p = dt2.predict_log_proba(x)
return p[:,1] - p[:,0]
部分相依圖
部分相依圖(Partial Dependence Plot,PDP)是一種視覺化工具,用於展示特徵和目標變數之間的關係。PDP可以幫助我們瞭解特徵如何影響預測結果。
# 製作標準部分相依圖
sample_ind = 25
fig, ax = shap.partial_dependence_plot(
"total_day_minutes", model_churn_proba, X, model_expected_value=True,
feature_expected_value=True, show=False, ice=False
)
圖4-10:總日分鐘數與客戶流失機率的PDP圖
從圖4-10中,我們可以看到總日分鐘數與客戶流失機率之間的關係。當總日分鐘數小於225時,客戶流失機率低於平均值(14.25%)。即使總日分鐘數大於225,客戶流失機率仍然低於25%。
圖4-11:語音信箱數量與客戶流失機率的PDP圖
從圖4-11中,我們可以看到語音信箱數量與客戶流失機率之間的關係。藍色的平行線表明,無論語音信箱數量如何,邊際貢獻都保持不變,這意味著該特徵對預測結果沒有顯著影響。
圖4-12:帳戶長度與客戶流失機率的PDP圖
從圖4-12中,我們可以看到帳戶長度與客戶流失機率之間的關係。藍色的直線表明,帳戶長度對客戶流失機率沒有影響。
圖4-13:客戶服務呼叫次數與客戶流失機率的PDP圖
從圖4-13中,我們可以看到客戶服務呼叫次數與客戶流失機率之間的關係。當客戶服務呼叫次數大於4時,客戶流失機率會增加。
非線性模型的可解釋性:以客戶流失預測為例
在機器學習領域中,非線性模型(如決策樹、隨機森林等)因其出色的預測能力而被廣泛應用。然而,這些模型的複雜性往往使得其決策過程難以被理解。為瞭解決這一問題,研究人員開發了多種可解釋性技術,如SHAP(SHapley Additive exPlanations)、LIME(Local Interpretable Model-agnostic Explanations)等。本章將以客戶流失預測為例,介紹如何使用這些技術來解釋非線性模型的預測結果。
使用SHAP進行模型解釋
SHAP是一種根據 Shapley 值的模型解釋技術,可以用於解釋任何機器學習模型的預測結果。其核心思想是將每個特徵對預測結果的貢獻度進行量化,從而揭示模型的決策過程。
部分相依圖(Partial Dependence Plot, PDP)
部分相依圖是一種用於展示特徵與預測結果之間關係的視覺化工具。透過SHAP函式庫,我們可以輕鬆地生成部分相依圖。
import shap
# 生成部分相依圖
sample_ind = 25
fig, ax = shap.partial_dependence_plot(
"total_eve_minutes", model_churn_proba, X, model_expected_value=True,
feature_expected_value=True, show=False, ice=False
)
內容解密:
shap.partial_dependence_plot函式用於生成部分相依圖,該圖展示了特徵 “total_eve_minutes” 與客戶流失機率之間的關係。model_expected_value=True和feature_expected_value=True引數確保了圖中顯示的是模型的預期值和特徵的預期值。show=False引數允許我們自定義圖表的顯示方式。ice=False引數關閉了個別條件期望(Individual Conditional Expectation, ICE)曲線的顯示。
分析結果
透過部分相依圖,我們可以觀察到不同特徵對客戶流失機率的影響。例如,當總日通話費用(total day charge)超過45美元時,客戶流失的機率會顯著增加。這是因為高昂的費用促讓使用者尋找替代服務提供商。
總晚間通話時長(total evening minutes)對客戶流失機率的影響
研究發現,總晚間通話時長對客戶流失機率有一定的影響,但其影響程度相對有限。當總晚間通話時長在180分鐘以內時,客戶流失機率保持在一個較低的水平(約13%)。當通話時長超過180分鐘後,流失機率略有上升,但整體而言,其對客戶流失的影響並不顯著。
# 生成總晚間通話次數的部分相依圖
fig, ax = shap.partial_dependence_plot(
"total_eve_calls", model_churn_proba, X, model_expected_value=True,
feature_expected_value=True, show=False, ice=False
)
內容解密:
- 該程式碼生成了總晚間通話次數(total_eve_calls)的部分相依圖。
- 從圖中可以看出,總晚間通話次數對客戶流失機率幾乎沒有影響,無論通話次數如何變化,客戶流失機率基本保持不變。
使用Scikit-Learn進行模型解釋
除了SHAP函式庫外,Scikit-Learn也提供了部分相依圖的功能,可以用於模型解釋。
from sklearn.inspection import plot_partial_dependence
# 生成部分相依圖
plot_partial_dependence(dt2, X, ['total_day_minutes', 'total_day_calls', 'total_day_charge'])
內容解密:
plot_partial_dependence函式用於生成部分相依圖,該圖展示了多個特徵與預測結果之間的關係。- 該程式碼展示了總日通話時長(total_day_minutes)、總日通話次數(total_day_calls)和總日通話費用(total_day_charge)對客戶流失機率的影響。
LIME技術
LIME是一種區域性可解釋的模型無關解釋技術,可以用於解釋任何機器學習模型的區域性預測結果。
import lime
import lime.lime_tabular
# 初始化LIME直譯器
explainer = lime.lime_tabular.LimeTabularExplainer(np.array(xtrain),
feature_names=list(xtrain.columns),
class_names=['target_churn_dum'],
verbose=True, mode='classification')
# 對測試集中的第一個樣本進行解釋
exp = explainer.explain_instance(xtest.iloc[0], dt2.predict_proba, num_features=16)
exp.show_in_notebook(show_table=True)
內容解密:
LimeTabularExplainer用於初始化LIME直譯器,針對表格型資料進行模型解釋。explain_instance方法用於對特定的樣本進行解釋,傳回一個解釋物件。show_in_notebook方法用於在Notebook中展示解釋結果,包括特徵的重要性以及它們對預測結果的貢獻度。