提问人:tpetzoldt 提问时间:3/5/2023 最后编辑:tpetzoldt 更新时间:3/7/2023 访问量:105
mlr3 regr.nnet 任务中的多次运行和交互项
Multiple runs and interaction terms in mlr3 regr.nnet task
问:
我正在尝试将一些教学示例从 nnet、neuralnet 和 ranger 包移植到包 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 和使用相同基函数的学习器重复此操作。x
f
regr.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)
我的问题
- 如何包含交互术语以及
- 是否有“最佳实践”选项来多次训练网络,即没有外部循环。由于 mlr3+ 使用 R6 类,因此可能需要克隆对象。
除此之外,我想知道是否可以避免将变量转换为 double 的解决方法。此外,如果 neuralnet 包也可以用作 mlr3 中的学习者,那就太好了。x
创建于 2023-03-05,使用 reprex v2.0.2
答:
答案 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
评论
obs$x
obs$x <- as.double(obs$x)
learner$train(task)
Error: <TaskRegr:obs> has the following unsupported feature types: integer
learner$feature_types
"integer"
评论