R 属性“.Environment”在 nnet 包中消耗大量 RAM

R attribute ".Environment" consuming large amounts of RAM in nnet package

我有一段使用 nnet 包的代码,我有兴趣计算许多不同的神经网络模型,然后将所有模型保存到磁盘(使用 save() )。

我 运行 遇到的问题是神经网络中的 "terms" 元素有一个属性“.Environment”,它最终达到数百兆字节,而模型的其余部分是只有几千字节。 (一旦拟合值和残差被删除)

此外,删除“.Environment”属性似乎不会导致在 'predict' 中使用模型方面的问题。

有谁知道 R 或 nnet 使用此属性做什么?有人见过这样的东西吗?

tl;dr:这没问题,除了一些非常特殊的情况

背景

R 中的 .Environment 属性包含对上下文的引用,其中 R closure(通常是 公式 函数 ) 被定义。 R 环境是存储变量值的存储,类似于列表。这允许公式引用这些变量,例如:

> f = function(g) return(y ~ g(x))
> form = f(exp)
> lm(form, list(y=1:10, x=log(1:10)))
...
Coefficients:
(Intercept)     g(x)
3.37e-15        1.00e+00

在此示例中,公式 form 如果定义为 y~exp(x),则通过为 g 赋予 exp 的值。为了能够找到 g 的值(它是函数 f 的参数),公式需要保存对函数 f 调用中构造的环境的引用.

您可以使用 attributes()environment() 函数查看附加到公式的环境,如下所示:

> attributes(form)
$class
[1] "formula"

$.Environment
<environment: R_GlobalEnv>

> environment(form)
<environment: R_GlobalEnv>

你的问题

我相信您正在使用带有公式(而不是矩阵)的 nnet() 函数变体,即

> nnet(y ~ x1 + x2, ...)

不幸的是,R 保留了整个环境(包括在定义公式的地方定义的所有变量)分配,即使您的公式没有引用其中任何一个。语言无法轻松判断您可能会或可能不会从环境中使用什么。

One solution就是明确的只保留环境需要的部分。特别是,如果您的公式未引用环境中的任何内容(这是最常见的情况),则可以安全地删除它。

我建议在调用 nnet 之前从公式中删除环境,如下所示:

    form = y~x + z
    environment(form) = NULL
    ...
    result = nnet(form, ...)