Лямбда.1се не в одной стандартной ошибке ошибки

В документации функции cv.glmnet() дано, что:

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

Который означает, что lambda.1se дает lambda, что дает ошибку (cvm), что является одной стандартной ошибкой от минимальной ошибки.

Итак, пытаясь проверить этот факт:
Есть набор данных Boston в библиотеке MASS, Я провел перекрестную проверку, используя лассо:

x = model.matrix(crim~.-1,data=Boston)#-1 for removing the intercept column
y = Boston$crim
cv.lasso = cv.glmnet(x,y,type.measure = "mse",alpha=1)

И значение cv.lasso$lambda.min выходит:

> cv.lasso$lambda.min
[1] 0.05630926

И значение cv.lasso$lambda.1se является:

> cv.lasso$lambda.1se
[1] 3.375651

Теперь посмотрим на это:

> std(cv.lasso$cvm)
[1] 0.7177808

куда std является функцией, которая возвращает стандартную ошибку значений, вставленных в нее. 1
И минимальное значение cvm можно найти как:

> cv.lasso$cvm[cv.lasso$lambda==cv.lasso$lambda.min]
[1] 42.95009

Итак, мы добавляем стандартную ошибку к значению cvm и мы получаем:

> 42.95009+0.7177808
[1] 43.66787

Хотя нет lambda значение, соответствующее этому cvm Значение, мы можем иметь представление на основе существующих данных:
введите описание изображения здесь

Что значит lambda.1se должно быть между 0,4784899 и 0,4359821. Но это абсолютно не так. Таким образом, есть внутреннее чувство, которое говорит, что я делаю ошибку здесь. Можете ли вы помочь мне указать на это?


1: определение std:

std<-function(x)
  sd(x)/sqrt(length(x))

1 ответ

Решение

Я добавлю семя, чтобы можно было повторить результаты ниже:

library(glmnet)
library(MASS)
data("Boston")
x = model.matrix(crim~.-1,data=Boston)#-1 for removing the intercept column
y = Boston$crim
set.seed(100)
cv.lasso = cv.glmnet(x,y,type.measure = "mse",alpha=1)

Минимальная перекрестная проверка MSE min(cv.lasso$cvm) = 43.51256, Соответствующая лямбда cv.lasso$lambda.min = 0.01843874, lambda.1se является cv.lasso$lambda.1se = 3.375651, Это соответствует перекрестной проверке MSE

cv.lasso$cvm[which(cv.lasso$lambda == cv.lasso$lambda.1se)] = 57.5393

Мы можем получить доступ к перекрестно проверенным стандартным ошибкам непосредственно из вывода GLMNET следующим образом:

cv.lasso$cvsd[which(cv.lasso$lambda == cv.lasso$lambda.min)] = 15.40236

Таким образом, перекрестная проверка MSE одна стандартная ошибка далеко

43.51256 + 15.40236 = 58.91492 

Это только немного выше, чем перекрестная проверка MSE в lambda.1se выше (т.е. 57.5393). Если мы посмотрим на перекрестную проверку MSE на lambda как раз перед lambda.1se, это:

cv.lasso$cvm[which(cv.lasso$lambda == cv.lasso$lambda.1se)-1] = 59.89079

Итак, теперь, когда мы можем согласовать вывод GLMNET, позвольте мне объяснить, почему вы не получаете то же самое, используя ваши вычисления:

  1. cv.lasso$cvm содержит перекрестную проверку среднего MSE для каждого значения lambda,
  2. Когда мы говорим 1 стандартная ошибка, мы говорим не о стандартной ошибке по лямбде, а о стандартной ошибке по сгибам для данной лямбды.
  3. Продолжая с вышеуказанным пунктом, в lambda.minУ нас есть 10 сгибов. Мы соответствуем 10 моделям и имеем 10 MSE вне образца. Среднее из этих 10 MSE определяется как cv.lasso$cvm[which(cv.lasso$lambda == cv.lasso$lambda.min)], Стандартное отклонение этих 10 MSE определяется как cv.lasso$cvsd[which(cv.lasso$lambda == cv.lasso$lambda.min)], То, что нам не дают в выходных данных GLMNET, это 10 MSE в lambda.min, Если бы у нас было это, то мы могли бы повторить стандартную ошибку, используя формулу, которую вы использовали выше.

Позвольте мне знать, если это помогает.

