随机森林实际上在寻找变量之间的相互作用方面有多好?在模型中明确添加交互项是否会增加随机森林的预测能力?
随机森林是否擅长检测交互项?
@gunes 已经给出了答案,即随机森林在交互方面效果很好。不过,举一个实际的例子可能会有所帮助。为此,我们需要一些玩具数据
set.seed(2021)
n = 5000
x1 <- rnorm(2*n)
x2 <- runif(2*n)
interaction <- x1 * x2
pseudointeraction <- sample(interaction)
x3 <- rbeta(2*n, 2, 10)
epsilon <- rt(2*n, df = 1)
y <- 1*x1 + 2*x2 + 3*x3 + 10*interaction
example <- data.frame(x1 = x1, x2 = x2, x3 = x3, x4 = rbeta(2*n, 5, 5), x5 = runif(2*n,-10, 10),
interaction = interaction, pseudointeraction = pseudointeraction,
y = y)
基本上我们有一个y
是x1
,x2
和x3
交互作用的线性函数x1*x2
。在数据集中还有一个交互项的排列和另外两个随机变量,它们都没有真实的信息。我们将其拆分为一个训练数据集和一个同样大小的测试数据集,如下所示:
train <- example[1:n,]
test <- example[(n+1):(2*n),]
由于玩具数据已经在线性模型中建模,线性回归应该能够轻松解决这个难题:
> linear1 <- lm(y ~ . - pseudointeraction , data = example)
> summary(linear1)
Call:
lm(formula = y ~ . - pseudointeraction, data = example)
Residuals:
Min 1Q Median 3Q Max
-1.071e-12 -3.400e-16 5.000e-17 4.700e-16 1.524e-12
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -1.641e-14 9.004e-16 -1.823e+01 < 2e-16 ***
x1 1.000e+00 4.293e-16 2.329e+15 < 2e-16 ***
x2 2.000e+00 7.480e-16 2.674e+15 < 2e-16 ***
x3 3.000e+00 2.076e-15 1.445e+15 < 2e-16 ***
x4 3.798e-15 1.423e-15 2.669e+00 0.00762 **
x5 2.698e-18 3.725e-17 7.200e-02 0.94225
interaction 1.000e+01 7.415e-16 1.349e+16 < 2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.145e-14 on 9993 degrees of freedom
Multiple R-squared: 1, Adjusted R-squared: 1
F-statistic: 1.647e+32 on 6 and 9993 DF, p-value: < 2.2e-16
线性模型在声x4
明显着预测变量时是错误的,但正如预期的那样,约为 100%。
如果我们去掉交互项或将其换成置换的交互项,事情会像预期的那样变得更糟:
> linear2 <- lm(y ~ . - interaction, data = example)
> summary(linear2)
Call:
lm(formula = y ~ . - interaction, data = example)
Residuals:
Min 1Q Median 3Q Max
-17.4533 -1.2764 0.0621 1.2977 14.8616
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.1791910 0.1214622 -1.475 0.140
x1 6.0262464 0.0287402 209.680 <2e-16 ***
x2 2.0022413 0.1009082 19.842 <2e-16 ***
x3 3.0676424 0.2800356 10.954 <2e-16 ***
x4 0.1791824 0.1919885 0.933 0.351
x5 0.0005224 0.0050245 0.104 0.917
pseudointeraction 0.0121493 0.0496305 0.245 0.807
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 2.894 on 9993 degrees of freedom
Multiple R-squared: 0.816, Adjusted R-squared: 0.8159
F-statistic: 7385 on 6 and 9993 DF, p-value: < 2.2e-16
下降到 82%。所以交互项在这个模型中很重要。
让我们用交互项和没有交互项的方式来增长一个 randomForest:
library(randomForest)
rf1 <- randomForest(y ~ . - interaction, data = example, mtry = 3)
rf2 <- randomForest(y ~ . - pseudointeraction, data = example, mtry = 3)
print(rf1)
print(rf2)
这将需要一些时间来计算,print
结果将声称具有给定交互项的随机森林解释了 99.67% 的方差,而具有交互项的随机森林解释了 99.93% 的方差。
很难将样本内与袋外性能进行比较,因此我们使用我们目前拥有的所有四个模型来预测我们的测试数据集:
linear1.on.test <- predict(linear1, data = test)
linear2.on.test <- predict(linear2, data = test)
rf1.on.test <- predict(rf1, data = test)
rf2.on.test <- predict(rf2, data = test)
在下一步中,我们计算绝对残差并将它们绘制为箱线图:
boxplot(linear1.on.test - test$y, linear2.on.test - test$y, rf1.on.test - test$y, rf2.on.test - test$y,
ylim=c(-7, 7), xaxt="n", ylab = "residuals")
axis(1, at = 1:4, labels = c("linear with I", "linear w/o I", "rf w/o I", "rf with I"))
因此,具有交互项的线性模型最适合数据的构建方式,因此预测效果最好。没有交互项的线性模型没有适应的灵活性,是所有模型中预测值最差的。
对于随机森林,无论有无交互项,我们都看到了非常相似的结果。明确说明交互项似乎很有帮助,但没有它的模型足够灵活,可以在没有它的情况下给出良好的预测。
现实世界的交互很少遵循精确乘法的规则,因此计算模型的交互项的小优势对于现实世界的交互可能更小。
所有这些都将受到样本大小、特征数量、调整参数等的影响,但简短的信息是,虽然特征构建是一件好事,但随机森林可以检测并利用交互,即使它们没有说明在调用randomForest
.
随意使用不同的set.seed
值运行此代码,计算 RMSE 等。
是的,基于树的方法擅长检测交互,但并非总是如此。例如,在树的后续级别中使用和将等效于在一个级别上也就是说,由于您在随机森林中设置了最大深度超参数,因此添加有希望的交互将降低您的整体深度,并通过将剩余级别留给其他功能来为提高性能铺平道路。