pretty.gbm.tree 中 gbm 单树预测的解释

机器算法验证 r 解释 助推
2022-03-07 17:11:37

我无法弄清楚如何从经过训练的带有损失函数的二元结果中解释Predictionpretty.gbm.tree单个树上调用的结果。我正在使用v2.1.1。gbmbernoulligbm

例子

data('ptitanic', package='rpart.plot') # note this is not the default data(Titanic)
ptitanic$died <- 2-as.integer(ptitanic$survived) #survived is fctr w/ 2 levels died/survived
mean(ptitanic$died) # 0.618 death rate
form <- as.formula('died ~ sex + age + pclass + sibsp + parch')

library('gbm')
set.seed(1)
m <- gbm(form,
         distribution = 'bernoulli',
         data = ptitanic,
         interaction.depth=4,
         n.trees=50)
summary(m)

mean(predict(m, ptitanic, type='response',n.trees=50)) # 0.618 death rate

# let's look at the 1st tree
t <- pretty.gbm.tree(m, i=1)
# I want to see the split variable names instead of indices 
# The indices are -1 for terminal, 0 for first term, 1 for second term, etc.
t$SplitVar <- c('Terminal',attr(terms(form),'term.labels'))[t$SplitVar+2]
# The predictions at nodes look like:
head(t$Prediction)
# [1] -2.066845e-05 -1.472631e-03 -2.374948e-03 -4.808952e-04 -1.472631e-03  7.829118e-04

我试过的:

根据?predict.gbm,该函数将返回一个对数赔率向量

返回预测向量。默认情况下,预测在 f(x) 的范围内。例如,对于伯努利损失,返回值是对数赔率标度,...

因此,Prediction树中的似乎应该是对数赔率,我应该能够通过以下方式获得概率估计:

x=lnp1p

p=11ex+1

IE:

t$OR <- exp(t$Prediction)
t$Prob <- 1/(1/t$OR + 1)
head(t$Prob)  
#[1] 0.5000094 0.4996384 0.4994387 0.4998654 0.4996384 0.5002175

非常奇怪的是,根节点的优势比约为 1,或 p = 0.5——尽管上面提到的总体死亡率为 61.8%。所以也许它是想告诉我相对风险?

有一个有点神秘的细节?predict.gbm

gbm 的预测不包括偏移项。如果需要,用户可以将偏移值添加到预测值。

在查看第一棵树时,我需要添加偏移量吗?(我可能理解需要在后续的树中做加法效果,但第一个?)如果是这样,我该怎么做?

1个回答

关于 gbm 算法的工作原理,您缺少一个微妙之处,这会导致您感到困惑。

predict方法从整个提升模型返回预测,在拟合以最小化伯努利偏差时,这些确实是对数几率。另一方面,来自单个树的预测不是对数赔率,它们是完全不同的东西。

事实上,虽然整个模型总体上适合预测响应,但单个树不适合,单个树适合预测在当前预测和响应中评估的损失函数的梯度这是“梯度提升”的“梯度”部分。

这是一个最小的例子,希望能澄清发生了什么,我将使用一个最小化高斯损失函数的助推器来保持数学简单并专注于重要的概念。

x <- seq(0, 1, length.out = 6)
y <- c(0, 0, 0, 1, 1, 1)
df <- data.frame(x = x, y = y)

M <- gbm(y ~ x, data = df, 
         distribution="gaussian",
         n.trees = 1,
         bag.fraction = 1.0, n.minobsinnode = 1, shrinkage = 1.0)

t <- pretty.gbm.tree(M, i = 1)
t[, c("SplitVar", "LeftNode", "RightNode", "MissingNode", "Prediction")]

看起来像

  SplitVar LeftNode RightNode MissingNode Prediction
0        0        1         2           3        0.0
1       -1       -1        -1          -1       -0.5
2       -1       -1        -1          -1        0.5
3       -1       -1        -1          -1        0.0

让我分解一下。在这个模型中,我们最小化了以下损失函数:

L(y,y^)=12(yy^)2

关于预测的梯度是:

L(y,y^)=yy^

这棵树适合预测这个函数的值。

详细地说,模型从第零阶段开始,预测一个常数,即平均响应。在我们的示例数据中,平均响应为0.5. 然后,在数据和当前预测处评估损失函数的梯度:

grad <- function(y, current_preds) {
  y - current_preds
}

grad(y, 0.5)

这导致

[1] -0.5 -0.5 -0.5  0.5  0.5  0.5

现在您可以通过将树预测与此进行比较来了解发生了什么。树的预测准确地恢复了梯度。

在伯努利模型的情况下也是如此,尽管细节更复杂。最小化的损失函数是

L(y,f)=yflog(1+ef)

注意这里f是预测的对数,而不是概率。梯度是

L(y,f)=y11+ef

这就是来自树的预测是近似的。

简而言之,梯度增强器中树的预测与响应相比是不可解释的,在解释增强模型的内部结构时必须非常小心。