Предсказание.glm() с тремя новыми категориями в тестовых данных (r)(ошибка)

У меня есть набор данных под названием data который имеет 481 092 строки.

Я разделил data на две равные половины:

  1. Первая половина (строка 1: 240 546) называется train и был использован для glm();
  2. вторая половина (строка 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 рутина не может принять вашу индивидуальную формулу предсказания. Обычно есть два решения:

  1. извлечь матрицу модели и коэффициенты модели из testreg и вручную предсказывать нужные нам модельные термины путем умножения матрицы на вектор. Вот что предлагает сделать ссылка, приведенная в вашем посте;
  2. сбросить уровни факторов в 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"

Это объясняет две вещи:

  1. Вы пожаловались мне в комментарии, что когда вы делаете testreg$xlevels$manufactureID, ты получаешь NULL;
  2. Ошибка прогноза, которую вы опубликовали

    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 пакет.

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