Повторне використання моделі, вбудованої в R


83

Створюючи модель у R, як ви зберігаєте специфікації моделі, щоб ви могли повторно використовувати її на нових даних? Скажімо, я будую логістичну регресію на історичних даних, але нових спостережень не матиму до наступного місяця. Який найкращий підхід?

Речі, які я розглядав:

  • Збереження об’єкта моделі та завантаження у новому сеансі
  • Я знаю, що деякі моделі можна експортувати за допомогою PMML, але насправді я нічого не бачив про імпорт PMML

Просто я намагаюся зрозуміти, що ви робите, коли вам потрібно використовувати свою модель у новому сеансі.

Заздалегідь спасибі.


Ну, ви завжди можете "зберегти" формулу моделі та надати оновлені дані в dataаргументі ... припускаючи, що я вас правильно зрозумів ...
aL3xa

Хм, що ви маєте на увазі під повторним використанням? Прогнозувати нові спостереження або оновити модель, придатну для використання нових спостережень та старих?
Gavin Simpson

@Gavin. Я хочу використовувати модель, яку я розробив, для прогнозування нових значень на даних, яких я ще не маю і може не мати їх деякий час.
Btibert3

1
@ Bitbert3 Гаразд, тоді вступний розділ моєї відповіді - це те, що я б зробив. Зберігання об’єкта моделі на диску є більш ніж прийнятним, але важливо зберегти код / ​​скрипт R, використаний для створення моделі, в першу чергу, щоб ваші дослідження / моделювання були відтворюваними.
Gavin Simpson

Відповіді:


144

Повторне використання моделі для прогнозування нових спостережень

Якщо модель не є обчислювально обчислюваною, я схильний документувати весь процес побудови моделі сценарієм R, який я повторюю за необхідності. Якщо у підгонці моделі бере участь випадковий елемент, я обов’язково встановлюю відоме випадкове насіння.

Якщо модель обчислювально обчислювальна, тоді я все ще використовую сценарій, як зазначено вище, але зберігаю об'єкти моделі, використовуючи save() in і 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

@Joris не сука передвизнання! ;-) +1 для updateвід мене
Гавін Сімпсон

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)

Це звичайно, без будь-якої підготовки даних тощо. Він просто повторно використовує встановлені специфікації моделі. Майте на увазі, що якщо ви тим часом зміните контрасти, нова модель оновлюється новими контрастами, а не старою.

Тож використання сценарію в більшості випадків є кращою відповіддю. Можна включити всі кроки у зручну функцію, яка просто бере кадр даних, так що ви можете створити скрипт, а потім використовувати функцію на будь-якому новому наборі даних. Дивіться також відповідь Гевіна на це.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.