R:实现我自己的梯度提升算法


10

我正在尝试编写自己的梯度提升算法。我了解有类似的现有软件包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是否正确计算了预测值?

Answers:


0
  1. 是的,这看起来是正确的。在每个步骤中,您都适合伪残差,这些残差被计算为相对于拟合的损耗导数。您在问题开始时就已经正确地得出了这个梯度,甚至费力地将因子设为2。
  2. 这看起来也是正确的。就像在训练中一样,您正在汇总各个模型,并按学习率加权。

但是要解决一些未问到的问题,我注意到您的培训设置有些怪异。

  • 所述iris的数据集是在3种(setosa,花斑癣,锦葵),并且这些是在数据相邻的均分。您的训练数据包含所有的setosa和杂色,而测试集包含所有的virginica示例。没有重叠,这将导致样本外问题。为避免这种情况,最好平衡训练和测试集。
  • 学习率和模型计数的组合对我来说似乎太低了。拟合收敛为(1-lr)^n。使用lr = 1e-3n = 1000只能建模数据量的63.2%。也就是说,即使每个模型都能正确预测每个样本,您也将估计正确值的63.2%。用平均值而不是0初始化拟合将有所帮助,因为那样的话,效果是平均值的回归,而不仅仅是阻力。

谢谢您的意见。您能否解释为什么“拟合收敛为(1-lr)^ n”?这背后的原理是什么?
YQW

这是因为fit <- fit + learning.rate * predictionprediction残留在哪里target - fit。所以fit <- fit + lr * (target - fit),还是fit <- fit * (1 - lr) + target * lr。这只是指数移动平均线。根据Wikipedia的说法,“在k个词之后停止停止所忽略的权重(1-α)^k不在总权重之内”(α是学习率,kn)。您从0而不是均值的估计开始,因此省略的权重直接来自预测。
mcskinner
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.