如何在mlr3torch中动态调优神经网络的层数?
在mlr3torch中动态调优神经网络层数
要实现动态调整神经网络层数+保留每层参数独立调优的需求,核心思路是通过自定义神经网络构建函数,结合mlr3的参数依赖机制来实现。以下是具体解决方案:
核心实现思路
- 自定义一个神经网络构建函数,接收
num_layers参数来动态生成对应数量的隐藏层。 - 为每个可能的层定义独立的调优参数(神经元数量、dropout比例),并通过参数依赖控制仅在层数满足条件时启用这些参数。
- 将自定义构建函数封装为
TorchModelClassif,转换为可调优的Learner后进行超参数优化。
完整可运行代码
# 加载必要库 if (!require("pacman")) install.packages("pacman") pacman::p_load( future, future.apply, magrittr, mlr3hyperband, mlr3torch, mlr3tuning, mlr3verse, tidyverse, install = TRUE ) torch::install_torch() # 设置随机种子 seed = 2024 set.seed(seed) # 准备数据集 tab <- iris colnames(tab)[which(names(tab) == "Species")] <- "target" tab$target <- as.factor(tab$target) # 创建分类任务 task <- TaskClassif$new(id = "iris", backend = tab, target = "target") # 定义动态神经网络构建函数 build_dynamic_nn <- function(input_dim, num_classes, num_layers, out_features_1, out_features_2, out_features_3, out_features_4, out_features_5, dropout_p_1, dropout_p_2, dropout_p_3, dropout_p_4, dropout_p_5) { # 收集所有层参数 out_features_list <- c(out_features_1, out_features_2, out_features_3, out_features_4, out_features_5) dropout_p_list <- c(dropout_p_1, dropout_p_2, dropout_p_3, dropout_p_4, dropout_p_5) layers <- list() current_dim <- input_dim # 动态生成指定数量的隐藏层 for (i in 1:num_layers) { layers[[length(layers)+1]] <- torch::nn_linear(current_dim, out_features_list[i]) layers[[length(layers)+1]] <- torch::nn_dropout(dropout_p_list[i]) layers[[length(layers)+1]] <- torch::nn_relu() current_dim <- out_features_list[i] } # 添加输出层 layers[[length(layers)+1]] <- torch::nn_linear(current_dim, num_classes) return(torch::nn_sequential(!!!layers)) } # 创建自定义Torch模型,包含参数依赖 custom_model <- TorchModelClassif$new( build = build_dynamic_nn, param_set = ps( num_layers = p_int(lower = 1, upper = 5), # 各层神经元数量,仅当层数达标时启用 out_features_1 = p_int(lower = 32, upper = 512), out_features_2 = p_int(lower = 32, upper = 512, deps = quote(num_layers >=2)), out_features_3 = p_int(lower = 32, upper = 512, deps = quote(num_layers >=3)), out_features_4 = p_int(lower = 32, upper = 512, deps = quote(num_layers >=4)), out_features_5 = p_int(lower = 32, upper = 512, deps = quote(num_layers >=5)), # 各层dropout比例,仅当层数达标时启用 dropout_p_1 = p_dbl(lower = 0.3, upper = 0.5), dropout_p_2 = p_dbl(lower = 0.3, upper = 0.5, deps = quote(num_layers >=2)), dropout_p_3 = p_dbl(lower = 0.3, upper = 0.5, deps = quote(num_layers >=3)), dropout_p_4 = p_dbl(lower = 0.3, upper = 0.5, deps = quote(num_layers >=4)), dropout_p_5 = p_dbl(lower = 0.3, upper = 0.5, deps = quote(num_layers >=5)), # 其他调优参数 lr = p_dbl(lower = 0.001, upper = 0.01), epochs = p_int(lower = 100, upper = 1000, tags = "budget") ) ) # 转换为可训练的Learner learner <- as_learner(custom_model) learner$id <- "dynamic_nn_iris" learner$predict_type <- "prob" # 固定非调优参数 learner$param_set$values$seed <- seed learner$param_set$values$batch_size <- 32 learner$param_set$values$device <- "cpu" learner$param_set$values$num_threads <- 1 # 标记需要调优的参数 learner$param_set$values$num_layers <- to_tune() learner$param_set$values$out_features_1 <- to_tune() learner$param_set$values$out_features_2 <- to_tune() learner$param_set$values$out_features_3 <- to_tune() learner$param_set$values$out_features_4 <- to_tune() learner$param_set$values$out_features_5 <- to_tune() learner$param_set$values$dropout_p_1 <- to_tune() learner$param_set$values$dropout_p_2 <- to_tune() learner$param_set$values$dropout_p_3 <- to_tune() learner$param_set$values$dropout_p_4 <- to_tune() learner$param_set$values$dropout_p_5 <- to_tune() learner$param_set$values$lr <- to_tune() learner$param_set$values$epochs <- to_tune() # 定义调优实例 terminator <- trm("evals", n_evals = 100) resampling <- rsmp("cv", folds = 5) instance <- ti( task = task, learner = learner, resampling = resampling, measure = msr("classif.bacc"), terminator = terminator ) # 使用Hyperband进行超参数优化 tuner <- tnr("hyperband", eta = 3, repetitions = 1) num_threads = 8 future::plan(multisession, workers = num_threads) tuner$optimize(instance)
关键细节说明
- 动态层生成:
build_dynamic_nn函数根据num_layers参数循环生成对应数量的隐藏层,每层包含线性层、dropout和ReLU激活。 - 参数依赖:通过
deps参数定义各层参数的启用条件(如out_features_2仅在num_layers >=2时生效),减少无效的参数搜索空间。 - 独立调优能力:每个层的神经元数量和dropout比例都作为独立参数,调优器会为不同层数组合搜索最优的层参数配置。
内容的提问来源于stack exchange,提问作者Livio Antonielli
相关产品推荐
相关产品推荐

