返回文章列表

決策樹模型可解釋性分析與應用

本文探討決策樹模型的可解釋性,涵蓋模型結構解析、特徵重要性分析、SHAP 值應用以及 LIME 技術的實踐。透過 Python 程式碼和視覺化圖表,剖析決策樹的預測邏輯,並以客戶流失預測案例示範如何應用這些技術提升模型的透明度和可信度,為實際業務決策提供更可靠的依據。

機器學習 資料分析

決策樹模型在機器學習中應用廣泛,但其預測邏輯的理解往往不夠直觀。為此,可解釋性分析變得至關重要。本文將探討如何利用 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)

程式碼解密:

  1. 載入必要的函式庫:首先載入了 pandas、numpy、matplotlib 等必要的函式庫,用於資料處理和視覺化。
  2. 資料預處理:使用 LabelEncoder 將類別變數 area_code 轉換為數值型變數,以便於模型訓練。
  3. 目標變數處理:將目標變數 churn 轉換為虛擬變數,並刪除原始的 churn 欄位。
  4. 資料集分割:將資料集分割為訓練集和測試集,用於模型的訓練和評估。

決策樹模型的建立與評估

# 建立決策樹模型
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))

程式碼解密:

  1. 建立決策樹模型:使用 DecisionTreeClassifier 建立決策樹模型,並對訓練資料進行擬合。
  2. 評估模型效能:分別計算模型在訓練集和測試集上的準確率,以評估模型的效能。
  3. 設定最大深度引數:透過設定 max_depth 引數控制決策樹的複雜度,防止過擬合。
  4. 比較不同模型的效能:比較無限制深度和限制深度為 3 的兩個模型的效能差異。

超引數說明

超引數說明
class_weight各類別的權重
criterion用於衡量分割品質的函式,如 gini 或 entropy
max_depth樹的最大深度
max_features在尋找最佳分割時考慮的特徵數量
max_leaf_nodes以最佳優先的方式生成具有 max_leaf_nodes 的樹
min_samples_leaf葉節點所需的最小樣本數
min_samples_split分割內部節點所需的最小樣本數

超引數解密:

  1. class_weight:為不同類別分配不同的權重,以處理類別不平衡問題。
  2. criterion:選擇用於評估分割品質的標準,如 Gini 不純度或熵。
  3. max_depth:控制樹的最大深度,以防止過擬合。
  4. 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_leftchildren_right屬性提供了左右子節點的ID。
  • features屬性提供了每個節點所使用的特徵。
  • thresholds屬性提供了每個節點的閾值。
  • values屬性提供了每個節點的預測值。
  • node_sample_weight屬性提供了每個節點的樣本權重。

使用SHAP解釋決策樹模型

決策樹是一種常見的機器學習模型,用於分類別和迴歸任務。然而,理解決策樹的預測結果並不容易。SHAP(SHapley Additive exPlanations)是一種解釋機器學習模型的方法,可以幫助我們理解決策樹模型的預測結果。

決策樹的低階屬性提取

在開始使用SHAP之前,我們需要了解決策樹的一些低階屬性。這些屬性包括:

  • node_count:樹中的節點總數
  • children_left[i]:節點i的左子節點的ID
  • children_right[i]:節點i的右子節點的ID
  • feature[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
)

內容解密:

  1. shap.partial_dependence_plot 函式用於生成部分相依圖,該圖展示了特徵 “total_eve_minutes” 與客戶流失機率之間的關係。
  2. model_expected_value=Truefeature_expected_value=True 引數確保了圖中顯示的是模型的預期值和特徵的預期值。
  3. show=False 引數允許我們自定義圖表的顯示方式。
  4. 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
)

內容解密:

  1. 該程式碼生成了總晚間通話次數(total_eve_calls)的部分相依圖。
  2. 從圖中可以看出,總晚間通話次數對客戶流失機率幾乎沒有影響,無論通話次數如何變化,客戶流失機率基本保持不變。

使用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'])

內容解密:

  1. plot_partial_dependence 函式用於生成部分相依圖,該圖展示了多個特徵與預測結果之間的關係。
  2. 該程式碼展示了總日通話時長(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)

內容解密:

  1. LimeTabularExplainer 用於初始化LIME直譯器,針對表格型資料進行模型解釋。
  2. explain_instance 方法用於對特定的樣本進行解釋,傳回一個解釋物件。
  3. show_in_notebook 方法用於在Notebook中展示解釋結果,包括特徵的重要性以及它們對預測結果的貢獻度。