J'essaye d'écrire mon propre algorithme d'amplification de gradient. Je comprends qu'il existe des packages existants comme gbm
et xgboost,
Mais je voulais comprendre comment fonctionne l'algorithme en écrivant le mien.
J'utilise l'ensemble de données iris
, et mon résultat est Sepal.Length
(Continu). Ma fonction de perte est mean(1/2*(y-yhat)^2)
(fondamentalement l'erreur quadratique moyenne avec 1/2 devant), donc mon gradient correspondant est juste le résidu 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'ensemble de données iris
en un ensemble de données d'entraînement et de test et j'y ai adapté mon modèle.
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édites à 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
yhats.mymod
?Mais pour répondre à quelque chose qui n'a pas été demandé, j'ai remarqué que votre configuration d'entraînement comporte quelques bizarreries.
iris
est divisé également entre 3 espèces (setosa, versicolor, virginica) et celles-ci sont adjacentes dans les données. Vos données d'entraînement contiennent tous les setosa et versicolor, tandis que l'ensemble de test contient tous les exemples virginica. Il n'y a pas de chevauchement, ce qui entraînera des problèmes de hors échantillon. Il est préférable d'équilibrer vos ensembles d'entraînement et de test pour éviter cela.(1-lr)^n
. Avec lr = 1e-3
et n = 1000
vous ne pouvez modéliser que 63,2% de la magnitude des données. Autrement dit, même si chaque modèle prédit correctement chaque échantillon, vous estimeriez 63,2% de la valeur correcte. Initialiser l'ajustement avec une moyenne, au lieu de 0, serait utile puisque l'effet est une régression vers la moyenne au lieu d'un simple glissement.