J'essaie d'écrire mon propre algorithme de renforcement de gradient. Je comprends qu'il existe des packages existants comme gbm
et xgboost,
mais je voulais comprendre comment l'algorithme fonctionne en écrivant le mien.
J'utilise l' iris
ensemble de données et mon résultat est Sepal.Length
(continu). Ma fonction de perte est mean(1/2*(y-yhat)^2)
(essentiellement l'erreur quadratique moyenne avec 1/2 devant), donc mon gradient correspondant n'est que le résiduel y - yhat
. J'initialise les prédictions à 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)
}
Avec cela, j'ai divisé l' iris
ensemble de données en un ensemble de données de formation et de test et j'adapte mon modèle à celui-ci.
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)
Maintenant, je calcule les valeurs prévues à partir de my.model
. Pour my.model
, les valeurs ajustées sont 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
J'ai quelques questions
- Mon algorithme d'amplification du gradient semble-t-il correct?
- Ai-je calculé
yhats.mymod
correctement les valeurs prévues ?
fit <- fit + learning.rate * prediction
, oùprediction
est le résidueltarget - fit
. Alorsfit <- fit + lr * (target - fit)
, oufit <- fit * (1 - lr) + target * lr
. Il s'agit simplement d'une moyenne mobile exponentielle. Selon Wikipedia , "le poids omis en s'arrêtant après k termes est(1-α)^k
hors du poids total" (α
est le taux d'apprentissage et l'k
estn
). Vous commencez avec une estimation de 0 au lieu de la moyenne, donc ce poids omis vient directement de la prédiction.