РЕДАКТИРОВАТЬ: Давайте сделаем пример, в котором мы определяем заранее три раза

set.seed(100)
folds = sample(1:3, nrow(x), replace = T)
cv.lasso = cv.glmnet(x,y,type.measure = "mse",alpha=1, keep =T, foldid = folds)

Обратите внимание, что

> min(cv.lasso$cvm)
[1] 42.76584
> cv.lasso$cvsd[which.min(cv.lasso$cvm)]
[1] 17.89725

(Они отличаются от предыдущего примера выше, потому что мы определили наши собственные сгибы)

Обратите внимание, что у меня есть дополнительный параметр keep = T в cv.glmnet вызов. Это возвращает предсказания сгиба для каждой лямбды. Вы можете извлечь их для оптимального лямбда, выполнив:

cv.lasso$fit.preval[,which.min(cv.lasso$cvm)]

Прежде чем мы продолжим, давайте создадим фрейм данных с ответом, прогнозами сгиба и соответствующими сгибами:

library(data.table)
OOSPred = data.table(y = y, 
                     predictions = cv.lasso$fit.preval[,which.min(cv.lasso$cvm)], 
                     folds = folds)

Вот предварительный просмотр первых 10 строк:

> head(OOSPred, 10)
          y predictions folds
 1: 0.00632  -0.7477977     1
 2: 0.02731  -1.3823830     1
 3: 0.02729  -3.4826143     2
 4: 0.03237  -4.4419795     1
 5: 0.06905  -3.4373021     2
 6: 0.02985  -2.5256505     2
 7: 0.08829   0.7343478     3
 8: 0.14455   1.1262462     2
 9: 0.21124   4.0507847     2
10: 0.17004   0.5859587     1

Например, для случаев, когда folds = 1модель была построена на сгибах № 2 и № 3, а затем были получены прогнозы для наблюдений на сгибе № 1. Теперь мы вычисляем MSE:

OOSPredSum = OOSPred[, list(MSE = mean((y - predictions)^2)), by = folds]

   folds      MSE
1:     1 27.51469
2:     2 75.72847
3:     3 19.93480

Наконец, мы возвращаем среднее значение MSE и стандартную ошибку MSE через сгибы

> OOSPredSum[, list("Mean MSE" = mean(MSE), "Standard Error" = sd(MSE)/sqrt(3))]
   Mean MSE Standard Error
1: 41.05932       17.47213

GLMNET может выполнять средневзвешенную и стандартную ошибку (взвешенную по количеству наблюдений в каждом сгибе), поэтому цифры выше близки, но не точно совпадают.

Думаю, процедура такая:

  1. Для каждого ƛ он создает x моделей (x = nº складок, в которых набор данных был разделен для алгоритма перекрестной проверки)
  2. Для каждого ƛ и каждой модели x вычисляется среднее значение (ошибка) и sd(ошибка), таким образом, среднее значение (ошибки x) и sd(ошибки x).
  3. Допустим, у нас есть ƛmin и serrorƛmin (рассчитанные на шаге 2.). Теперь ƛse определяется как "наибольшее значение лямбда, при котором ошибка находится в пределах 1 стандартной ошибки от минимума". Тогда условие для ƛse:

    ƛse в [ƛmin - seƛmin, ƛmin + seƛmin]

  4. Тогда ƛse = max(ƛ),ƛ где удовлетворяет вышеуказанному условию.

Я могу показать вам пример:

lasso_cv <- cv.glmnet(x = x, y= endpoint, alpha = 1, lambda = lambdas_to_try,
                  standardize = TRUE, nfolds = 10,type.measure="auc",
                  family="binomial")

Обратите внимание, что ƛmin:

lasso_cv$lambda.min
[1] 0.007742637

И serrorƛmin это:

serrorlmin <- lasso_cv$cvsd[which(lasso_cv$lambda == lasso_cv$lambda.min)]
serrorlmin

[1] 0.01058009

Тогда диапазон, в котором выбирается ƛse:

rang <- c(lasso_cv$lambda.min - serrorlmin,lasso_cv$lambda.min + serrorlmin)
[1] -0.002837457  0.018322731

И найти его:

max(lasso_cv$lambda[lasso_cv$lambda>=rang[1] & lasso_cv$lambda<=rang[2]])
[1] 0.01629751

И это значение совпадает с ƛse!

lasso_cv$lambda.1se # 0.01629751

Я надеюсь, что это помогает!

Другие вопросы по тегам