随机森林模型的预测是否有预测区间?

机器算法验证 r 置信区间 随机森林
2022-01-26 01:44:45

如果我运行一个randomForest模型,我就可以根据该模型进行预测。有没有办法获得每个预测的预测区间,以便我知道模型对其答案的“确定性”。如果这是可能的,它只是基于整个模型的因变量的可变性,还是会根据特定预测所遵循的特定决策树而具有更宽和更窄的区间?

4个回答

这部分是对@Sashikanth Dareddy 的回应(因为它不适合评论),部分是对原始帖子的回应。

记住什么是预测区间,它是我们预测未来观测值的区间或一组值。通常,预测区间有两个决定其宽度的主要部分,一个代表预测平均值(或其他参数)的不确定性,这是置信区间部分,另一个代表围绕该平均值的单个观测值的可变性。由于中心极限定理,置信区间非常稳健,在随机森林的情况下,自举也有帮助。但是预测区间完全取决于给定预测变量的数据分布方式的假设,CLT 和自举对该部分没有影响。

预测区间应该更宽,相应的置信区间也会更宽。其他会影响预测区间宽度的因素是关于是否相等方差的假设,这必须来自研究人员的知识,而不是随机森林模型。

预测区间对于分类结果没有意义(您可以做一个预测集而不是一个区间,但大多数时候它可能不会提供很多信息)。

通过模拟我们知道确切事实的数据,我们可以看到预测区间的一些问题。考虑以下数据:

set.seed(1)

x1 <- rep(0:1, each=500)
x2 <- rep(0:1, each=250, length=1000)

y <- 10 + 5*x1 + 10*x2 - 3*x1*x2 + rnorm(1000)

该特定数据遵循线性回归的假设,并且对于随机森林拟合相当简单。我们从“真实”模型中知道,当两个预测变量都为 0 时,平均值为 10,我们还知道各个点遵循标准差为 1 的正态分布。这意味着基于完美知识的 95% 预测区间这些点是从 8 到 12(实际上是 8.04 到 11.96,但四舍五入使它更简单)。任何估计的预测间隔都应该比这个更宽(没有完美的信息会增加宽度来补偿)并包括这个范围。

让我们看看回归的区间:

fit1 <- lm(y ~ x1 * x2)

newdat <- expand.grid(x1=0:1, x2=0:1)

(pred.lm.ci <- predict(fit1, newdat, interval='confidence'))
#        fit       lwr      upr
# 1 10.02217  9.893664 10.15067
# 2 14.90927 14.780765 15.03778
# 3 20.02312 19.894613 20.15162
# 4 21.99885 21.870343 22.12735

(pred.lm.pi <- predict(fit1, newdat, interval='prediction'))
#        fit      lwr      upr
# 1 10.02217  7.98626 12.05808
# 2 14.90927 12.87336 16.94518
# 3 20.02312 17.98721 22.05903
# 4 21.99885 19.96294 24.03476

我们可以看到估计的平均值(置信区间)存在一些不确定性,这为我们提供了一个更宽(但包括)8 到 12 范围的预测区间。

现在让我们看看基于单个树的单个预测的间隔(我们应该期望这些更宽,因为随机森林不会受益于线性回归所做的假设(我们知道该数据是正确的)):

library(randomForest)
fit2 <- randomForest(y ~ x1 + x2, ntree=1001)

pred.rf <- predict(fit2, newdat, predict.all=TRUE)

pred.rf.int <- apply(pred.rf$individual, 1, function(x) {
  c(mean(x) + c(-1, 1) * sd(x), 
  quantile(x, c(0.025, 0.975)))
})

t(pred.rf.int)
#                           2.5%    97.5%
# 1  9.785533 13.88629  9.920507 15.28662
# 2 13.017484 17.22297 12.330821 18.65796
# 3 16.764298 21.40525 14.749296 21.09071
# 4 19.494116 22.33632 18.245580 22.09904

