使用 lightgbm Tweedie 目标将 SHAP 值从原始单位转换为原生单位?
Posted
技术标签:
【中文标题】使用 lightgbm Tweedie 目标将 SHAP 值从原始单位转换为原生单位?【英文标题】:Transform SHAP values from raw to native units with lightgbm Tweedie objective? 【发布时间】:2021-02-23 20:39:58 【问题描述】:Shapley Additive Explanations(SHAP 值)的用途是了解每个特征如何对模型的预测做出贡献。对于某些目标,例如以 RMSE 作为目标函数的回归,SHAP 值采用标签值的本机单位。例如,如果估算住房成本,SHAP 值可以表示为美元。正如您将在下面看到的,并非所有目标函数都是如此。特别是,Tweedie 回归目标不会产生原生单位的 SHAP 值。这是一个解释问题,因为我们想知道住房成本如何受 +/- 美元的特征影响。
鉴于这些信息,我的问题是:在解释具有 Tweedie 回归目标的模型时,我们如何将每个单独特征的 SHAP 值转换为目标标签的数据空间?
我不知道目前有任何包实现了这种转换。 This remains unresolved in the package put out by the shap authors themselves.
我在下面用 lightgbm 的 R 实现来说明这个问题的细节:
library(tweedie)
library(lightgbm)
set.seed(123)
tweedie_variance_power <- 1.2
labels <- rtweedie(1000, mu = 1, phi = 1, power = tweedie_variance_power)
hist(labels)
feat1 <- labels + rnorm(1000) #good signal for label with some noise
feat2 <-rnorm(1000) #garbage feature
feat3 <-rnorm(1000) #garbage feature
features <- cbind(feat1, feat2, feat3)
dTrain <- lgb.Dataset(data = features,
label = labels)
params <- c(objective = 'tweedie',
tweedie_variance_power = tweedie_variance_power)
mod <- lgb.train(data = dTrain,
params = params,
nrounds = 100)
#Predictions in the native units of the labels
predsNative <- predict(mod, features, rawscore = FALSE)
#Predictions in the raw format
predsRaw <- predict(mod, features, rawscore = TRUE)
#We do not expect these values to be equal
all.equal(predsTrans, predsRaw)
"Mean relative difference: 1.503072"
#We expect values to be equal if raw scores are exponentiated
all.equal(predsTrans, exp(predsRaw))
"TRUE" #... our expectations are correct
#SHAP values
shapNative <- predict(mod, features, rawscore = FALSE, predcontrib = TRUE)
shapRaw <- predict(mod, features, rawscore = TRUE, predcontrib = TRUE )
#Are there differences between shap values when rawscore is TRUE or FALSE?
all.equal(shapNative, shapRaw)
"TRUE" #outputs are identical, that is surprising!
#So are the shap values in raw or native formats?
#To anwser this question we can sum them
#testing raw the raw case first
all.equal(rowSums(shapRaw), predsRaw)
"TRUE"
#from this we can conclude that shap values are not in native units,
#regardless of whether rawscore is TRUE or FALSE
#Test native scores just to prove point
all.equal(rowSums(shapNative), predsNative)
"Mean relative difference: 1.636892" # reaffirms that shap values are not in native units
#However, we can perform this operation on the raw shap scores
#to get the prediction in the native value
all.equal(exp(rowSums(shapRaw)), predsNative)
'TRUE'
#reversing the operations does not yield the same result
all.equal(rowSums(exp(shapRaw)), predsNative)
"Mean relative difference: 0.7662481"
#The last line is relevant because it implies
#The relationship between native predictions
#and exponentiated shap values is not linear
#So, given the point of SHAP is to understand how each
#feature impacts the prediction in its native units
#the raw shap values are not as useful as they could be
#Thus, how how would we convert
#each of these four raw shap value elements to native units,
#thus understanding their contributions to their predictions
#in currency of native units?
shapRaw[1,]
-0.15429227 0.04858757 -0.27715359 -0.48454457
原始发布和编辑
我对 SHAP 值的理解是,它们在进行回归时采用标签/响应的原生单位,并且 SHAP 值的总和近似于模型的预测。
我正在尝试使用 Tweedie 回归目标提取 LightGBM 包中的 SHAP 值,但发现 SHAP 值不是标签的本机单位,并且它们不与预测值相加。
看来它们必须取幂,这样对吗?
旁注:我了解 SHAP 值矩阵的最后一列代表基本预测,必须添加。
可重现的例子:
library(tweedie)
library(caret)
library(lightgbm)
set.seed(123)
tweedie_variance_power <- 1.2
labels <- rtweedie(1000, mu = 1, phi = 1, power = tweedie_variance_power)
hist(labels)
feat1 <- labels + rnorm(1000) #good signal for label with some noise
feat2 <-rnorm(1000) #garbage feature
feat3 <-rnorm(1000) #garbage feature
features <- cbind(feat1, feat2, feat3)
dTrain <- lgb.Dataset(data = features,
label = labels)
params <- c(objective = 'tweedie',
tweedie_variance_power = tweedie_variance_power)
mod <- lgb.train(data = dTrain,
params = params,
nrounds = 100)
preds <- predict(mod, features)
plot(preds, labels,
main = paste('RMSE =',
RMSE(pred = preds, obs = labels)))
#shap values are summing to negative values?
shap_vals <- predict(mod, features, predcontrib = TRUE, rawscore = FALSE)
shaps_sum <- rowSums(shap_vals)
plot(shaps_sum, labels,
main = paste('RMSE =',
RMSE(pred = shaps_sum, obs = labels)))
#maybe we need to exponentiate?
shap_vals_exp <- exp(shap_vals)
shap_vals_exp_sum <- rowSums(shap_vals_exp)
#still looks a little weird, overpredicting
plot(shap_vals_exp_sum, labels,
main = paste('RMSE =',
RMSE(pred = shap_vals_exp_sum, obs = labels)))
编辑
操作的顺序是先求和,然后对 SHAP 值求幂,这将为您提供本机单位的预测。虽然我仍然不清楚如何将特征级别值转换为原生响应单元。
shap_vals_sum_exp <- exp(shaps_sum)
plot(shap_vals_sum_exp, labels,
main = paste('RMSE =',
RMSE(pred = shap_vals_sum_exp, obs = labels)))
【问题讨论】:
【参考方案1】:我将展示如何在 Python 中协调 shap 值和模型预测,包括原始分数和原始单位。希望它能帮助您了解您在 R 中的位置。
步骤 1. 生成数据集
# pip install tweedie
import tweedie
y = tweedie.tweedie(1.2,1,1).rvs(size=1000)
X = np.random.randn(1000,3)
第 2 步。拟合模型
from lightgbm.sklearn import LGBMRegressor
lgb = LGBMRegressor(objective = 'tweedie')
lgb.fit(X,y)
第 3 步。了解什么是 shap 值。
第 0 个数据点的形状值
shap_values = lgb.predict(X, pred_contrib=True)
shap_values[0]
array([ 0.36841812, -0.15985678, 0.28910617, -0.27317984])
前 3 个是模型对基线的贡献,即 shap 值本身:
shap_values[0,:3].sum()
0.4976675073764354
第四个是原始分数的基线:
shap_values[0,3]
-0.2731798364061747
它们的总和加起来就是原始分数中的模型预测:
shap_values[0,:3].sum() + shap_values[0,3]
0.22448767097026068
让我们检查原始模型预测:
preds = lgb.predict(X, raw_score=True)
preds[0]
0.2244876709702609
编辑。原始分数与原始单位之间的转换
要在 Tweedie(以及 Poisson 和 Gamma)分布的原始分数和原始单位之间进行转换,您需要了解 2 个事实:
-
原文是
exp
的raw
exp
的 sum
是 product
的 exps
演示:
-
原始单位的第 0 个预测:
lgb.predict([X[0,:]])
array([0.39394102])
-
原始分数空间中第 0 行的形状值:
shap_values = lgb.predict(X, pred_contrib=True, raw_score=True)
shap_values[0]
array([-0.77194274, -0.08343294, 0.22740536, -0.30358374])
-
将 shap 值转换为原始单位(指数乘积):
np.prod(np.exp(shap_values[0]))
0.3939410249402226
又和我很像了。
【讨论】:
感谢您的贡献。虽然您提供的方法描述了如何提取目标函数单位的 SHAP 值(对数似然),但这些值不在标签的本机单位中。从那以后,我了解到转换回本机单位并不简单,在这里进一步讨论:github.com/slundberg/shap/pull/1041 你能澄清一下你的问题到底是什么吗?我认为您在协调 shap 值与预测时遇到了困难。我向你展示了如何在原始分数空间中做到这一点。但你不接受答案。为什么?您在将原始分数转换为原始单位时遇到困难吗?另请注意,这是一个回归。对数似然无关紧要。 问题是原始分数空间不是您在答案中描述的 y 单位(我称之为本机)。目标是以您在步骤 1 中描述的 y 为单位提取每个特征的 SHAP 值,以便它们与以 y 为单位的预测值相加。 @kdoherty 请参阅编辑 我向您展示了两种方法:原始乐谱和原创乐谱。小数点后第15位数字相同以上是关于使用 lightgbm Tweedie 目标将 SHAP 值从原始单位转换为原生单位?的主要内容,如果未能解决你的问题,请参考以下文章