Как при построении модели в R сохранять спецификации модели, чтобы их можно было повторно использовать в новых данных? Допустим, я построил логистическую регрессию на исторических данных, но новых наблюдений не будет до следующего месяца. Какой лучший подход?

Вещи, которые я рассмотрел:

  • Сохранение объекта модели и загрузка в новом сеансе
  • Я знаю, что некоторые модели можно экспортировать с помощью PMML, но на самом деле ничего не видел об импорте PMML.

Просто я пытаюсь понять, что вы делаете, когда вам нужно использовать свою модель в новом сеансе.

87
Btibert3 25 Фев 2011 в 16:58
Что ж, вы всегда можете «сохранить» формулу модели и предоставить обновленные данные в аргументе data ... при условии, что я вас правильно понял ...
 – 
aL3xa
25 Фев 2011 в 17:20
Хм, что вы имеете в виду под повторным использованием? Спрогнозировать новые наблюдения или обновить модель, чтобы использовать новые наблюдения плюс старые?
 – 
Gavin Simpson
25 Фев 2011 в 17:24
@ Гэвин. Я хочу использовать разработанную мной модель для прогнозирования новых значений данных, которых у меня еще нет и которых может не быть в течение некоторого времени.
 – 
Btibert3
25 Фев 2011 в 17:58
1
Хорошо, тогда начальная часть моего ответа - это то, что я бы сделал. Сохранение объекта модели на диск более чем приемлемо, но важно сохранить код / ​​скрипт R, используемый для создания модели, в первую очередь, чтобы ваше исследование / моделирование было воспроизводимым.
 – 
Gavin Simpson
25 Фев 2011 в 18:09

2 ответа

Лучший ответ

Повторное использование модели для прогнозирования новых наблюдений

Если модель не требует больших вычислительных затрат, я стараюсь документировать весь процесс построения модели в сценарии R, который я повторно запускаю при необходимости. Если в подгонке модели участвует случайный элемент, я обязательно устанавливаю известное случайное начальное число.

Если вычисление модели требует больших вычислительных затрат, я все еще использую сценарий, как указано выше, но сохраняю объекты модели с помощью save() в и объект rda. Затем я стараюсь изменить сценарий таким образом, чтобы, если сохраненный объект существует, загрузить его или, если нет, обновить модель, используя простое предложение if()...else, обернутое вокруг соответствующих частей кода.

При загрузке сохраненного объекта модели обязательно перезагрузите все необходимые пакеты, хотя в вашем случае, если модель logit была подобрана через glm(), не будет никаких дополнительных пакетов для загрузки, кроме R.

Вот пример:

> set.seed(345)
> df <- data.frame(x = rnorm(20))
> df <- transform(df, y = 5 + (2.3 * x) + rnorm(20))
> ## model
> m1 <- lm(y ~ x, data = df)
> ## save this model
> save(m1, file = "my_model1.rda")
> 
> ## a month later, new observations are available: 
> newdf <- data.frame(x = rnorm(20))
> ## load the model
> load("my_model1.rda")
> ## predict for the new `x`s in `newdf`
> predict(m1, newdata = newdf)
        1         2         3         4         5         6 
6.1370366 6.5631503 2.9808845 5.2464261 4.6651015 3.4475255 
        7         8         9        10        11        12 
6.7961764 5.3592901 3.3691800 9.2506653 4.7562096 3.9067537 
       13        14        15        16        17        18 
2.0423691 2.4764664 3.7308918 6.9999064 2.0081902 0.3256407 
       19        20 
5.4247548 2.6906722 

Если бы я хотел автоматизировать это, я бы, вероятно, сделал в сценарии следующее:

## data
df <- data.frame(x = rnorm(20))
df <- transform(df, y = 5 + (2.3 * x) + rnorm(20))

## check if model exists? If not, refit:
if(file.exists("my_model1.rda")) {
    ## load model
    load("my_model1.rda")
} else {
    ## (re)fit the model
    m1 <- lm(y ~ x, data = df)
}

## predict for new observations
## new observations
newdf <- data.frame(x = rnorm(20))
## predict
predict(m1, newdata = newdf)

Конечно, код генерации данных будет заменен кодом, загружающим ваши фактические данные.

