R與機器學習系列|15.可解釋的機器學習算法(Interpretable Machine Learning)(中)

在上次推文中我們介紹了幾種可解釋機器學習算法的常見方法,包括置換特征重要性、偏依賴圖和個體條件期望及其實現。本次我們將繼續介紹其他的用來解釋機器學習算法的方法。

1.特征交互(Feature interactions)

1.1介紹

在機器學習中,Feature Interactions(特征交互)是指不同特征之間的相互作用或聯合效應。特征交互可以幫助我們更好地理解數據,發現特征之間的復雜關系,以及提高機器學習模型的性能。當預測模型中的特征之間存在交互作用時,特征對預測結果的影響不是簡單的加和,而是更為復雜。在現實生活中,大多數特征與某些響應變量之間的關系都是復雜的,包括交互作用。這也是為什么更復雜的算法(尤其是基于樹的算法)往往表現得非常好的原因——它們的復雜性通常能夠自然地捕捉復雜的交互作用。然而,識別和理解這些交互作用較為困難的。

估計交互作用強度的一種方法是衡量預測結果的變化有多少取決于特征之間的交互作用。這種衡量稱為H統計量,由Friedman、Popescu等人在2008年提出。

特征交互通常在以下兩個方面進行考慮:

  1. 特征之間的組合效應:某些特征組合在一起可能具有比它們單獨使用更強的預測能力。例如,對于預測房價的問題,房屋的面積和地理位置可能單獨對房價的預測有一定的影響,但將它們組合在一起可能會得到更準確的預測結果。

  2. 特征之間的相互作用:某些特征之間可能存在非線性相互作用,即它們的組合效果不是簡單的加和關系。例如,對于預測用戶購買行為的問題,用戶的年齡和購買頻率可能存在相互作用,即不同年齡段的用戶在購買頻率上表現不同。

1.2實施

目前,H統計量的計算僅可以通過iml包實現。我們可以使用Interaction$new()來計算單向交互作用,以評估兩個特定特征在模型中如何相互作用,并且強度如何。

不幸的是,由于算法的復雜性,H統計量需要進行2n^2次運行,因此計算非常耗時。例如,計算單向交互作用的H統計量需要花費兩個小時的時間!在這種情況下,我們可以通過在iml包中減少grid.size或使用parallel = TRUE進行并行計算來加速計算。
這里為了示例,小編僅使用示例數據中的幾個特征演示一下這一部分(運行時間真的太長了,所以就只選幾個變量)

# 加載依賴包
library(dplyr)      #數據操縱
library(ggplot2)    # 可視化

# Modeling packages
library(h2o)       # H2O
library(recipes)   # 機器學習藍圖
library(rsample)   # 數據分割
library(xgboost)   # 擬合GBM模型

# 模型可解釋性包
library(pdp)       # 偏依賴圖及ICE曲線繪制
library(vip)       # 變量重要性VIP圖
library(iml)       # 普遍IML相關函數
library(DALEX)     # 普遍IML相關函數
# devtools::install_github('thomasp85/lime')
library(lime)      # 局部可解釋模型無關解釋
load("inputdata.Rda")#加載示例數據
inputdata<-inputdata[,-1]
inputdata$Event<-factor(inputdata$Event,levels = c(0,1),labels = c("Alive","Death"))#結局變量因子化
set.seed(123)  # 設置隨機種子保證可重復性
split <- initial_split(inputdata, strata = "Event")#數據分割
data_train <- training(split)
data_test <- testing(split)

我們這里按照Interaction {iml}示例,使用示例數據擬合一個分類任務的CART算法

library("rpart")
set.seed(42)
data<-data_train[,1:10]
rf<-rpart(Event~.,data=data)
mod <- Predictor$new(rf, data =data, type = "prob")

# For some models we have to specify additional arguments for the
# predict function
ia <- Interaction$new(mod)

接下來我們對交互作用降序排列

ia$results %>% 
  arrange(desc(.interaction)) %>% 
  head()
# .feature .class .interaction
# 1:  AADACP1  Death    0.6121357
# 2:  AADACP1  Alive    0.6121357
# 3:     AAAS  Alive    0.6038541
# 4:     AAAS  Death    0.6038541
# 5:    AAGAB  Alive    0.5892189
# 6:    AAGAB  Death    0.5892189

