Я пытаюсь написать свой собственный алгоритм повышения градиента. Я понимаю, что существуют такие пакеты, как gbm
иxgboost,
, но я хотел бы понять , как работает алгоритм, написав мой собственный.
Я использую 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
У меня есть несколько вопросов
- Мой алгоритм повышения градиента выглядит правильно?
yhats.mymod
Правильно ли я рассчитал прогнозные значения ?
fit <- fit + learning.rate * prediction
, гдеprediction
находится остатокtarget - fit
. Такfit <- fit + lr * (target - fit)
илиfit <- fit * (1 - lr) + target * lr
. Это просто экспоненциальная скользящая средняя. Согласно Википедии , «вес, пропущенный при остановке после k членов,(1-α)^k
выходит за пределы общего веса» (α
это скорость обучения иk
естьn
). Вы начинаете с оценки 0 вместо среднего, поэтому этот пропущенный вес напрямую зависит от прогноза.