Лямбда.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, позвольте мне объяснить, почему вы не получаете то же самое, используя ваши вычисления:
cv.lasso$cvm
содержит перекрестную проверку среднего MSE для каждого значенияlambda
,- Когда мы говорим 1 стандартная ошибка, мы говорим не о стандартной ошибке по лямбде, а о стандартной ошибке по сгибам для данной лямбды.
- Продолжая с вышеуказанным пунктом, в
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 может выполнять средневзвешенную и стандартную ошибку (взвешенную по количеству наблюдений в каждом сгибе), поэтому цифры выше близки, но не точно совпадают.
Думаю, процедура такая:
- Для каждого ƛ он создает x моделей (x = nº складок, в которых набор данных был разделен для алгоритма перекрестной проверки)
- Для каждого ƛ и каждой модели x вычисляется среднее значение (ошибка) и sd(ошибка), таким образом, среднее значение (ошибки x) и sd(ошибки x).
Допустим, у нас есть ƛmin и serrorƛmin (рассчитанные на шаге 2.). Теперь ƛse определяется как "наибольшее значение лямбда, при котором ошибка находится в пределах 1 стандартной ошибки от минимума". Тогда условие для ƛse:
ƛse в [ƛmin - seƛmin, ƛmin + seƛmin]
Тогда ƛ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
Я надеюсь, что это помогает!