可以進一步使用plot函數將結果可視化出來

plot(ia)

在確定了具有最強交互作用的變量后,我們可以計算h統計量,以確定它主要與哪些特征存在交互作用。我們可以看到AAGAB和AADAT之間有較強的交互作用。

interact_2way <- Interaction$new(mod, feature = "AAGAB")
interact_2way$results %>% 
  arrange(desc(.interaction)) %>% 
  top_n(10)
Selecting by .interaction
# .feature .class .interaction
# 1:   AADAT:AAGAB  Alive    0.4992814
# 2:   AADAT:AAGAB  Death    0.4992814
# 3:    AACS:AAGAB  Death    0.2733772
# 4:    AACS:AAGAB  Alive    0.2733772
# 5: AADACP1:AAGAB  Alive    0.2707731
# 6: AADACP1:AAGAB  Death    0.2707731
# 7:    AAAS:AAGAB  Death    0.2669400
# 8:    AAAS:AAGAB  Alive    0.2669400
# 9:     A2M:AAGAB  Alive    0.1190083
# 10:     A2M:AAGAB  Death    0.1190083

識別這些交互作用可以幫助我們了解它們與響應變量的關系。我們可以使用PDPs或ICE曲線來觀察交互作用對預測結果的影響。我們可以看下上面步驟發現的兩個交互作用比較強的變量如何影響結局事件的預測。

# Two-way PDP using iml
interaction_pdp <- Partial$new(
  mod, 
  c("AAGAB", "AADAT"), 
  ice = FALSE, 
  grid.size = 20
) 
plot(interaction_pdp)

1.3其他可供選擇方法

顯然,計算時間是確定潛在交互效應的主要限制因素,因為這個過程會花費很長的計算時間。盡管 H 統計量是檢測交互作用的方法中最具統計學意義的方法,但還有其他選擇。在Brandon M Greenwell, Boehmke和McCarthy (2018)中討論的基于PDP的變量重要性測量也可以用于量化潛在交互效應的強度,可以通過vip::vint()實現。

2.局部可解釋模型無關解釋(Local interpretable model-agnostic explanations)

2.1介紹

機器學習中的局部可解釋模型無關解釋(Local Interpretable Model-Agnostic Explanations,LIME)是一種用于解釋機器學習模型預測的方法。LIME的目標是在特定樣本附近構建一個局部線性模型來近似原始模型的預測結果,并解釋該局部模型的系數以得到對預測的解釋。

LIME的基本思想是通過生成一組“虛擬樣本”,這些虛擬樣本是原始樣本在特征空間中的近似,然后利用這些虛擬樣本來訓練一個局部線性模型。在構建局部模型時,LIME使用一種稱為“稀疏線性模型”的方法,這是一種可以解釋性較好的線性模型。通過解釋稀疏線性模型的系數,我們可以得到對預測的解釋,即哪些特征對于模型的預測起到了關鍵作用。

LIME的優點是可以應用于任何類型的機器學習模型,而不僅限于特定類型的模型。它還可以在不需要訪問原始模型的內部結構的情況下解釋模型的預測結果,因此被稱為“模型無關”的解釋方法。

然而,LIME也有一些局限性。首先,由于LIME是在局部構建模型,所以解釋的可信度可能會受到局部數據分布的影響。其次,LIME的解釋是基于稀疏線性模型的,可能會丟失一些復雜模型的細節。因此,在使用LIME時,需要仔細考慮其解釋的適用范圍和可信度。

LIME所應用的一般算法如下:

  1. 對訓練數據進行置換以創建復制的特征數據,這些數據的值可能有輕微修改。
  2. 計算感興趣觀測值與每個置換觀測值之間的接近度度量(例如,1 - 距離)。
  3. 使用選定的機器學習模型預測置換數據的結局。
  4. 選擇 m 個特征來最好地描述預測結果。
  5. 對置換數據擬合一個簡單模型,用 m 個特征來解釋復雜模型的結局,并根據其與原始觀測值的相似性進行加權。
  6. 使用得到的特征權重來解釋局部行為。

