Повторное использование модели, построенной в R

82

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

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

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

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

Заранее спасибо.

Btibert3
источник
Что ж, вы всегда можете «сохранить» формулу модели и предоставить обновленные данные в dataаргументе ... при условии, что я вас правильно понял ...
aL3xa
Хм, что вы имеете в виду под повторным использованием? Спрогнозировать новые наблюдения или обновить модель, чтобы использовать новые наблюдения плюс старые?
Гэвин Симпсон
@ Гэвин. Я хочу использовать разработанную мной модель для прогнозирования новых значений данных, которых у меня еще нет и которых может не быть в течение некоторого времени.
Btibert3
1
@ Bitbert3 Хорошо, тогда начальный раздел моего ответа - это то, что я бы сделал. Сохранение объекта модели на диск более чем приемлемо, но важно сохранить код / ​​сценарий R, используемый для создания модели, в первую очередь, чтобы ваше исследование / моделирование было воспроизводимым.
Гэвин Симпсон

Ответы:

144

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

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

Если вычисление модели требует больших вычислительных затрат, я все равно использую сценарий, как указано выше, но сохраняю объекты модели, используя save()объект into и 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 или подобного.

Гэвин Симпсон
источник
1
+1 и если вы любезно воздержитесь от редактирования ваших ответов, чтобы они соответствовали тому ответу, который я готовил ... ;-)
Joris Meys
@ Джорис не сука предвидение! ;-) +1 для updateменя
Gavin Simpson
1
Это действительно отличный ответ. Я надеюсь, что кто-то курирует такие ответы SO [r], как этот, и объединяет их в качестве учебного пособия.
JD Long
1
Отличный ответ. Спасибо за приведенные вами примеры.
nhern121
1
Именно то, что я искал. Я хочу сделать +1000 ... Спасибо
Adjeiinfo
7

Если вы используете то же имя фрейма данных и переменных, вы можете (по крайней мере, для 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)

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

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

Джорис Мейс
источник