Sto cercando di scrivere il mio algoritmo di aumento gradiente. Capisco che ci sono pacchetti esistenti come gbme xgboost,ma volevo capire come funziona l'algoritmo scrivendo il mio.
Sto usando il irisset di dati e il mio risultato è Sepal.Length(continuo). La mia funzione di perdita è mean(1/2*(y-yhat)^2)(sostanzialmente l'errore quadratico medio con 1/2 davanti), quindi il gradiente corrispondente è solo il residuo y - yhat. Sto inizializzando le previsioni a 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 questo, ho diviso il irisset di dati in un set di dati di training e test e ho adattato il mio modello ad esso.
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)
Ora calcolo i valori previsti da my.model. Per my.model, i valori adattati sono 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
Ho alcune domande
- Il mio algoritmo di aumento gradiente sembra giusto?
- Ho calcolato
yhats.mymodcorrettamente i valori previsti ?