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


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

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

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

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

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

2 63

2 ответа:

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

если модель не является вычислительно дорогостоящей, я склонен документировать весь процесс построения модели в 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 или аналогичного.

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

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

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