重用R中内置的模型


82

在R中建立模型时,如何保存模型规格,以便可以在新数据上重用它?假设我在历史数据上建立了逻辑回归,但直到下个月才有新的观察结果。最好的方法是什么?

我考虑过的事情:

  • 保存模型对象并在新会话中加载
  • 我知道某些模型可以使用PMML导出,但是对于导入PMML并没有真正了解

简单来说,当您需要在新的会话中使用模型时,我试图了解您的工作。

提前致谢。


好吧,您始终可以“保存”模型公式,并在data参数中提供更新的数据……假设我正确理解了您的情况……
aL3xa 2011年

嗯,重用是什么意思?预测新的观测值或更新模型以使用新的观测值加上旧的观测值?
加文·辛普森,

@加文 我想使用我开发的模型来预测数据,这些数据我还没有并且可能已经有一段时间没有了。
Btibert3 2011年

1
@ Bitbert3好,那么我的答案的开头部分就是我要做的。将模型对象保存到磁盘上是可以接受的,但是首先保存用于生成模型的R代码/脚本很重要,这样可以重现您的研究/建模。
加文·辛普森

Answers:


143

重用模型来预测新观测

如果模型的计算成本不高,我倾向于在需要时重新运行的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()是一个有用的功能。它所做的只是用更新的一个或多个模型参数来调整模型。如果要在用于拟合模型的数据中包括新的观测值,请将新的观测值添加到传递给arguments的数据框中'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不会是个a子!;-)为update我+1
加文·辛普森

1
这是一个非常好的答案。我希望有人策划这样的SO [r]答案,并将它们汇总为一个教程。
JD Long

1
极好的答案。感谢您提供的示例。
nhern121

1
正是我想要的。我想做+1000 ...谢谢
Adjeiinfo,2015年

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)

没有任何数据准备等等,这是不可能的。它只是重用模型规范集。请注意,如果您同时更改对比度,则新模型将使用新的对比度而不是旧的进行更新。

因此,在大多数情况下,使用脚本是更好的答案。一个可能包含便利功能的所有步骤,该便利功能仅采用数据框,因此您可以获取脚本,然后在任何新数据集中使用该功能。另请参阅加文的答案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.