기능 공학은 실제 생활에서 매우 중요하지만 나무 (및 임의의 포리스트)는 양식의 상호 작용 항을 찾는 데 매우 능숙합니다 x*y
. 다음은 양방향 상호 작용이있는 회귀의 장난감 예입니다. 순진한 선형 모델은 나무와 나무 자루와 비교됩니다 (임의의 숲에 대한 간단한 대안 임).
보시다시피 트리 자체는 상호 작용을 찾는 데 꽤 좋지만이 예제에서는 선형 모델이 좋지 않습니다.
# fake data
x <- rnorm(1000, sd=3)
y <- rnorm(1000, sd=3)
z <- x + y + 10*x*y + rnorm(1000, 0, 0.2)
dat <- data.frame(x, y, z)
# test and train split
test <- sample(1:nrow(dat), 200)
train <- (1:1000)[-test]
# bag of trees model function
boot_tree <- function(formula, dat, N=100){
models <- list()
for (i in 1:N){
models[[i]] <- rpart(formula, dat[sample(nrow(dat), nrow(dat), replace=T), ])
}
class(models) <- "boot_tree"
models
}
# prediction function for bag of trees
predict.boot_tree <- function(models, newdat){
preds <- matrix(0, nc=length(models), nr=nrow(newdat))
for (i in 1:length(models)){
preds[,i] <- predict(models[[i]], newdat)
}
apply(preds, 1, function(x) mean(x, trim=0.1))
}
## Fit models and predict:
# linear model
model1 <- lm(z ~ x + y, data=dat[train,])
pred1 <- predict(model1, dat[test,])
# tree
require(rpart)
model2 <- rpart(z ~ x + y, data=dat[train,])
pred2 <- predict(model2, dat[test,])
# bag of trees
model3 <- boot_tree("z ~ x+y", dat)
pred3 <- predict(model3, dat[test,])
ylim = range(c(pred1, pred2, pred3))
# plot predictions and true z
plot(dat$z[test], predict(model1, dat[test,]), pch=19, xlab="Actual z",
ylab="Predicted z", ylim=ylim)
points(dat$z[test], predict(model2, dat[test,]), col="green", pch=19)
points(dat$z[test], predict(model3, dat[test,]), col="blue", pch=19)
abline(0, 1, lwd=3, col="orange")
legend("topleft", pch=rep(19,3), col=c("black", "green", "blue"),
legend=c("Linear", "Tree", "Forest"))