Как при построении модели в R сохранять спецификации модели, чтобы их можно было повторно использовать в новых данных? Допустим, я построил логистическую регрессию на исторических данных, но новых наблюдений не будет до следующего месяца. Какой лучший подход?
Вещи, которые я рассмотрел:
- Сохранение объекта модели и загрузка в новом сеансе
- Я знаю, что некоторые модели можно экспортировать с помощью PMML, но на самом деле ничего не видел об импорте PMML.
Просто я пытаюсь понять, что вы делаете, когда вам нужно использовать свою модель в новом сеансе.
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 или подобного.
update
от меня
Если вы используете то же имя фрейма данных и переменных, вы можете (по крайней мере, для 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)
Это, конечно, без какой-либо подготовки данных и так далее. Он просто повторно использует набор спецификаций модели. Имейте в виду, что если вы тем временем измените контрасты, новая модель будет обновляться с новыми контрастами, а не старая.
Так что использование сценария в большинстве случаев является лучшим ответом. Можно было бы включить все шаги в удобную функцию, которая просто берет фрейм данных, чтобы вы могли создать скрипт, а затем использовать функцию в любом новом наборе данных. См. Также ответ Гэвина по этому поводу.
Похожие вопросы
Связанные вопросы
Новые вопросы
r
R — это бесплатный язык программирования с открытым исходным кодом и программная среда для статистических вычислений, биоинформатики, визуализации и общих вычислений. Пожалуйста, используйте минимально воспроизводимые примеры, которые другие могут запустить с помощью копирования и вставки. Показать желаемый результат полностью. Используйте dput() для данных и укажите все небазовые пакеты с помощью library(). Не вставляйте изображения для данных или кода, вместо этого используйте блоки кода с отступом. Для вопросов по статистике используйте https://stats.stackexchange.com.
data
... при условии, что я вас правильно понял ...