R: реализация моего собственного алгоритма повышения градиента

10

Я пытаюсь написать свой собственный алгоритм повышения градиента. Я понимаю, что существуют такие пакеты, как 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

У меня есть несколько вопросов

  1. Мой алгоритм повышения градиента выглядит правильно?
  2. yhats.mymodПравильно ли я рассчитал прогнозные значения ?
YQW
источник

Ответы:

0
  1. Да, это выглядит правильно. На каждом шаге вы подходите к псевдо-остаткам, которые вычисляются как производные потерь по отношению к соответствию. Вы правильно вывели этот градиент в начале своего вопроса и даже потрудились получить правильный коэффициент 2.
  2. Это также выглядит правильно. Вы агрегируете по моделям, взвешенным по скорости обучения, так же, как вы делали это во время обучения.

Но чтобы ответить на вопрос, который не был задан, я заметил, что у вашей тренировочной программы есть несколько причуд.

  • iris данных разделен поровну между 3 видами (setosa, versicolor, virginica), и они являются смежными в данных. Ваши тренировочные данные содержат все сетозу и разноцветные, а набор тестов содержит все примеры virginica. Нет перекрытия, что приведет к проблемам вне выборки. Чтобы избежать этого, желательно сбалансировать тренировочный и тестовый наборы.
  • Комбинация скорости обучения и количества моделей кажется мне слишком низкой. Приступ сходится как (1-lr)^n. При помощи lr = 1e-3и n = 1000вы можете смоделировать только 63,2% величины данных. То есть, даже если каждая модель предсказывает каждую выборку правильно, вы оцениваете 63,2% правильного значения. Инициализация подгонки со средним значением, а не 0, поможет с тех пор, что эффект представляет собой регрессию к среднему значению, а не просто перетаскивание.
mcskinner
источник
Спасибо за ваши Коментарии. Не могли бы вы объяснить, почему «сходится как (1-lr) ^ n»? В чем причина этого?
YQW
Это потому что 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 вместо среднего, поэтому этот пропущенный вес напрямую зависит от прогноза.
Маккиннер