重用R中内置的模型

Bti*_*rt3 77 r models

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

我考虑过的事情:

  • 保存模型对象并加载到新会话中
  • 我知道有些模型可以用PMML导出,但还没有真正看到有关导入PMML的信息

简单地说,我试图了解当您需要在新会话中使用模型时所执行的操作.

提前致谢.

Rei*_*son 137

重用模型来预测新的观察结果

如果模型的计算成本不高,我倾向于在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 
Run Code Online (Sandbox Code Playgroud)

如果想要自动执行此操作,那么我可能会在脚本中执行以下操作:

## 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)
Run Code Online (Sandbox Code Playgroud)

当然,数据生成代码将被加载实际数据的代码所取代.

使用新观察更新先前安装的模型

如果要使用其他新观察值重新构建模型.然后update()是一个有用的功能.它所做的只是更新模型,更新一个或多个模型参数.如果要在用于拟合模型的数据中包含新观察值,请将新观察值添加到传递给参数的数据框中'data',然后执行以下操作:

m2 <- update(m1, . ~ ., data = df)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

其他在评论中提到,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)
Run Code Online (Sandbox Code Playgroud)

但是,如果模型拟合涉及更复杂的模型拟合函数中的其他参数'family',或者'subset'参数.如果update()方法可用于您的模型拟合函数(它们适用于许多常见的拟合函数glm()),则它提供了一种更简单的方法来更新模型拟合,而不是提取和重用模型公式.

如果您打算在R中进行所有建模和未来预测,那么通过PMML或类似方法抽象出模型似乎没什么意义.


Jor*_*eys 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)
Run Code Online (Sandbox Code Playgroud)

这是在没有任何数据准备等的情况下.它只是重用模型规范集.请注意,如果您在此期间更改对比度,新模型将使用新的对比更新,而不是旧对比.

所以在大多数情况下使用脚本是更好的答案.可以包括仅占用数据帧的便捷函数中的所有步骤,因此您可以获取脚本,然后在任何新数据集上使用该函数.另见Gavin的答案.