Повторное использование модели, созданной в R - PullRequest
77 голосов
/ 25 февраля 2011

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

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

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

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

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

Ответы [ 2 ]

134 голосов
/ 25 февраля 2011

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

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

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

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

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

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

Если вы хотите обновить модель, используя дополнительные новые наблюдения.Тогда 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 или подобного.

7 голосов
/ 25 февраля 2011

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

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

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

...