r - 返回保存时如何清理函数闭包(环境)?
问题描述
我有一个这样的计算(请注意,这只是非常简化的缩减版本,最小的可重现示例!):
computation <- function() # simplified version!
{
# a lot of big matrices here....
big_matrix <- matrix(rnorm(2000*2000), nrow = 2000, ncol = 2000)
exp.value <- 4.5
prior <- function (x) rep(exp.value, nrow(x))
# after computation, it returns the model
list(
some_info = 5.18,
prior = prior
)
}
此函数适合并返回一个模型,我想将其保存到磁盘:
m <- computation()
save(m, file = "tmp.Rdata")
file.info("tmp.Rdata")$size
# [1] 30713946
不幸的是,如您所见,文件太大,因为它包含函数的整个闭包prior()
,而这个闭包包含computation()
函数的所有数据,包括big_matrix
(在我的完整代码中有很多数据)。
现在,我尝试通过使用以下方法重新定义先前函数的环境(闭包)来修复它environment(prior) <- list2env(list(exp.value = exp.value))
:
exp.value <- 4.5
environment(m$prior) <- list2env(list(exp.value = exp.value))
save(m, file = "tmp.Rdata")
file.info("tmp.Rdata")$size
# [1] 475
这按预期工作!不幸的是,当我将此清理代码放入计算()函数时(实际上,当我将此代码放入任何函数时),它停止工作!看:
computation <- function() # simplified version!
{
# a lot of big matrices here....
big_matrix <- matrix(rnorm(2000*2000), nrow = 2000, ncol = 2000)
exp.value <- 4.5
prior <- function (x) rep(exp.value, nrow(x))
environment(prior) <- list2env(list(exp.value = exp.value)) # this is the update
# after computation, it returns the model
list(
some_info = 5.18,
prior = prior
)
}
m <- computation()
save(m, file = "tmp.Rdata")
file.info("tmp.Rdata")$size
# [1] 30713151
文件又大了,关闭没有正确清理。
- 我不明白这是怎么回事?为什么清理代码在任何函数之外运行时都在工作,而在函数中时停止工作?
- 如何让它在函数内部工作?
解决方案
解决问题的一种方法是在返回之前从环境中删除大变量。
computation <- function()
{
big_matrix <- matrix(rnorm(2000*2000), nrow = 2000, ncol = 2000)
exp.value <- 4.5
prior <- function (x) rep(exp.value, nrow(x))
rm(big_matrix) ## remove variable
list(
some_info = 5.18,
prior = prior
)
}
您的list2env
方法的问题在于,默认情况下它指向当前环境作为新环境的父环境,因此无论如何您都在捕获函数内的所有内容。您可以改为将全局环境指定为基础环境
computation <- function()
{
big_matrix <- matrix(rnorm(2000*2000), nrow = 2000, ncol = 2000)
exp.value <- 4.5
prior <- function (x) rep(exp.value, nrow(x))
# explicit parent
environment(prior) <- list2env(list(exp.value = exp.value), parent=globalenv())
list(
some_info = 5.18,
prior = prior
)
}
(如果您指定emptyenv()
,那么您将无法找到类似的内置函数rep()
)
推荐阅读
- python - Python中字节的奇怪表示
- laravel - Laravel 一对多关系与 2 个主键
- excel - 如何比较字符串?
- java - Java Swing 会限制它绘制的项目数吗?
- python - 如何运行for循环然后在最后进行计算
- amazon-web-services - 以用户身份执行:xxxx\xxxxx。找不到配置文件 (xxxxxxx)。进程退出代码 255。步骤失败
- android - 在 Windows 7 中找不到 HAXM 设备
- java - CBC模式下的DES必须被捕获或抛出错误
- python - 熊猫 groupby 不返回预期的输出
- networking - 是否可以在不使用 VPN 的情况下将同一 LAN 上的多台远程机器互连?