R:实现我自己的梯度增强算法



我正在尝试编写自己的梯度增强算法。我知道有像gbmxgboost,这样的现有包,但我想通过编写自己的包来了解算法是如何工作的。

我使用的是iris数据集,结果是Sepal.Length(连续(。我的损失函数是mean(1/2*(y-yhat)^2)(基本上是前面有1/2的均方误差(,所以我对应的梯度只是残差y - yhat。我正在0初始化预测。

library(rpart)
data(iris)
#Define gradient
grad.fun <- function(y, yhat) {return(y - yhat)}
mod <- list()
grad_boost <- function(data, learning.rate, M, grad.fun) {
# Initialize fit to be 0
fit <- rep(0, nrow(data))
grad <- grad.fun(y = data$Sepal.Length, yhat = fit)
# Initialize model
mod[[1]] <- fit
# Loop over a total of M iterations
for(i in 1:M){
# Fit base learner (tree) to the gradient
tmp <- data$Sepal.Length
data$Sepal.Length <- grad
base_learner <- rpart(Sepal.Length ~ ., data = data, control = ("maxdepth = 2"))
data$Sepal.Length <- tmp
# Fitted values by fitting current model
fit <- fit + learning.rate * as.vector(predict(base_learner, newdata = data))
# Update gradient
grad <- grad.fun(y = data$Sepal.Length, yhat = fit)
# Store current model (index is i + 1 because i = 1 contain the initialized estiamtes)
mod[[i + 1]] <- base_learner
}
return(mod)
}

这样,我将iris数据集拆分为一个训练和测试数据集,并将我的模型与之匹配

train.dat <- iris[1:100, ]
test.dat <- iris[101:150, ]
learning.rate <- 0.001
M = 1000
my.model <- grad_boost(data = train.dat, learning.rate = learning.rate, M = M, grad.fun = grad.fun)

现在我从my.model计算预测值。对于my.model,拟合值为0 (vector of initial estimates) + learning.rate * predictions from tree 1 + learning rate * predictions from tree 2 + ... + learning.rate * predictions from tree M

yhats.mymod <- apply(sapply(2:length(my.model), function(x) learning.rate * predict(my.model[[x]], newdata = test.dat)), 1, sum)
# Calculate RMSE
> sqrt(mean((test.dat$Sepal.Length - yhats.mymod)^2))
[1] 2.612972

我有几个问题

  1. 我的梯度增强算法看起来正确吗
  2. 我是否正确计算了预测值yhats.mymod
  1. 是的,这看起来是正确的。在每个步骤中,您都要拟合psuedo残差,该残差被计算为损耗相对于拟合的导数。你在问题一开始就正确地推导出了这个梯度,甚至还麻烦把因子2取对
  2. 这看起来也是正确的。你正在根据学习率对模型进行汇总,就像你在训练中所做的那样

但为了解决一些没有被问到的问题,我注意到你的训练设置有一些怪癖。

  • iris数据集平均分为3个物种(刚毛、云芝、弗吉尼亚(,这些物种在数据中相邻。您的训练数据包含所有的setosa和versicolor,而测试集包含所有的virginica示例。没有重叠,这将导致样本外的问题。为了避免这种情况,最好平衡你的训练和测试集
  • 学习率和模型计数的组合在我看来太低了。拟合收敛为(1-lr)^n。使用lr = 1e-3n = 1000,您只能对63.2%的数据量值进行建模。也就是说,即使每个模型都正确地预测了每个样本,你也会估计出63.2%的正确值。用平均值而不是0初始化拟合会有所帮助,因为从那时起,效果是回归到平均值,而不仅仅是拖动

最新更新