mlr3 regr.nnet 任务中的多次运行和交互项

Multiple runs and interaction terms in mlr3 regr.nnet task

提问人:tpetzoldt 提问时间:3/5/2023 最后编辑:tpetzoldt 更新时间:3/7/2023 访问量:105

问:

我正在尝试将一些教学示例从 nnetneuralnetranger 包移植到包 mlr3。我喜欢 mlr3 处理拟合模型的方式,例如模型评估、特征重要性或超参数优化,但在模型规范方面仍然存在一些问题。

在下面的示例中,我使用了一个人工数据集,该数据集由常见的密度函数和一些随机噪声构成:

library("dplyr", warn.conflicts = FALSE)
library("nnet")
library("mlr3")
library("mlr3learners")
library("ggplot2")
set.seed(123)

## observation data, functional pattern + some random noise
x <- 1:20
obs <- data.frame(
  x = rep(x, 3),
  f = factor(rep(c("A", "B", "C"), each = 20)),
  y = c(3 * dnorm(x, 10, 3), 5 * dlnorm(x, 2, 0.5), dexp(20-x, .5))
      + rnorm(60, sd = 0.02)
)

它可以配备一个带有 3 个隐藏神经元的小神经元,我在那里进行了相当多的试验,然后提取了最好的。当然,这是一种可能导致过度训练的蛮力方法,但这是示例的预期部分。nnet

nns <- lapply(1:100,
         \(foo) nnet(y ~ x * f, data = obs, size = 3, maxit=500, trace=FALSE))
nn <- nns[[which.min(lapply(nns, \(x) x$value))]]
nn
#> a 5-3-1 network with 22 weights
#> inputs: x fB fC x:fB x:fC 
#> output(s): y 
#> options were -

结果网络如预期的那样为 5-3-1,其中 1 个输入为 ,因子有 2 个水平 (= 3 - 1),交互作用有 2 个水平。 现在我想对 mlr3 和使用相同基函数的学习器重复此操作。xfregr.nnet

## workaround: resolve "unsupported feature types: integer"
obs$x <- as.double(obs$x)

## create task and train model
task    <- as_task_regr(obs, target = "y")
learner <- lrn("regr.nnet", size = 3, maxit = 500, trace = FALSE)
learner$train(task)
print(learner$model)
#> a 3-3-1 network with 16 weights
#> inputs: fB fC x 
#> output(s): y 
#> options were - linear output units

我们看到生成的模型只有 3 个输入,即没有交互输入。现在我们可以将模型与数据进行比较,发现第一个模型更好,因为它基于多次运行并考虑了交互作用:

pred_grid <- expand.grid(
  x = seq(0, 20, length.out=100),
  f = c("A", "B", "C"))

pred1 <-
  pred_grid |>
  mutate(y = predict(nn, newdata = pred_grid), method = "nnet basic")

pred2 <-
  pred_grid |>
  mutate(y = predict(learner, newdata = pred_grid), method = "nnet mlr")

ggplot(obs, aes(x, y)) + geom_point() +
  geom_line(data = rbind(pred1, pred2), mapping = aes(x, y, color = method)) +
  facet_wrap(~f)

我的问题

  1. 如何包含交互术语以及
  2. 是否有“最佳实践”选项来多次训练网络,即没有外部循环。由于 mlr3+ 使用 R6 类,因此可能需要克隆对象。

除此之外,我想知道是否可以避免将变量转换为 double 的解决方法。此外,如果 neuralnet 包也可以用作 mlr3 中的学习者,那就太好了。x

创建于 2023-03-05,使用 reprex v2.0.2

R MLR3 NNET

评论


答:

1赞 Sebastian 3/7/2023 #1

答案 1:(如何包含交互术语和)

因此,您面临的问题是 nnet 的参数未公开为超参数。我们在这一行中创建自动拟合的公式:https://github.com/mlr-org/mlr3learners/blob/856d1d016957c63929b8c8811aad4ad87bd7043a/R/LearnerClassifNnet.R#L71。 但是,在这种情况下,能够修改此公式非常重要,如示例所示。formula

出于这个原因,我在这里创建了一个拉取请求来解决这个问题。

答案 2:(是否有“最佳实践”选项可以多次训练网络,即没有外部循环。由于 mlr3+ 使用 R6 类,因此可能需要克隆对象。

实现此目的的一种方法确实是克隆学习器并使用该函数。benchmark()

library(mlr3learners)
#> Loading required package: mlr3

learner = lrn("regr.nnet")

lgr::get_logger("mlr3")$set_threshold("warn")

set.seed(123)
x = 1:20



obs = data.frame(
  x = rep(x, 3),
  f = factor(rep(c("a", "b", "c"), each = 20)),
  y = c(3 * dnorm(x, 10, 3), 5 * dlnorm(x, 2, 0.5), dexp(20 - x, .5)) + rnorm(60, sd = 0.02)
)

nrow(obs)
#> [1] 60

x_test = seq(0, 20, length.out = 100)
test = expand.grid(
  x = x_test,
  f = c("a", "b", "c"),
  y = c(3 * dnorm(x_test, 10, 3), 5 * dlnorm(x_test, 2, 0.5), dexp(20 - x_test, .5)) + rnorm(60, sd = 0.02)
)

dat = rbind(obs, test)

task = as_task_regr(dat, target = "y")
resampling = rsmp("custom")
resampling$instantiate(task, list(train = 1:60), test = list(61:90060))

learners = replicate(100, learner$clone())

design = benchmark_grid(
  tasks = task,
  learners = learners,
  resampling
)


bmr = benchmark(design)
#> LOG OUTPUT ...

创建于 2023-03-07 使用 reprex v2.0.2但是,推荐的方法还取决于您到底想对结果做什么。

答案 3(除此之外,我想知道是否可以避免将 x 变量转换为 double 的解决方法。

我不明白这个问题。你能详细说明一下吗?

问题 4:(此外,如果 neuralnet 包也可以用作 mlr3 中的学习器,那就太好了。

您可以在此处创建问题:https://github.com/mlr-org/mlr3extralearners

但请注意,我们很快就会正确支持 torch 包,通过它将成为使用 mlr3 训练神经网络的首选方式mlr3torch

评论

0赞 tpetzoldt 3/7/2023
很高兴将来有 mlr3torch 可用!如果从技术上讲是一个整数,则会出现问题 #3。如果没有解决方法,则调用 将返回: 。obs$xobs$x <- as.double(obs$x)learner$train(task)Error: <TaskRegr:obs> has the following unsupported feature types: integer
1赞 Sebastian 3/7/2023
好吧,这似乎也是实现中的一个问题。我们总是显式地注释学习者可以处理的特征类型(可通过 访问)。似乎我们忘了在这里添加,我将其添加到我上面链接的拉取请求中。感谢您报告此事!:)learner$feature_types"integer"
1赞 Sebastian 3/7/2023
我刚刚意识到我忘了显示 PR:github.com/mlr-org/mlr3learners/pull/264。合并后,您可以指定 nnet 学习器的公式。