2.2實施

以上過程可以通過lime包實現,主要涉及兩個過程:lime::lime()和lime::explain()。lime::lime()函數用于創建一個"explainer"對象,它是一個包含已擬合的機器學習模型和訓練數據特征分布的列表。其中包含的特征分布包括每個分類變量水平和每個連續變量分為n個箱子(當前默認為四個箱子)的分布統計。這些特征屬性將用于對數據進行置換。
首先我們根據前面的堆疊算法先生成一個堆疊模型

#訓練一個堆疊模型(見機器學習系列堆疊算法)
ensemble_tree <- h2o.stackedEnsemble(
  x = X, y = Y, training_frame = train_h2o, model_id = "my_tree_ensemble",
  base_models = list(best_glm, best_rf, best_gbm,best_nb,best_nn),
  metalearner_algorithm = "drf"
)

接著提取特征

features<-data_train%>%select(-Event)

使用lime函數基于堆疊算法模型和特征創建一個解釋器

# Create explainer object
components_lime <- lime(
  x = features,
  model = ensemble_tree, 
  n_bins = 10
)

class(components_lime)
## [1] "data_frame_explainer" "explainer"            "list"
# Length Class            Mode     
# model                  1    H2OBinomialModel S4       
# preprocess             1    -none-           function 
# bin_continuous         1    -none-           logical  
# n_bins                 1    -none-           numeric  
# quantile_bins          1    -none-           logical  
# use_density            1    -none-           logical  
# feature_type         101    -none-           character
# bin_cuts             101    -none-           list     
# feature_distribution 101    -none-           list     

然后我們在驗證集數據中選擇兩個對象,基于他們的特征來解釋模型

lime_explanation <- lime::explain(
  x =data_new, 
  explainer = components_lime, 
  n_permutations = 5000,
  dist_fun = "gower",
  kernel_width = 0.25,
  n_labels = 2,
  n_features = 10, 
  feature_select = "highest_weights"
)

lime::explain()函數的主要參數及意義如下:

x:要為其創建局部解釋的觀察值。
explainer:采用由lime::lime()創建的解釋器對象,將用于創建置換數據。置換是從lime::lime()解釋器對象創建的變量分布中采樣得到的。
n_permutations:為x中的每個觀察值創建的置換數(默認為5000)。
dist_fun:要使用的距離函數。默認為Gower距離,但也可以使用Euclidean、Manhattan或dist()函數允許的任何其他距離函數。為了計算相似性,分類特征將根據它們是否等于實際觀察值進行重新編碼。如果連續特征被分箱(默認值),則這些特征將根據它們是否與要解釋的觀察值在同一個箱中進行重新編碼。然后,使用重新編碼的數據計算到原始觀察值的距離。
kernel_width:為了將距離度量轉換為相似度得分,使用用戶定義的寬度的指數核(默認為特征數的0.75倍的平方根)。
n_features:最能描述預測結果的特征數。
feature_select:lime::lime()可以使用前向選擇、嶺回歸、LASSO或決策樹來選擇“最佳”的n_features特征。
對于分類模型,我們需要指定一些額外的參數:
labels:要解釋的特定標簽(類)(例如,0/1,“是”/“否”)?
n_labels:要解釋的標簽數。

如果原始的機器學習模型是回歸模型,局部模型將直接預測復雜模型的輸出結果。如果是分類器,局部模型將預測所選擇類別的概率。
通過lime::explain()函數得到的輸出是一個包含各種信息的數據框,用于描述局部模型的預測結果。其中最重要的信息是對于每個提供的觀測值,它包含了擬合的解釋模型 (model_r2) 和每個重要特征 (feature_desc) 的加權重要性 (feature_weight),用于最佳描述局部關系。

