Перекрестная проверка шаговых функций в R
Я пытаюсь получить ошибки от пошаговых функций, но получаю сообщение об ошибке:
library(boot)
library(ISLR)
attach(Wage)
set.seed(5082)
cv.error <- rep (0,12)
for (i in 2:13){
step.fit = glm(wage~cut(age,i), data = Wage)
cv.error[i] <- cv.glm(Wage ,step.fit, K= 10)$delta [1]
}
Error in model.frame.default(Terms, newdata, na.action = na.action, xlev = object$xlevels) :
cut(age, i) has new levels (17.9,43.5], (43.5,69.1]
Я могу получить ошибку от cv.glm()$delta [1]
если вместо автоматической генерации cut()
Индекс я использую определенные перерывы:
fit <- glm(wage~cut(age,breaks=c(17.9,33.5,49,64.5,80.1)), data = Wage)
cv.error <- cv.glm(Wage ,step.fit, K= 10)$delta [1]'
Хотя это те же самые перерывы cut(age,4)
делает.
Может кто-нибудь объяснить, что происходит или как исправить ошибку.
Моя цель - попытаться найти ошибки в 12 различных пошаговых моделях и выбрать лучшую на основе cv.glm()$delta
ошибка.
2 ответа
Проблема заключалась в том, что cut(age, i)
существовал только как встроенное создание внутри вашего glm()
и не был частью Wage
набор данных, который вы использовали для проверки. Мы можем исправить это так:
library(boot)
library(ISLR)
data(Wage) # using attach is a bad practice
set.seed(5082)
cv.error <- rep (0,12)
for (i in 2:13){
Wage$tmp <- cut(Wage$age,i)
step.fit = glm(wage~tmp, data = Wage)
cv.error[i] <- cv.glm(Wage ,step.fit, K= 10)$delta [1]
}
cv.error
[1] 0.000 1733.815 1682.731 1637.200 1631.049 1623.069 1613.099 1600.413 1613.127 1603.581 1603.601 1604.730 1602.462
Обратите внимание, что первое значение 0 только потому, что значения i
начать с 2, так что ничего не было написано в первый элемент.
Я посмотрел, как получить этикетки от cut
вывод и нашел полезную заметку в конце документации (??cut
)
## one way to extract the breakpoints
labs <- levels(cut(aaa, 3))
cbind(lower = as.numeric( sub("\\((.+),.*", "\\1", labs) ),
upper = as.numeric( sub("[^,]*,([^]]*)\\]", "\\1", labs) ))
Таким образом, положить это использовать:
library(boot)
library(ISLR)
data(Wage)
set.seed(5082)
cv.error <- rep (0,12)
for (i in 2:13){
labs <- levels(cut(age, i))
breaks <- unique(c(as.numeric(sub("\\((.+),.*", "\\1", labs)),
as.numeric(sub("[^,]*,([^]]*)\\]", "\\1", labs))))
step.fit <- glm(wage~cut(age,unique(breaks)), data = Wage)
cv.error[i] <- cv.glm(Wage ,step.fit, K=10)$delta[1]
}
cv.error
[1] 0.000 1733.815 1682.731 1637.200 1631.049 1623.069 1613.099 1600.413 1613.127 1603.581 1603.601
[12] 1604.730 1602.462