производительность модели glmnet по сравнению с алгоритмами повышения - PullRequest
0 голосов
/ 07 сентября 2018

Чтобы помочь узнать о машинном обучении, я привожу несколько примеров, чтобы не показать, что один метод лучше другого, а чтобы показать, как использовать различные функции и какие параметры настраивать.Я начал с этого блога , в котором сравнивались BooST и xgboost, затем успешно добавил gbm в пример.Сейчас я пытаюсь добавить glmnet, но возвращаемая модель всегда имеет (почти) ноль для обоих коэффициентов.Либо я делаю что-то не так, либо glmnet просто не правильный алгоритм для этих данных.Я пытаюсь понять, что это такое.Вот мой воспроизводимый пример:

# Uncomment the following 2 lines if you need to install BooST (requires devtools)
#library(devtools)
#install_github("gabrielrvsc/BooST")

library(BooST)
library(xgboost)
library(gbm)
library(glmnet)

# Data generating process
dgp = function(N, r2){
  X = matrix(rnorm(N*2,0,1),N,2)
  X[,ncol(X)] = base::sample(c(0,1),N,replace=TRUE)
  aux = X
  yaux = cos(pi*(rowSums(X)))
  vyaux = var(yaux)
  ve = vyaux*(1-r2)/r2
  e = rnorm(N,0,sqrt(ve))
  y = yaux+e
  return(list(y = y, X = X))
}

# Real data
x1r = rep(seq(-4,4,length.out = 1000), 2)
x2r = c(rep(0,1000), rep(1,1000))
yr = cos(pi*(x1r+x2r))
real_function = data.frame(x1 = x1r, x2 = as.factor(x2r), y = yr)

# Train data (noisy)
set.seed(1)
data = dgp(N = 1000, r2 = 0.5)
y = data$y
x = data$X

# Test data (noisy)
set.seed(2)
dataout=dgp(N = 1000, r2 = 0.5)
yout = dataout$y
xout = dataout$X

# Set seed and train all 4 models
set.seed(1)
BooST_Model = BooST(x, y, v = 0.18, M = 300 , display = TRUE)
xgboost_Model = xgboost(x, label = y, nrounds = 300, params = list(eta = 0.14, max_depth = 2))
gbm_Model = gbm.fit(x, y, distribution = "gaussian", n.trees = 10000, shrinkage = .001, interaction.depth=5)
glmnet_Model = cv.glmnet(x, y, family = "gaussian", alpha=0)
coef(glmnet_Model)

coef (glmnet_Model)

3 x 1 разреженная матрица класса "dgCMatrix" 1

(перехват) 0.07807215463259706278442706661754421011 *

V1 -0,000000000000000000000000000000000000003033534

V2 -0,0000000000000000000000000000000000000000000000000044661342

# Predict from test data
p_BooST = predict(BooST_Model, xout)
p_xgboost = predict(xgboost_Model, xout)
p_gbm = predict(gbm_Model, xout, n.trees=10000)
p_glmnet = predict(glmnet_Model, xout)

# Show RMSE
sqrt(mean((p_BooST - yout)^2))
sqrt(mean((p_xgboost - yout)^2))
sqrt(mean((p_gbm - yout)^2))
sqrt(mean((p_glmnet - yout)^2))

fitted = data.frame(x1 = x[,1], x2 = as.factor(x[,2]),
  BooST = fitted(BooST_Model),
  xgboost = predict(xgboost_Model, x),
  gbm = predict(object = gbm_Model, newdata = x, n.trees = 10000),
  glmnet = predict(glmnet_Model, newx = x, s=glmnet_Model$lambda.min)[, 1], y = y)

# Plot noisy Y
ggplot() + geom_point(data = fitted, aes(x = x1, y = y, color = x2)) + geom_line(data = real_function, aes(x = x1, y = y, linetype = x2))

# Plot xgboost
ggplot() + geom_point(data = fitted, aes(x = x1, y = y), color = "gray") + geom_point(data = fitted, aes(x = x1, y = xgboost, color = x2)) + geom_line(data = real_function, aes(x = x1, y = y, linetype = x2))

# Plot BooST
ggplot() + geom_point(data = fitted, aes(x = x1, y = y), color = "gray") + geom_point(data = fitted, aes(x = x1, y = BooST, color = x2)) + geom_line(data = real_function, aes(x = x1, y = y, linetype = x2))

# Plot gbm
ggplot() + geom_point(data = fitted, aes(x = x1, y = y), color = "gray") + geom_point(data = fitted, aes(x = x1, y = gbm, color = x2)) + geom_line(data = real_function, aes(x = x1, y = y, linetype = x2))

# Plot glmnet
ggplot() + geom_point(data = fitted, aes(x = x1, y = y), color = "gray") + geom_point(data = fitted, aes(x = x1, y = glmnet, color = x2)) + geom_line(data = real_function, aes(x = x1, y = y, linetype = x2))

Ответы [ 2 ]

0 голосов
/ 09 сентября 2018

Помните, что glmnet подходит для линейной модели, что означает, что ответ может быть записан в виде линейной комбинации предикторов:

 y = b0 + b1*x1 + b2*x2 + ...

В вашем наборе данных вы определяете ответ следующим образом:

yaux = cos(pi*(rowSums(X)))

yr = cos(pi*(x1r+x2r))

, которая в обоих случаях явно не линейная комбинация предикторов.

0 голосов
/ 07 сентября 2018

Либо я делаю что-то не так

Вы не, по крайней мере, в программировании

или glmnet просто не правильный алгоритм для этих данных

Это не значит, что glmnet "не верен" (хотя предполагается, что он в основном используется для проблем с большим количеством предикторов, а не просто парой); Дело в том, что ваше сравнение в корне «несправедливо» и неуместно: все остальные 3 алгоритма, которые вы используете, - ансамбль - ваш gbm, например, состоит из десять тысяч (10 000) отдельные деревья решений ...! Попытка сравнить этот с одним регрессором, таким как glmnet, ну, это почти как сравнение яблок с апельсинами ...

Тем не менее, это должно быть хорошим упражнением и напоминанием о том, что все эти инструменты, с точки зрения программирования , кажутся "эквивалентными" ("ну, я просто использую library() для загрузки каждого из них, верно? Итак, почему они не должны быть эквивалентны и сопоставимы? "), скрывает много ... И именно поэтому, по крайней мере, элементарное знакомство с принципами статистического обучения всегда хорошая идея (я настоятельно рекомендую Свободно доступное введение в статистическое обучение , для начала - включая также фрагменты кода R).

Метод ансамбля Adaboost , в частности (который является объединяющим элементом всех остальных трех алгоритмов, которые вы здесь используете), не шутка! Когда он вышел, это был реальный изменитель игры (примерно за 10 лет до эры глубокого обучения), а в реализации xgboost он по-прежнему является победным выбором в большинстве соревнований Kaggle, в которых участвуют " традиционные "структурированные данные (т.е. без текста или изображений).

...