区间比回归预测区间更宽,但并未涵盖整个范围。它们确实包含真实值,因此作为置信区间可能是合法的,但它们仅预测平均值(预测值)在哪里,而不是围绕该平均值的分布的附加部分。对于 x1 和 x2 都为 0 的第一种情况,区间不会低于 9.7,这与下降到 8 的真实预测区间非常不同。如果我们生成新的数据点,那么将会有几个点(更多大于 5%)在真实区间和回归区间内,但不属于随机森林区间。

要生成预测区间,您需要对预测均值周围的各个点的分布做出一些强有力的假设,然后您可以从各个树(自举置信区间)中获取预测,然后从假设中生成一个随机值与该中心的分布。这些生成的片段的分位数可能会形成预测区间(但我仍然会对其进行测试,您可能需要多次重复该过程并结合起来)。

下面是一个示例,通过将正态(因为我们知道原始数据使用正态)偏差添加到基于从该树估计的 MSE 的标准偏差的预测中:

pred.rf.int2 <- sapply(1:4, function(i) {
  tmp <- pred.rf$individual[i, ] + rnorm(1001, 0, sqrt(fit2$mse))
  quantile(tmp, c(0.025, 0.975))
})
t(pred.rf.int2)
#           2.5%    97.5%
# [1,]  7.351609 17.31065
# [2,] 10.386273 20.23700
# [3,] 13.004428 23.55154
# [4,] 16.344504 24.35970

这些间隔包含基于完美知识的间隔,因此看起来很合理。但是,它们在很大程度上取决于所做的假设(假设在这里是有效的,因为我们使用了关于如何模拟数据的知识,它们在真实数据案例中可能不那么有效)。在完全信任这种方法之前,我仍然会多次重复模拟看起来更像你的真实数据(但模拟以便你知道真相)的数据。

我意识到这是一篇旧帖子,但我一直在对此进行一些模拟,并认为我会分享我的发现。

@GregSnow 对此发表了非常详细的帖子,但我相信在使用来自单个树的预测计算区间时,他正在查看这只有 70% 的预测区间。我们需要查看以获得 95% 的预测区间。[μ+σ,μσ][μ+1.96σ,μ1.96σ]

对@GregSnow 代码进行此更改,我们得到以下结果

set.seed(1)
x1 <- rep( 0:1, each=500 )
x2 <- rep( 0:1, each=250, length=1000 )
y <- 10 + 5*x1 + 10*x2 - 3*x1*x2 + rnorm(1000)

library(randomForest)
fit2 <- randomForest(y~x1+x2)
pred.rf <- predict(fit2, newdat, predict.all=TRUE)
pred.rf.int <- t(apply( pred.rf$individual, 1, function(x){ 
  c( mean(x) + c(-1.96,1.96)*sd(x), quantile(x, c(0.025,0.975)) )}))

pred.rf.int
                          2.5%    97.5%
1  7.826896 16.05521  9.915482 15.31431
2 11.010662 19.35793 12.298995 18.64296
3 14.296697 23.61657 14.749248 21.11239
4 18.000229 23.73539 18.237448 22.10331

现在,将这些与通过将正常偏差添加到具有标准偏差的预测中生成的间隔进行比较,如@GregSnow 建议的 MSE,我们得到,

pred.rf.int2 <- sapply(1:4, function(i) {
   tmp <- pred.rf$individual[i,] + rnorm(1000, 0, sqrt(fit2$mse))
   quantile(tmp, c(0.025, 0.975))
   })
t(pred.rf.int2)
          2.5%    97.5%
[1,]  7.486895 17.21144
[2,] 10.551811 20.50633
[3,] 12.959318 23.46027
[4,] 16.444967 24.57601

这两种方法的间隔现在看起来非常接近。在这种情况下,针对误差分布绘制三种方法的预测区间如下所示

在此处输入图像描述

  • 黑线 = 线性回归的预测区间,
  • 红线 = 根据个人预测计算的随机森林区间,
  • 蓝线 = 通过向预测添加正态偏差计算的随机森林区间

现在,让我们重新运行模拟,但这次增加了误差项的方差。如果我们的预测区间计算良好,我们最终应该得到比我们上面得到的更宽的区间。

