当前位置:  开发笔记 > 编程语言 > 正文

如何正确地"拟合"拟合的线性模型(通过`lm`)到ASCII文件并在以后重新创建?

如何解决《如何正确地"拟合"拟合的线性模型(通过`lm`)到ASCII文件并在以后重新创建?》经验,为你挑选了1个好方法。

我想将一个lm对象持久化到一个文件并将其重新加载到另一个程序中.我知道我可以通过saveRDS/ 写入/读取二进制文件来做到这一点readRDS,但我希望有一个ASCII文件而不是二进制文件.在更一般的层面上,我想知道为什么我在dput输出中阅读的习语一般不符合我的预期.

下面是简单拟合的示例,以及模型的成功和不成功的重新创建:

dat_train <- data.frame(x=1:4, z=c(1, 2.1, 2.9, 4))
fit <- lm(z ~ x, dat_train)
rm(dat_train) # Just to make sure fit is not dependent upon `dat_train existence`

dat_score <- data.frame(x=c(1.5, 3.5))

## This works (of course)
predict(fit, dat_score)
#    1    2 
# 1.52 3.48

保存到二进制文件工作:

## http://stackoverflow.com/questions/5118074/reusing-a-model-built-in-r
saveRDS(fit, "model.RDS")
fit2 <- readRDS("model.RDS")
predict(fit2, dat_score)
#    1    2 
# 1.52 3.48

这样做(dput它在R会话中不是文件):

fit2 <- eval(dput(fit))
predict(fit2, dat_score)
#    1    2 
# 1.52 3.48

但是,如果我将文件保存到磁盘,我无法弄清楚如何恢复正常形状:

dput(fit, file = "model.R")
fit3 <- source("model.R")$value

# Error in is.data.frame(data): object 'dat_train' not found

predict(fit3, dat_score)
# Error in predict(fit3, dat_score): object 'fit3' not found

试图明确表示eval不起作用:

## http://stackoverflow.com/questions/9068397/import-text-file-as-single-character-string
dput(fit, file="model.R")
fit4 <- eval(parse(text=paste(readLines("model.R"), collapse=" ")))

# Error in is.data.frame(data): object 'dat_train' not found

predict(fit4, dat_score)
# Error in predict(fit4, dat_score): object 'fit4' not found

在上面的两种情况中,我都希望fit3并且fit4两者都能工作,但是它们不会重新编译成lm我可以使用的对象predict().

任何人都可以告诉我如何将模型保存到具有类似structure(...)ASCII结构的文件中,然后将其重新读回作为lm我可以使用的对象predict()?为什么我目前的方法不起作用?



1> 李哲源..:

步骤1:

您需要控制解析选项:

dput(fit, control = c("quoteExpressions", "showAttributes"), file = "model.R") 

您可以阅读有关所有可能选项的更多信息?.deparseOpts.


"quoteExpressions"包含所有调用/表达式/语言quote,以便在以后重新解析它们时不会对它们进行求值.注意:

source 正在解析;

call 拟合的"lm"对象中的字段是一个调用:

fit$call
# lm(formula = z ~ x, data = dat_train)

因此,如果没有"quoteExpressions",R将尝试lm在解析期间评估调用.如果我们对它进行评估,那么它就是拟合线性模型,而R将旨在找到dat_train,这将在您的新R会话中不存在.


"showAttributes"是另一个强制选项,因为"lm"对象具有类属性.你当然不想丢弃所有的类属性,只导出一个简单的"列表"对象,对吧?此外,"lm"对象中的许多元素,如model(模型框架),qr(紧凑的QR矩阵)和terms(术语信息)等都具有属性.你想要保留所有这些.


如果未设置control,则默认设置为:

control = c("keepNA", "keepInteger", "showAttributes")

将会被使用.如你所见,没有"quoteExpressions",所以你会遇到麻烦.

你也可以指定"keepInteger"和"keepNA",但我不认为需要"lm"对象.

------

第2步:

上面的步骤将source正常工作.您可以恢复您的模型:

fit1 <- source("model.R")$value

但是,它还没有为像summarypredict工作这样的通用功能做好准备.为什么?

关键问题是terms对象fit1并不是一个真正的"术语"对象,而只是一个公式(它甚至不是一个公式,而只是一个没有"公式"类的"语言"对象!).只是比较fit$termsfit1$terms,你会看到其中的差别.不要惊讶; 我们之前设置了"quoteExpressions".虽然这对于防止评估肯定是有帮助的call,但它有副作用terms.所以我们需要尽可能地重建terms.

幸运的是,它足以做到:

fit1$terms <- terms.formula(fit1$terms)

虽然这仍然无法恢复所有信息fit$terms(如缺少变量类),但它很容易成为有效的"术语"对象.

为什么"条款"对象至关重要?因为所有通用功能都依赖于它.你可能不需要了解更多,因为它真的是技术性的,所以我会停在这里.

完成后,我们可以成功使用predict(summary也是):

predict(fit1)  ## no `newdata` given, using model frame `fit1$model`
#   1    2    3    4 
#1.03 2.01 2.99 3.97 

predict(fit1, dat_score)  ## with `newdata`
#   1    2 
#1.52 3.48 

-------

结论说:

虽然我已经向您展示了如何让事情发挥作用,但我并不建议您这样做.将模型拟合到大型数据集时,"lm"对象将非常大,例如residuals,fitted.values是长矢量,qr并且model是巨大的矩阵/数据帧.所以想想这个.

推荐阅读
李桂平2402851397
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有