對比式解釋技術有助於理解模型預測結果背後的關鍵因素,不僅能識別影響預測的重要特徵,還能比較不同類別特徵的差異。CEM 方法提供了一種系統性的生成對比式解釋的流程,透過調整引數,可以針對不同資料集和模型特性進行客製化解釋。此外,模型無關解釋的興起,讓開發者不需深入模型結構,即可理解模型行為。Alibi 函式庫提供的錨點解釋,更進一步找出穩固的規則,揭示模型預測的區域性和全域性影響因素,提升模型的可解釋性和透明度。
對比式解釋在機器學習中的應用
簡介
對比式解釋(Contrastive Explanations)是一種用於解釋機器學習模型預測結果的方法,透過找出與預測結果相關的關鍵特徵,幫助使用者理解模型的決策過程。在本章中,我們將介紹如何使用對比式解釋方法來分析機器學習模型的預測結果。
對比式解釋的基本概念
對比式解釋的核心思想是找出與預測結果相關的關鍵特徵,並將其與其他類別的特徵進行比較,從而幫助使用者理解模型的決策過程。對比式解釋可以分為兩種型別:Pertinent Negative(PN)和Pertinent Positive(PP)。
- Pertinent Negative(PN):找出使模型預測結果不同的最小特徵集合,即如果缺少這些特徵,模型的預測結果將會改變。
- Pertinent Positive(PP):找出使模型預測結果相同的最小特徵集合,即如果具備這些特徵,模型的預測結果將會保持不變。
使用CEM進行對比式解釋
CEM(Contrastive Explanation Method)是一種用於生成對比式解釋的方法,可以用於解釋深度學習模型的預測結果。下面是使用CEM進行對比式解釋的步驟:
- 資料準備:準備需要進行解釋的資料集,例如MNIST手寫數字資料集或IRIS資料集。
- 模型訓練:訓練一個深度學習模型,例如卷積神經網路(CNN)或全連線網路(Dense),用於對資料集進行分類別。
- CEM初始化:初始化CEM直譯器,設定相關引數,例如
mode、shape、kappa、beta、gamma等。 - 生成解釋:使用CEM直譯器生成對比式解釋,包括Pertinent Negative和Pertinent Positive解釋。
MNIST資料集的CEM解釋
mode = 'PN' # 'PN' (pertinent negative) 或 'PP' (pertinent positive)
shape = (1,) + x_train.shape[1:] # 例項形狀
kappa = 0. # 原始例項預測類別與擾動例項預測類別之間所需的最小差異
beta = .1 # L1損失項的權重
gamma = 100 # 自動編碼器損失項的權重
c_init = 1. # 鼓勵預測不同類別的損失項的初始權重
c_steps = 10 # c的更新次數
max_iterations = 1000 # 每個c值的迭代次數
feature_range = (x_train.min(), x_train.max()) # 擾動例項的特徵範圍
clip = (-1000., 1000.) # 梯度裁剪
lr = 1e-2 # 初始學習率
no_info_val = -1. # 一個值(浮點數或特徵級),可視為不包含任何資訊以進行預測
# 初始化CEM直譯器並解釋例項
cem = CEM(cnn, mode, shape, kappa=kappa, beta=beta, feature_range=feature_range, gamma=gamma, ae_model=ae, max_iterations=max_iterations, c_init=c_init, c_steps=c_steps, learning_rate_init=lr, clip=clip, no_info_val=no_info_val)
explanation = cem.explain(X)
print(f'Pertinent negative prediction: {explanation.PN_pred}')
plt.imshow(explanation.PN.reshape(28, 28))
IRIS資料集的CEM解釋
import tensorflow as tf
from tensorflow.keras.layers import Dense, Input
from tensorflow.keras.models import Model
from alibi.explainers import CEM
# 載入IRIS資料集
dataset = load_iris()
feature_names = dataset.feature_names
class_names = list(dataset.target_names)
# 資料縮放
dataset.data = (dataset.data - dataset.data.mean(axis=0)) / dataset.data.std(axis=0)
# 分割訓練和測試資料集
idx = 145
x_train, y_train = dataset.data[:idx, :], dataset.target[:idx]
x_test, y_test = dataset.data[idx+1:, :], dataset.target[idx+1:]
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)
# 建立神經網路模型
input_shape = x_train.shape[1:]
inputs = Input(shape=input_shape)
x = Dense(20, activation='relu')(inputs)
outputs = Dense(3, activation='softmax')(x)
model = Model(inputs=inputs, outputs=outputs)
# 編譯模型
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
# 初始化CEM直譯器並解釋例項
cem = CEM(model, mode='PN', shape=(1,) + input_shape)
explanation = cem.explain(x_test[0])
結果分析
透過CEM生成的對比式解釋,可以幫助我們理解模型的決策過程。例如,在MNIST資料集中,Pertinent Negative解釋可以告訴我們哪些畫素點的缺失會導致模型將數字5誤分類別為數字8。Pertinent Positive解釋可以告訴我們哪些畫素點的存在是模型將數字5正確分類別的關鍵。
在IRIS資料集中,CEM可以幫助我們理解哪些特徵對於模型的預測結果最為重要。
對比式解釋在機器學習中的應用
本章節將探討如何使用對比式解釋(Contrastive Explanation)來闡述機器學習模型的預測結果。對比式解釋是一種能夠提供模型預測的正反兩面理由的方法,分別是正向相關(Pertinent Positive)和負向相關(Pertinent Negative)。
邏輯迴歸模型的建立與訓練
首先,我們使用Iris資料集建立了一個簡單的邏輯迴歸模型。模型的輸入層有4個神經元,輸出層有3個神經元,使用softmax啟用函式。模型的損失函式為交叉熵,最佳化器為隨機梯度下降(SGD)。
def lr_model():
x_in = Input(shape=(4,))
x_out = Dense(3, activation='softmax')(x_in)
lr = Model(inputs=x_in, outputs=x_out)
lr.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])
return lr
lr = lr_model()
lr.summary()
lr.fit(x_train, y_train, batch_size=16, epochs=500, verbose=0)
lr.save('iris_lr.h5', save_format='h5')
內容解密:
lr_model函式定義了一個邏輯迴歸模型,輸入層形狀為(4,),輸出層使用softmax啟用函式進行三分類別。- 模型使用交叉熵作為損失函式,SGD作為最佳化器,並監控準確率。
- 訓練模型時,批次大小設為16,迭代次數為500。
- 訓練完成後,模型被儲存為
iris_lr.h5檔案。
使用CEM進行對比式解釋
接下來,我們使用CEM(Contrastive Explanation Method)對模型的預測結果進行解釋。CEM是一種能夠提供正向和負向相關特徵的方法,能夠幫助我們理解模型為什麼做出某個預測。
idx = 0
X = x_test[idx].reshape((1,) + x_test[idx].shape)
cem = CEM(lr, mode='PN', shape=(1, 4), kappa=0.2, beta=0.1, feature_range=(x_train.min(axis=0)-0.1, x_train.max(axis=0)+0.1))
cem.fit(x_train, no_info_type='median')
explanation = cem.explain(X, verbose=False)
內容解密:
- 選取測試集中的第一個例項進行解釋。
- 初始化CEM直譯器,模式設為’PN’(負向相關),並設定相關超引數。
- 使用訓練集擬合CEM直譯器,並定義無資訊特徵的取值範圍為中位數。
- 對選定的例項進行解釋。
結果呈現與視覺化
最後,我們將CEM的解釋結果進行視覺化,以直觀地展示正向和負向相關特徵。
expl = {}
expl['PN'] = explanation.PN
expl['PN_pred'] = explanation.PN_pred
expl['PP'] = explanation.PP
expl['PP_pred'] = explanation.PP_pred
df = pd.DataFrame(dataset.data, columns=dataset.feature_names)
df['species'] = np.array([dataset.target_names[i] for i in dataset.target])
pn = pd.DataFrame(expl['PN'], columns=dataset.feature_names)
pn['species'] = 'PN_' + class_names[expl['PN_pred']]
pp = pd.DataFrame(expl['PP'], columns=dataset.feature_names)
pp['species'] = 'PP_' + class_names[expl['PP_pred']]
orig_inst = pd.DataFrame(explanation.X, columns=dataset.feature_names)
orig_inst['species'] = 'orig_' + class_names[explanation.X_pred]
df = df.append([pn, pp, orig_inst], ignore_index=True)
fig = sns.pairplot(df, hue='species', diag_kind='hist')
內容解密:
- 將CEM的解釋結果(正向和負向相關特徵)儲存在
expl字典中。 - 將原始資料、負向相關特徵、正向相關特徵和原始例項合併成一個DataFrame。
- 使用Seaborn的pairplot函式進行視覺化,以展示不同特徵之間的關係。
模型無關解釋:識別預測不變性
在數學領域中,不變性的概念用於描述當解釋變數受到干預時,機器學習模型的預測結果保持不變的情況,這是根據模型透過正式的因果關係生成的。機器學習模型可以分為因果模型和非因果模型。因果模型顯示了回應變數與解釋變數之間真正的因果關係,而非因果模型則顯示了偶然的關係;後者的預測結果可能會發生變化。理解這兩種模型之間差異的唯一方法是透過解釋。在本章中,我們將使用一個名為 Alibi 的 Python 函式庫來生成模型無關的解釋。
什麼是模型無關?
模型無關意味著模型獨立。無論模型型別如何,對於機器學習模型的解釋都是有效的。當我們解釋機器學習模型的內在行為時,通常不會假設模型本身所顯示的行為具有任何底層結構。在本章中,我們將使用模型無關的解釋來描述預測不變性。一直以來,人們很難理解機器學習模型的工作原理。人們總是想知道並詢問有關機器學習模型行為的問題。為了理解模型的無關行為,人類總是認為他們可以對模型的行為做出預測。
什麼是錨點?
複雜的模型通常被視為黑箱模型,因為很難理解為什麼會做出某個預測。錨點的概念其實就是找出規則。這裡的規則是指能夠解釋模型行為的高精確度規則,同時考慮到區域性和全域性因素。換句話說,錨點是 if/then/else 條件,無論其他特徵的值如何,都能錨定預測結果。錨點演算法建立在模型無關解釋的基礎上,具有三個核心功能:
- 覆寫率:這意味著人們可以改變框架以預測機器學習模型行為的頻率。
- 精確度:這意味著人類預測模型行為的準確程度。
- 努力程度:這意味著解釋模型行為或理解模型行為所產生的預測結果所需的初始努力。兩種情況都很難解釋。
使用 Alibi 進行錨點解釋
為了為黑箱模型生成錨點解釋,我們將使用 Python 函式庫 Alibi。以下指令碼顯示瞭解釋該概念所需的匯入陳述式。我們將使用隨機森林分類別器,這也是一種黑箱模型,因為有多棵樹生成預測結果,並且這些預測結果被彙總以產生最終輸出。
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from alibi.explainers import AnchorTabular
from alibi.datasets import fetch_adult
內容解密:
import numpy as np:匯入 NumPy 函式庫,用於數值計算。import pandas as pd:匯入 Pandas 函式庫,用於資料處理。from sklearn.ensemble import RandomForestClassifier:從 Scikit-learn 匯入隨機森林分類別器,用於建立分類別模型。from alibi.explainers import AnchorTabular:從 Alibi 函式庫匯入錨點表格直譯器,用於生成錨點解釋。
Alibi 函式庫具有多個資料集,可用於生成範例來解釋該概念。這裡我們將使用成人資料集,也稱為人口普查收入資料集,可從 UCI 機器學習儲存函式庫獲得。這是一個二元分類別模型的範例。有多個特徵可用於預測收入類別是否超過 5 萬美元。
adult = fetch_adult()
adult.keys()
data = adult.data
target = adult.target
feature_names = adult.feature_names
category_map = adult.category_map
內容解密:
adult = fetch_adult():從 Alibi 函式庫取得成人資料集。adult.keys():顯示資料集的鍵值,包括 ‘data’、’target’、‘feature_names’、’target_names’ 和 ‘category_map’。data = adult.data:將資料集的特徵指定給data變數。category_map = adult.category_map:將類別對映指定給category_map變數,用於對映類別型欄位。
在訓練模型之前,我們需要對資料進行隨機化處理,並使用 33,000 筆記錄進行模型訓練,2,560 筆記錄進行模型測試或驗證。
np.random.seed(0)
data_perm = np.random.permutation(np.c_[data, target])
data = data_perm[:,:-1]
target = data_perm[:,-1]
idx = 30000
X_train, Y_train = data[:idx,:], target[:idx]
X_test, Y_test = data[idx+1:,:], target[idx+1:]
內容解密:
np.random.seed(0):設定隨機種子,以確保結果的可重現性。data_perm = np.random.permutation(np.c_[data, target]):將資料和目標變數合併後進行隨機排列。X_train, Y_train = data[:idx,:], target[:idx]:將資料分割為訓練集和測試集。
選擇序數特徵後,可以套用序數特徵轉換器,該轉換器由管線觸發。
ordinal_features = [x for x in range(len(feature_names)) if x not in list(category_map.keys())]
ordinal_transformer = Pipeline(steps=[('imputer', SimpleImputer(strategy='median')), ('scaler', StandardScaler())])
categorical_features = list(category_map.keys())
categorical_transformer = Pipeline(steps=[('imputer', SimpleImputer(strategy='median')), ('onehot', OneHotEncoder(handle_unknown='ignore'))])
preprocessor = ColumnTransformer(transformers=[('num', ordinal_transformer, ordinal_features), ('cat', categorical_transformer, categorical_features)])
內容解密:
ordinal_features = [x for x in range(len(feature_names)) if x not in list(category_map.keys())]:選擇序數特徵,即不在類別對映中的特徵。ordinal_transformer = Pipeline(steps=[('imputer', SimpleImputer(strategy='median')), ('scaler', StandardScaler())]):建立序數特徵轉換器管線,包括缺失值填補和標準化縮放。categorical_transformer = Pipeline(steps=[('imputer', SimpleImputer(strategy='median')), ('onehot', OneHotEncoder(handle_unknown='ignore'))]):建立類別型特徵轉換器管線,包括缺失值填補和獨熱編碼。
綜上所述,本章節介紹瞭如何使用 Alibi 函式庫生成模型無關的解釋,並透過錨點演算法來描述預測不變性。同時,也展示瞭如何使用 Python 程式碼來實作這些功能,包括資料處理、模型訓練和錨點解釋的生成。