set.seed(1)
x1 <- rep( 0:1, each=500 )
x2 <- rep( 0:1, each=250, length=1000 )
y <- 10 + 5*x1 + 10*x2 - 3*x1*x2 + rnorm(1000,mean=0,sd=5)

fit1 <- lm(y~x1+x2)
newdat <- expand.grid(x1=0:1,x2=0:1)
predict(fit1,newdata=newdat,interval = "prediction")
      fit       lwr      upr
1 10.75006  0.503170 20.99695
2 13.90714  3.660248 24.15403
3 19.47638  9.229490 29.72327
4 22.63346 12.386568 32.88035

set.seed(1)
fit2 <- randomForest(y~x1+x2,localImp=T)
pred.rf.int <- t(apply( pred.rf$individual, 1, function(x){ 
  c( mean(x) + c(-1.96,1.96)*sd(x), quantile(x, c(0.025,0.975)) )}))
pred.rf.int
                          2.5%    97.5%
1  7.889934 15.53642  9.564565 15.47893
2 10.616744 18.78837 11.965325 18.51922
3 15.024598 23.67563 14.724964 21.43195
4 17.967246 23.88760 17.858866 22.54337

pred.rf.int2 <- sapply(1:4, function(i) {
   tmp <- pred.rf$individual[i,] + rnorm(1000, 0, sqrt(fit2$mse))
   quantile(tmp, c(0.025, 0.975))
   })
t(pred.rf.int2)
         2.5%    97.5%
[1,] 1.291450 22.89231
[2,] 4.193414 25.93963
[3,] 7.428309 30.07291
[4,] 9.938158 31.63777

在此处输入图像描述

现在,这清楚地表明,通过第二种方法计算预测区间要准确得多,并且产生的结果非常接近线性回归的预测区间。

假设正态性,还有另一种更简单的方法来计算随机森林的预测区间。从每棵树中,我们得到预测值 ( ) 以及均方误差 ( )。因此,来自每棵树的预测可以被认为是使用正态分布属性,我们对随机森林的预测将具有分布将此应用于我们上面讨论的示例,我们得到以下结果μiMSEiN(μi,RMSEi)N(μi/n,RMSEi/n)

mean.rf <- pred.rf$aggregate
sd.rf <- mean(sqrt(fit2$mse))
pred.rf.int3 <- cbind(mean.rf - 1.96*sd.rf, mean.rf + 1.96*sd.rf)
pred.rf.int3
1  1.332711 22.09364
2  4.322090 25.08302
3  8.969650 29.73058
4 10.546957 31.30789

这些与线性模型间隔以及@GregSnow 建议的方法非常吻合。但请注意,我们讨论的所有方法的基本假设是误差服从正态分布。

如果您使用 R,您可以轻松地为随机森林回归的预测生成预测区间:只需使用包quantregForest(可在CRAN获得)并阅读N. Meinshausen 的论文,了解如何使用分位数回归森林推断条件分位数以及它们如何可用于构建预测区间。即使您不使用 R 也能提供非常丰富的信息!

这很容易用 randomForest 解决。

首先让我处理回归任务(假设你的森林有 1000 棵树)。在该predict函数中,您可以选择从单个树返回结果。这意味着您将收到 1000 列输出。我们可以取每行 1000 列的平均值——这是常规输出 RF 会产生的任何方式。现在要获得预测间隔,可以说 +/- 2 std。您需要做的就是,对于每一行,从 1000 个值中计算 +/-2 标准差。偏差并使这些成为您预测的上限和下限。

其次,在分类的情况下,请记住每棵树输出 1 或 0(默认情况下),所有 1000 棵树的总和除以 1000 给出类概率(在二元分类的情况下)。为了在概率上设置预测区间,您需要修改最小值。nodesize 选项(有关该选项的确切名称,请参阅 randomForest 文档)一旦将其设置为值 >>1,那么各个树将输出 1 和 0 之间的数字。现在,从这里开始,您可以重复上述相同的过程回归任务。

我希望这是有道理的。