Обновление ранее подобранной модели новыми наблюдениями

Если вы хотите обновить модель, используя дополнительные новые наблюдения. Тогда update() - полезная функция. Все, что он делает, это обновляет модель, обновляя один или несколько аргументов модели. Если вы хотите включить новые наблюдения в данные, используемые для соответствия модели, добавьте новые наблюдения во фрейм данных, переданный в аргумент 'data', а затем выполните следующие действия:

m2 <- update(m1, . ~ ., data = df)

Где m1 - исходная сохраненная подгонка модели, . ~ . - изменения формулы модели, что в данном случае означает включение всех существующих переменных как с левой, так и с правой стороны ~ (в Другими словами, не вносите изменений в формулу модели), а df - это фрейм данных, используемый для соответствия исходной модели, расширенный для включения новых доступных наблюдений.

Вот рабочий пример:

> set.seed(123)
> df <- data.frame(x = rnorm(20))
> df <- transform(df, y = 5 + (2.3 * x) + rnorm(20))
> ## model
> m1 <- lm(y ~ x, data = df)
> m1

Call:
lm(formula = y ~ x, data = df)

Coefficients:
(Intercept)            x  
      4.960        2.222  

> 
> ## new observations
> newdf <- data.frame(x = rnorm(20))
> newdf <- transform(newdf, y = 5 + (2.3 * x) + rnorm(20))
> ## add on to df
> df <- rbind(df, newdf)
> 
> ## update model fit
> m2 <- update(m1, . ~ ., data = df)
> m2

Call:
lm(formula = y ~ x, data = df)

Coefficients:
(Intercept)            x  
      4.928        2.187

Другие упомянули в комментариях formula(), который извлекает формулу из подобранной модели:

> formula(m1)
y ~ x
> ## which can be used to set-up a new model call
> ## so an alternative to update() above is:
> m3 <- lm(formula(m1), data = df)

Однако, если подгонка модели включает дополнительные аргументы, такие как 'family' или 'subset' аргументы в более сложных функциях подбора модели. Если методы update() доступны для вашей функции подгонки модели (а они есть для многих распространенных функций подгонки, таких как glm()), это обеспечивает более простой способ обновления подгонки модели, чем извлечение и повторное использование формулы модели.

Если вы намереваетесь выполнять все моделирование и прогнозирование будущего в R, на самом деле нет особого смысла абстрагироваться от модели с помощью PMML или подобного.

148
Gavin Simpson 25 Фев 2011 в 18:19
1
+1, и если вы любезно воздержитесь от редактирования ваших ответов, чтобы они соответствовали тому ответу, который я готовил ... ;-)
 – 
Joris Meys
25 Фев 2011 в 18:22
Сука не предвидение! ;-) +1 для update от меня
 – 
Gavin Simpson
25 Фев 2011 в 18:38
1
Это действительно отличный ответ. Я надеюсь, что кто-то курирует такие ответы SO [r], как этот, и объединяет их в виде учебного пособия.
 – 
JD Long
25 Фев 2011 в 23:12
1
Отличный ответ. Спасибо за приведенные вами примеры.
 – 
nhern121
17 Ноя 2012 в 01:15
1
Именно то, что я искал. Хочу сделать +1000 ... Спасибо
 – 
Adjeiinfo
25 Авг 2015 в 07:45

Если вы используете то же имя фрейма данных и переменных, вы можете (по крайней мере, для lm() и glm()) использовать функцию update для сохраненной модели:

Df <- data.frame(X=1:10,Y=(1:10)+rnorm(10))

model <- lm(Y~X,data=Df)
model

Df <- rbind(Df,data.frame(X=2:11,Y=(10:1)+rnorm(10)))

update(model)

Это, конечно, без какой-либо подготовки данных и так далее. Он просто повторно использует набор спецификаций модели. Имейте в виду, что если вы тем временем измените контрасты, новая модель будет обновляться с новыми контрастами, а не старая.

Так что использование сценария в большинстве случаев является лучшим ответом. Можно было бы включить все шаги в удобную функцию, которая просто берет фрейм данных, чтобы вы могли создать скрипт, а затем использовать функцию в любом новом наборе данных. См. Также ответ Гэвина по этому поводу.

8
Joris Meys 25 Фев 2011 в 18:22