Предсказание.glm() с тремя новыми категориями в тестовых данных (r)(ошибка)
У меня есть набор данных под названием data
который имеет 481 092 строки.
Я разделил data
на две равные половины:
- Первая половина (строка 1: 240 546) называется
train
и был использован дляglm()
; - вторая половина (строка 240 547: 481 092) называется
test
и должен использоваться для проверки модели;
Затем я начал регрессию:
testreg <- glm(train$returnShipment ~ train$size + train$color + train$price +
train$manufacturerID + train$salutation + train$state +
train$age + train$deliverytime,
family=binomial(link="logit"), data=train)
Теперь прогноз:
prediction <- predict.glm(testreg, newdata=test, type="response")
выдает мне ошибку:
Error in model.frame.default(Terms, newdata, na.action=na.action, xlev=object$xlevels):
Factor 'train$manufacturerID' has new levels 125, 136, 137
Теперь я знаю, что эти уровни были опущены в регрессии, потому что она не показывает никаких коэффициентов для этих уровней.
Я пробовал это: предикат.lm() с неизвестным уровнем фактора в тестовых данных. Но это почему-то не работает для меня, или я просто не понимаю, как это реализовать. Я хочу предсказать зависимую двоичную переменную, но, конечно, только с существующими коэффициентами. Ссылка выше предлагает сообщить R, что строки с новыми уровнями должны просто называться / или рассматриваться как NA.
Как я могу продолжить?
Edit-предложенный подход Z. Li
У меня проблема на первом этапе:
xlevels <- testreg$xlevels$manufacturerID
mID125 <- xlevels[1]
но mID125
является NULL
! Что я сделал не так?
2 ответа
Невозможно получить оценку новых уровней факторов при моделировании с фиксированным эффектом, включая линейные модели и обобщенные линейные модели. glm
(так же как lm
) ведет учет того, какие уровни факторов представлены и используются во время подбора модели, и могут быть найдены в testreg$xlevels
,
Ваша модельная формула для оценки модели:
returnShipment ~ size + color + price + manufacturerID + salutation +
state + age + deliverytime
затем predict
жалуется на новые уровни факторов 125, 136, 137 для manufactureID
, Это означает, что эти уровни не внутри testreg$xlevels$manufactureID
, следовательно, не имеет ассоциированного коэффициента для прогнозирования. В этом случае мы должны отбросить эту факторную переменную и использовать формулу прогнозирования:
returnShipment ~ size + color + price + salutation +
state + age + deliverytime
Тем не менее, стандарт predict
рутина не может принять вашу индивидуальную формулу предсказания. Обычно есть два решения:
- извлечь матрицу модели и коэффициенты модели из
testreg
и вручную предсказывать нужные нам модельные термины путем умножения матрицы на вектор. Вот что предлагает сделать ссылка, приведенная в вашем посте; - сбросить уровни факторов в
test
в любой один уровень появился вtestreg$xlevels$manufactureID
, например,testreg$xlevels$manufactureID[1]
, Таким образом, мы все еще можем использовать стандартpredict
для прогноза.
Теперь давайте сначала подберем уровень фактора, используемый для подгонки модели
xlevels <- testreg$xlevels$manufacturerID
mID125 <- xlevels[1]
Затем мы назначаем этот уровень вашим прогнозным данным:
replacement <- factor(rep(mID125, length = nrow(test)), levels = xlevels)
test$manufacturerID <- replacement
И мы готовы предсказать:
pred <- predict(testreg, test, type = "link") ## don't use type = "response" here!!
В конце мы корректируем этот линейный предиктор, вычитая оценку коэффициента:
est <- coef(testreg)[paste0(manufacturerID, mID125)]
pred <- pred - est
Наконец, если вы хотите сделать прогноз в исходном масштабе, примените функцию обратной ссылки:
testreg$family$linkinv(pred)
Обновить:
Вы жаловались на то, что столкнулись с различными трудностями, пытаясь найти вышеуказанные решения. Вот почему.
Ваш код:
testreg <- glm(train$returnShipment~ train$size + train$color +
train$price + train$manufacturerID + train$salutation +
train$state + train$age + train$deliverytime,
family=binomial(link="logit"), data=train)
это очень плохой способ указать формулу вашей модели. train$returnShipment
и т. д. ограничит среду получения переменных строго до фрейма данных train
и у вас возникнут проблемы в дальнейшем прогнозировании с другими наборами данных, такими как test
,
В качестве простого примера такого недостатка мы моделируем некоторые игрушечные данные и подходим к GLM:
set.seed(0); y <- rnorm(50, 0, 1)
set.seed(0); a <- sample(letters[1:4], 50, replace = TRUE)
foo <- data.frame(y = y, a = factor(a))
toy <- glm(foo$y ~ foo$a, data = foo) ## bad style
> toy$formula
foo$y ~ foo$a
> toy$xlevels
$`foo$a`
[1] "a" "b" "c" "d"
Теперь мы видим, что все идет с префиксом foo$
, Во время прогноза:
newdata <- foo[1:2, ] ## take first 2 rows of "foo" as "newdata"
rm(foo) ## remove "foo" from R session
predict(toy, newdata)
мы получаем ошибку:
Ошибка в eval(expr, envir, enclos): объект 'foo' не найден
Хороший стиль - указать среду получения данных из data
аргумент функции:
foo <- data.frame(y = y, a = factor(a))
toy <- glm(y ~ a, data = foo)
затем foo$
уходит.
> toy$formula
y ~ a
> toy$xlevels
$a
[1] "a" "b" "c" "d"
Это объясняет две вещи:
- Вы пожаловались мне в комментарии, что когда вы делаете
testreg$xlevels$manufactureID
, ты получаешьNULL
; Ошибка прогноза, которую вы опубликовали
Error in model.frame.default(Terms, newdata, na.action=na.action, xlev=object$xlevels): Factor 'train$manufacturerID' has new levels 125, 136, 137
жалуется
train$manufacturerID
вместоtest$manufacturerID
,
Как вы разделили train
а также test
В выборке, основанной на числовых значениях, некоторые факторные уровни ваших переменных не одинаково представлены как в поездах, так и в тестовых выборках.
Вы должны сделать стратифицированную выборку, чтобы гарантировать, что и обучающая и тестовая выборки имеют все представления уровня фактора. использование stratified
от splitstackshape
пакет.