glimpse(lime_explanation)
# Rows: 40
# Columns: 13
# $ model_type       <chr> "classification", "classification", "classification", "classification", "classification~
# $ case             <chr> "TCGA-D5-6530", "TCGA-D5-6530", "TCGA-D5-6530", "TCGA-D5-6530", "TCGA-D5-6530", "TCGA-D~
#   $ label            <chr> "Alive", "Alive", "Alive", "Alive", "Alive", "Alive", "Alive", "Alive", "Alive", "Alive~
# $ label_prob       <dbl> 0.99, 0.99, 0.99, 0.99, 0.99, 0.99, 0.99, 0.99, 0.99, 0.99, 0.01, 0.01, 0.01, 0.01, 0.0~
# $ model_r2         <dbl> 0.01444325, 0.01444325, 0.01444325, 0.01444325, 0.01444325, 0.01444325, 0.01444325, 0.0~
# $ model_intercept  <dbl> 0.7045399, 0.7045399, 0.7045399, 0.7045399, 0.7045399, 0.7045399, 0.7045399, 0.7045399,~
# $ model_prediction <dbl> 0.7756461, 0.7756461, 0.7756461, 0.7756461, 0.7756461, 0.7756461, 0.7756461, 0.7756461,~
# $ feature          <chr> "ABCA1", "ABCC4", "ABHD3", "AAMP", "ABHD2", "ABCG1", "ABCG2", "ABCD3", "AC000111.2", "A~
#   $ feature_value    <dbl> 1.4922773, 0.8637574, 3.8144376, 6.1803265, 4.3477301, 2.2083119, 0.2595689, 3.2786676,~
#   $ feature_weight   <dbl> 0.02450017, -0.02491953, -0.02346769, 0.02196452, 0.02330070, 0.01894933, -0.01702930, ~
#   $ feature_desc     <chr> "1.475 < ABCA1 <= 1.642", "ABCC4 <= 1.17", "3.66 < ABHD3 <= 3.92", "6.17 < AAMP", "4.29~
# $ data             <list> [1.041423, 4.595776, 1.484305, 3.626439, 2.718439, 0.09743433, 0.594286, 1.95217, 3.91~
# $ prediction       <list> [0.99, 0.01], [0.99, 0.01], [0.99, 0.01], [0.99, 0.01], [0.99, 0.01], [0.99, 0.01], [0~

我們看看可視化的結果。然而,需要注意模型的低R2(“解釋適配度”)。局部模型的擬合效果似乎相當差,因此我們不應過于依賴這些解釋。

plot_features(lime_explanation, ncol =2)

2.3參數調整

在執行LIME(局部解釋性模型)時,我們可以調整幾個參數,將它們視為調參參數,這樣可以嘗試調整局部模型。這有助于最大程度地增加局部解釋性模型的可信性。

#LIME算法調參
lime_explanation2 <- explain(
  x =data_new, 
  explainer = components_lime, 
  n_permutations = 5000,
  dist_fun = "euclidean",
  kernel_width = 0.75,
  n_labels = 2,
  n_features = 10, 
  feature_select = "lasso_path"
)

#可視化結果
plot_features(lime_explanation2, ncol = 2)

在上面的調參過程中,我們將距離函數更改為歐幾里得距離,增加了核寬度以創建更大的局部區域,并將特征選擇方法改為基于LARS的LASSO模型。

2.4其他可供選擇的方法

上面的示例我們主要圍繞在表格數據集中使用LIME進行解釋性模型的構建。然而,LIME也可以應用于非傳統數據集,例如文本和圖像。對于文本數據,LIME會創建一個包含擾動文本的新的文檔-詞矩陣(例如,它會基于現有文本生成新的短語和句子)。然后,LIME會按照類似的步驟對生成的文本與原始文本的相似性進行加權。局部模型然后幫助確定在擾動文本中哪些詞語產生了最強的信號。

對于圖像數據,LIME會通過用一個常量顏色(例如灰色)替換某些像素組合來創建圖像的變體。然后,LIME會評估給定未擾動像素組的預測標簽。

3.SHAP值

3.1背景

SHAP(SHapley Additive exPlanations)是一種解釋機器學習模型預測的方法,它基于合作博弈理論中的Shapley值概念。SHAP通過計算每個特征對于模型預測輸出的貢獻,幫助我們理解模型預測的原因和解釋。

