Estoy tratando de escribir mi propio algoritmo de aumento de gradiente. Entiendo que hay paquetes existentes como gbm
y, xgboost,
pero quería entender cómo funciona el algoritmo escribiendo el mío.
Estoy usando el iris
conjunto de datos y mi resultado es Sepal.Length
(continuo). Mi función de pérdida es mean(1/2*(y-yhat)^2)
(básicamente el error cuadrático medio con 1/2 en el frente), por lo que mi gradiente correspondiente es solo el residual y - yhat
. Estoy inicializando las predicciones en 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)
}
Con esto, dividí el iris
conjunto de datos en un conjunto de datos de entrenamiento y prueba y ajusté mi modelo a él.
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)
Ahora calculo los valores predichos de my.model
. Para my.model
, los valores ajustados son 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
Tengo algunas preguntas
- ¿Mi algoritmo de aumento de gradiente se ve bien?
- ¿Calculé los valores pronosticados
yhats.mymod
correctamente?
fit <- fit + learning.rate * prediction
, dondeprediction
está el residuotarget - fit
. Entoncesfit <- fit + lr * (target - fit)
, ofit <- fit * (1 - lr) + target * lr
. Esto es solo un promedio móvil exponencial. Según Wikipedia , "el peso omitido al detenerse después de k términos está(1-α)^k
fuera del peso total" (α
es la tasa de aprendizaje yk
esn
). Está comenzando con una estimación de 0 en lugar de la media, por lo que este peso omitido proviene directamente de la predicción.