首页 > 解决方案 > 在函数工厂创建的函数中调用 lm 时出现“找不到对象”

问题描述

我正在尝试建立一个通用框架来快速评估各种模型。我正在尝试使用工厂模式来生成“模型训练器”函数,这些函数采用数据框并返回经过训练的模型。lm但是,我在这个框架中遇到了 R 的内置函数的意外行为。

gen_lm_model_trainer <- function(formula, weights_col = NULL) {
  function(train_data) {
    trained_lm <- lm(formula = formula,
                     data = train_data,
                     weights = train_data[[weights_col]])

    pred_func <- function(test_data) {
      prediction <- predict(trained_lm, newdata = test_data)
      return(prediction)
    }

    return(list(predict = pred_func, info = trained_lm))
  }
}

mtcars$random_weights <- rbeta(nrow(mtcars), shape1 = 5, shape2 = 2)
trainer <- gen_lm_model_trainer(formula = mpg ~ ., weights_col = 'random_weights')
trained_model <- trainer(mtcars)

对此代码的响应如下:

Error in eval(extras, data, env) : object 'train_data' not found

这与另一个 SO 问题类似,Object not found error when passing model formula to another function,但是通过将公式的环境分配给生成的函数的环境并不能解决这个问题,即

gen_lm_model_trainer <- function(formula, weights_col = NULL) {
  function(train_data) {
    scoped_formula <- as.formula(formula, env = environment())
    trained_lm <- lm(formula = scoped_formula,
                     data = train_data,
                     weights = train_data[[weights_col]])

    pred_func <- function(test_data) {
      prediction <- predict(trained_lm, newdata = test_data)
      return(prediction)
    }

    return(list(predict = pred_func, info = trained_lm))
  }
}

一个对这两个问题都有效的解决方案将不胜感激。

标签: rfunctional-programmingfactoryenvironmentlm

解决方案


我找到了对这个问题的部分答案——部分是因为它只解决了这种情况,而不是链接的 SO 问题。问题似乎是 lm 的参数正在与调用对应的环境中进行评估with(train_data, lm(...))parent.frame()因此,使用它来遍历调用函数(“模型训练器”)的环境应该是安全的。这恰好对应于 n = 1 的深度——在这种情况下,我认为 n = 1 是数据框的环境,n = 2 是 eval 的环境,n = 3 是从中lm调用的环境。

gen_lm_model_trainer <- function(formula, weights_col = NULL) {
  function(train_data) {
    trained_lm <- lm(formula = formula,
                     data = train_data,
                     weights = get('train_data', parent.frame(3))[[get('weights_col', parent.frame(3))]])

    pred_func <- function(test_data) {
      prediction <- predict(trained_lm, newdata = test_data)
      return(prediction)
    }

    return(list(predict = pred_func, info = trained_lm))
  }
}

mtcars$random_weights <- rbeta(nrow(mtcars), shape1 = 5, shape2 = 2)
trainer <- gen_lm_model_trainer(formula = mpg ~ ., weights_col = 'random_weights')
trained_model <- trainer(mtcars)

我不清楚为什么lm如此不寻常地更改范围,并且似乎是一个错误。


推荐阅读