在機器學習中,模型預測的輸出往往由多個特征共同決定。SHAP通過考慮每個特征值與其他特征值之間的交互作用,將模型預測的總體變化分配給每個特征。這樣,我們可以了解每個特征對于模型輸出的相對重要性,以及特征之間的相互作用對預測的影響。

SHAP值具有以下特點:

  1. 公平性:SHAP值確保在所有可能的特征子集中,特征的貢獻是公平的,不受其他特征的影響。
  2. 一致性:SHAP值滿足Shapley值的一致性屬性,即如果兩個模型預測相同,但是特征值不同,那么它們的SHAP值應該相同。
  3. 局部解釋性:SHAP值提供了對于單個樣本的局部解釋,即了解某個特定樣本的預測結果是由哪些特征貢獻決定的。

在之前的推文中我們介紹了R和Python中SHAP值的可視化過程,當然也包括生存數據的SHAP值可視化。在這次的示例中我們將一起學習如何通過iml包實現SHAP值的可視化。

#SHAP
#提取特征
features <- as.data.frame(train_h2o) %>% select(-Event)

#提取響應變量
response <- as.data.frame(train_h2o) %>% pull(Event)

#自定義函數
pred <- function(object, newdata)  {
  results <- as.vector(h2o.predict(object, as.h2o(newdata)))
  return(results)
}

#創建一個iml模型無關對象
components_iml <- Predictor$new(
  model = ensemble_tree, 
  data = features, 
  y = response, 
  predict.fun = pred
)
#計算SHAP值
(shapley <- Shapley$new(components_iml, x.interest =data_new, sample.size =1000))
# |========================================================================================================| 100%
# |========================================================================================================| 100%
# |========================================================================================================| 100%
# |========================================================================================================| 100%
# |========================================================================================================| 100%
# |========================================================================================================| 100%
# Interpretation method:  Shapley 
# Predicted value: 0.980000, Average prediction: 0.703570 (diff = 0.276430) Predicted value: 0.020000, Average prediction: 0.296430 (diff = -0.276430)
# 
# Analysed predictor: 
#   Prediction task: unknown 
# 
# 
# Analysed data:
#   Sampling from data.frame with 338 rows and 101 columns.
# 
# 
# Head of results:
#   feature class           phi     phi.var            feature.value
# 1    A1CF Alive  0.0017600000 0.006776857    A1CF=1.04142313260927
# 2     A2M Alive -0.0016233333 0.001454914     A2M=4.59577575137959
# 3  A4GALT Alive -0.0028233333 0.002947425  A4GALT=1.48430469549071
# 4    AAAS Alive -0.0008516667 0.005436699    AAAS=3.62643913669732
# 5    AACS Alive  0.0077550000 0.007041842    AACS=2.71843944462677
# 6   AADAC Alive  0.0004400000 0.002993781 AADAC=0.0974343320963354
#可視化結果
plot(shapley)

上述過程的計算時間主要取決于預測變量的數量和樣本大小。默認情況下,Shapley$new()函數只使用100個樣本,但我們可以通過控制參數來減少計算時間或增加估計值的可信性。

由于iml使用R6,我們可以重復使用Shapley對象來解釋特征對預測結局的影響。

#繼續使用shapley值解釋感興趣的觀測值
shapley$explain(x.interest =data_new)

#可視化結果
shapley$results %>%
  top_n(20, wt = abs(phi)) %>%
  ggplot(aes(phi, reorder(feature.value, phi), color = phi > 0)) +
  geom_point(size=3)+
  scale_color_brewer(palette = "Set2")+
  theme_bw()

今天的分享就到這里了。下次我們將分享XGBoost算法中SHAP值的可視化,也是比較經典的可視化,另外我們將分享最后一個iml方法—Localized step-wise procedure。下次分享后我們的R與機器學習系列推文也就基本到尾聲了,后面的無監督機器學習算法暫時不做重點分享。后續的分享重點將圍繞Python與機器學習系列展開。因為在分享過程中發現R中進行機器學習算法運算時還是比較耗時間、耗內存,尤其是在樣本量很大的情況下,就不得不借助Python了。另外,Python才是機器學習的主流。后續我們將從Python基礎知識逐漸過渡到Python與機器學習系列。歡迎一起學習!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容