From dc1a1198d11378a355f1d03dc467ad0b5bfaf655 Mon Sep 17 00:00:00 2001 From: "srishti.dutta1111" Date: Fri, 10 Jul 2026 16:02:24 +0530 Subject: [PATCH 1/3] Preallocate lists and vectors before iteration loops (#335) --- NEWS.md | 1 + R/dataset-cityscapes.R | 11 +++--- R/folder-dataset.R | 16 ++++---- R/models-convnext_segmentation.R | 6 +-- R/models-deeplabv3.R | 4 +- R/models-efficientnet.R | 10 +++-- R/models-efficientnetv2.R | 14 +++---- R/models-faster_rcnn.R | 42 +++++++++++---------- R/models-lw_detr.R | 8 ++-- R/models-mask_rcnn.R | 4 +- R/models-mobilenetv3.R | 52 ++++++++++++-------------- R/models-mobilenetv3_large.R | 19 +++++----- R/models-resnet.R | 2 +- R/models-rfdetr_detection.R | 64 ++++++++++++++++---------------- R/models-vgg.R | 23 +++++++++--- 15 files changed, 146 insertions(+), 130 deletions(-) diff --git a/NEWS.md b/NEWS.md index 43da4fe8..c6da3cee 100644 --- a/NEWS.md +++ b/NEWS.md @@ -16,6 +16,7 @@ ## Bug fixes and improvements * `nms()` now uses `torchvisionlib::ops_nms()` when torchvisionlib is installed, speeding up inference for `model_fasterrcnn_*()` and `model_maskrcnn_*()` (#321, #322). +* Lists and vectors that are filled in a loop are now preallocated to their target size instead of being grown one element at a time (@srishtiii28, #335). ## New Features diff --git a/R/dataset-cityscapes.R b/R/dataset-cityscapes.R index 33d6a83e..7b6b9130 100644 --- a/R/dataset-cityscapes.R +++ b/R/dataset-cityscapes.R @@ -229,18 +229,17 @@ cityscapes_dataset <- torch::dataset( } # Collect all images from all cities - images <- character(0) - for (city in cities) { - city_path <- file.path(img_dir, city) - city_imgs <- list.files( + images <- vector("list", length(cities)) + for (i in seq_along(cities)) { + city_path <- file.path(img_dir, cities[i]) + images[[i]] <- list.files( city_path, pattern = "_leftImg8bit\\.png$", full.names = TRUE ) - images <- c(images, city_imgs) } - sort(images) + sort(unlist(images)) }, get_target_path = function(img_path, target_type) { diff --git a/R/folder-dataset.R b/R/folder-dataset.R index 64d0fba2..d214047e 100644 --- a/R/folder-dataset.R +++ b/R/folder-dataset.R @@ -28,11 +28,13 @@ folder_make_dataset <- function(directory, class_to_idx, extensions = NULL, is_v } } - paths <- c() - indexes <- c() + target_classes <- sort(names(class_to_idx)) + paths <- vector("list", length(target_classes)) + indexes <- vector("list", length(target_classes)) - for (target_class in sort(names(class_to_idx))) { + for (i in seq_along(target_classes)) { + target_class <- target_classes[i] class_index <- class_to_idx[target_class] target_dir <- fs::path_join(c(directory, target_class)) @@ -42,13 +44,13 @@ folder_make_dataset <- function(directory, class_to_idx, extensions = NULL, is_v fnames <- fs::dir_ls(target_dir, recurse = TRUE) fnames <- fnames[is_valid_file(fnames)] - paths <- c(paths, fnames) - indexes <- c(indexes, rep(class_index, length(fnames))) + paths[[i]] <- fnames + indexes[[i]] <- rep(class_index, length(fnames)) } list( - paths, - indexes + unlist(paths), + unlist(indexes) ) } diff --git a/R/models-convnext_segmentation.R b/R/models-convnext_segmentation.R index f645fb59..c2008575 100644 --- a/R/models-convnext_segmentation.R +++ b/R/models-convnext_segmentation.R @@ -161,7 +161,7 @@ ppm_module <- torch::nn_module( }, forward = function(x) { target_size <- x$shape[3:4] - ppm_outs <- list() + ppm_outs <- vector("list", length(self$stages)) for (i in seq_along(self$stages)) { ppm_out <- self$stages[[i]](x) @@ -241,7 +241,7 @@ upernet_head <- torch::nn_module( inputs <- list(features$c2, features$c3, features$c4, features$c5) # Build laterals - laterals <- list() + laterals <- vector("list", 4) for (i in 1:3) { laterals[[i]] <- self$lateral_convs[[i]](inputs[[i]]) } @@ -260,7 +260,7 @@ upernet_head <- torch::nn_module( } # Build FPN outputs - fpn_outs <- list() + fpn_outs <- vector("list", 4) for (i in 1:3) { fpn_outs[[i]] <- self$fpn_convs[[i]](laterals[[i]]) } diff --git a/R/models-deeplabv3.R b/R/models-deeplabv3.R index da904741..57506bfc 100644 --- a/R/models-deeplabv3.R +++ b/R/models-deeplabv3.R @@ -161,7 +161,7 @@ aspp_module <- torch::nn_module( }, forward = function(x) { input_size <- x$shape[3:4] # Get height and width dimensions - res <- list() + res <- vector("list", length(self$convs)) for (i in 1:(length(self$convs) - 1)) { res[[i]] <- self$convs[[i]](x) @@ -170,7 +170,7 @@ aspp_module <- torch::nn_module( global_feat <- self$convs[[length(self$convs)]](x) target_size <- as.integer(input_size) global_feat <- nnf_interpolate(global_feat, size = target_size, mode = "bilinear", align_corners = FALSE) - res[[length(res) + 1]] <- global_feat + res[[length(res)]] <- global_feat x <- torch_cat(res, dim = 2) self$project(x) diff --git a/R/models-efficientnet.R b/R/models-efficientnet.R index fe72916d..676f7e67 100644 --- a/R/models-efficientnet.R +++ b/R/models-efficientnet.R @@ -177,13 +177,15 @@ efficientnet <- torch::nn_module( as.integer(ceiling(depth_coefficient * repeats)) } out_channels <- round_filters(32) - features <- list(conv_norm_act(3, out_channels, stride = 2, norm_layer = norm_layer, activation_layer = torch::nn_silu)) + features <- vector("list", length(b0_cfg) + 1) + features[[1]] <- conv_norm_act(3, out_channels, stride = 2, norm_layer = norm_layer, activation_layer = torch::nn_silu) in_channels <- out_channels - for (cfg in b0_cfg) { + for (cfg_idx in seq_along(b0_cfg)) { + cfg <- b0_cfg[[cfg_idx]] oc <- round_filters(cfg$channels) r <- round_repeats(cfg$repeats) - stage_blocks <- list() + stage_blocks <- vector("list", r) for (i in 1:r) { s <- ifelse(i == 1, cfg$stride, 1) stage_blocks[[i]] <- mbconv_block(in_channels, oc, @@ -191,7 +193,7 @@ efficientnet <- torch::nn_module( se_ratio = 0.25, norm_layer = norm_layer) in_channels <- oc } - features[[length(features) + 1]] <- torch::nn_sequential(!!!stage_blocks) + features[[cfg_idx + 1]] <- torch::nn_sequential(!!!stage_blocks) } final_channels <- round_filters(1280) diff --git a/R/models-efficientnetv2.R b/R/models-efficientnetv2.R index 56230e1d..9953082e 100644 --- a/R/models-efficientnetv2.R +++ b/R/models-efficientnetv2.R @@ -88,17 +88,17 @@ efficientnet_v2 <- torch::nn_module( if (is.null(norm_layer)) norm_layer <- torch::nn_batch_norm2d - features <- list( - conv_norm_act(3, firstconv_out, stride = 2, - norm_layer = norm_layer, activation_layer = torch::nn_silu) - ) + features <- vector("list", length(cfgs) + 1) + features[[1]] <- conv_norm_act(3, firstconv_out, stride = 2, + norm_layer = norm_layer, activation_layer = torch::nn_silu) in_channels <- firstconv_out - for (cfg in cfgs) { + for (cfg_idx in seq_along(cfgs)) { + cfg <- cfgs[[cfg_idx]] oc <- cfg$channels r <- cfg$repeats block_fn <- if (identical(cfg$block, "fused")) fused_mbconv_block else mbconv_block - stage_blocks <- list() + stage_blocks <- vector("list", r) for (i in seq_len(r)) { s <- ifelse(i == 1, cfg$stride, 1) if (identical(cfg$block, "fused")) { @@ -115,7 +115,7 @@ efficientnet_v2 <- torch::nn_module( } in_channels <- oc } - features[[length(features) + 1]] <- torch::nn_sequential(!!!stage_blocks) + features[[cfg_idx + 1]] <- torch::nn_sequential(!!!stage_blocks) } final_channels <- 1280 diff --git a/R/models-faster_rcnn.R b/R/models-faster_rcnn.R index 04cfd36a..5663e708 100644 --- a/R/models-faster_rcnn.R +++ b/R/models-faster_rcnn.R @@ -6,8 +6,8 @@ rpn_head <- torch::nn_module( self$bbox_pred <- nn_conv2d(in_channels, num_anchors * 4, kernel_size = 1) }, forward = function(features) { - objectness_list <- list() - bbox_reg_list <- list() + objectness_list <- vector("list", length(features)) + bbox_reg_list <- vector("list", length(features)) for (i in seq_along(features)) { x <- features[[i]] @@ -38,8 +38,8 @@ rpn_head_v2 <- torch::nn_module( self$bbox_pred <- nn_conv2d(in_channels, num_anchors * 4, kernel_size = 1, bias = TRUE) }, forward = function(features) { - objectness_list <- list() - bbox_reg_list <- list() + objectness_list <- vector("list", length(features)) + bbox_reg_list <- vector("list", length(features)) for (i in seq_along(features)) { x <- features[[i]] @@ -60,13 +60,13 @@ rpn_head_mobilenet <- torch::nn_module( self$bbox_pred <- nn_conv2d(in_channels, num_anchors * 4, kernel_size = 1) }, forward = function(features) { - objectness <- list() - bbox_deltas <- list() + objectness <- vector("list", length(features)) + bbox_deltas <- vector("list", length(features)) - for (x in features) { - t <- nnf_relu(self$conv(x)) - objectness[[length(objectness) + 1]] <- self$cls_logits(t) - bbox_deltas[[length(bbox_deltas) + 1]] <- self$bbox_pred(t) + for (i in seq_along(features)) { + t <- nnf_relu(self$conv(features[[i]])) + objectness[[i]] <- self$cls_logits(t) + bbox_deltas[[i]] <- self$bbox_pred(t) } list(objectness = objectness, bbox_deltas = bbox_deltas) @@ -83,13 +83,15 @@ generate_level_anchors <- function(h, w, stride, base_sizes = c(32, 64, 128, 256 shift_grid <- torch_stack(list(shifts[[1]], shifts[[2]], torch_zeros_like(shifts[[1]]), torch_zeros_like(shifts[[2]])), dim = 3)$unsqueeze(3) # [H, W, 1, 4] # Create anchors for each combination of base_size and aspect_ratio - anchor_list <- list() + anchor_list <- vector("list", length(base_sizes) * length(aspect_ratios)) + k <- 0L for (base_size in base_sizes) { for (ratio in aspect_ratios) { w_anchor <- base_size * sqrt(ratio) h_anchor <- base_size / sqrt(ratio) - anchor_list[[length(anchor_list) + 1]] <- c(w_anchor, h_anchor) + k <- k + 1L + anchor_list[[k]] <- c(w_anchor, h_anchor) } } @@ -472,7 +474,7 @@ fpn_module <- torch::nn_module( names(inputs) <- c("c2", "c3", "c4", "c5") last_inner <- self$inner_blocks[[4]](inputs$c5) - results <- list() + results <- vector("list", 4) results[[4]] <- self$layer_blocks[[4]](last_inner) for (i in 3:1) { @@ -571,7 +573,7 @@ fasterrcnn_model <- torch::nn_module( batch_size <- images$shape[1] image_size <- images$shape[3:4] - final_results <- list() + final_results <- vector("list", batch_size) for (b in seq_len(batch_size)) { props <- generate_proposals(features, rpn_out, image_size, c(4, 8, 16, 32), @@ -633,7 +635,7 @@ fpn_module_v2 <- torch::nn_module( names(inputs) <- c("c2", "c3", "c4", "c5") last_inner <- self$inner_blocks[[4]](inputs$c5) - results <- list() + results <- vector("list", 4) results[[4]] <- self$layer_blocks[[4]](last_inner) for (i in 3:1) { @@ -729,7 +731,7 @@ fasterrcnn_model_v2 <- torch::nn_module( batch_size <- images$shape[1] image_size <- images$shape[3:4] - final_results <- list() + final_results <- vector("list", batch_size) for (b in seq_len(batch_size)) { props <- generate_proposals(features, rpn_out, image_size, c(4, 8, 16, 32), @@ -780,7 +782,7 @@ fpn_module_2level <- torch::nn_module( }, forward = function(inputs) { last_inner <- self$inner_blocks[[2]](inputs[[2]]) - results <- list() + results <- vector("list", 2) results[[2]] <- self$layer_blocks[[2]](last_inner) lateral <- self$inner_blocks[[1]](inputs[[1]]) @@ -807,7 +809,7 @@ mobilenet_v3_fpn_backbone <- function(pretrained = TRUE) { ) }, forward = function(x) { - all_feats <- list() + all_feats <- vector("list", length(self$body)) for (i in seq_len(length(self$body))) { x <- self$body[[i]](x) @@ -857,7 +859,7 @@ fasterrcnn_mobilenet_model <- torch::nn_module( batch_size <- images$shape[1] image_size <- images$shape[3:4] - final_results <- list() + final_results <- vector("list", batch_size) for (b in seq_len(batch_size)) { props <- generate_proposals(features, rpn_out, image_size, c(8, 16), @@ -910,7 +912,7 @@ mobilenet_v3_320_fpn_backbone <- function(pretrained = TRUE) { ) }, forward = function(x) { - all_feats <- list() + all_feats <- vector("list", length(self$body)) for (i in seq_len(length(self$body))) { x <- self$body[[i]](x) diff --git a/R/models-lw_detr.R b/R/models-lw_detr.R index a19a5b51..e7bf39f8 100644 --- a/R/models-lw_detr.R +++ b/R/models-lw_detr.R @@ -26,7 +26,7 @@ lw_detr_gen_sineembed <- function(pos, dim = 128L) { dim_t <- torch_arange(dim, dtype = torch_float32(), device = pos$device) dim_t <- 10000^(2 * torch_div(dim_t, 2L, rounding_mode = "floor") / dim) - coords <- list() + coords <- vector("list", pos$size(-1)) for (c_idx in seq_len(pos$size(-1))) { v <- pos[,, c_idx] * scale pe <- v$unsqueeze(3) / dim_t @@ -46,7 +46,7 @@ lw_detr_gen_sineembed <- function(pos, dim = 128L) { # `masks` is a list of (B, H_l, W_l) logical tensors (TRUE = valid pixel); the # proposal centres are normalised by the valid extent so padding is ignored. lw_detr_gen_proposals <- function(spatial_shapes, masks, bs, device) { - proposals <- list() + proposals <- vector("list", nrow(spatial_shapes)) for (lvl in seq_len(nrow(spatial_shapes))) { h_l <- as.integer(spatial_shapes[lvl, 1]) w_l <- as.integer(spatial_shapes[lvl, 2]) @@ -376,7 +376,7 @@ detr_ms_deform_attn <- nn_module( offsets / np * ref_wh$unsqueeze(3L)$unsqueeze(5L) * 0.5 } - val_split <- list() + val_split <- vector("list", nl) for (lvl in seq_len(nl)) { h_l <- as.integer(spatial_shapes[lvl, 1]) w_l <- as.integer(spatial_shapes[lvl, 2]) @@ -389,7 +389,7 @@ detr_ms_deform_attn <- nn_module( sampling_grids <- 2 * sampling_locs - 1 - out_list <- list() + out_list <- vector("list", nl) for (lvl in seq_len(nl)) { grid_l <- sampling_grids[,,, lvl, , ] grid_l <- grid_l$permute(c(1L, 3L, 2L, 4L, 5L)) diff --git a/R/models-mask_rcnn.R b/R/models-mask_rcnn.R index 41723592..5c5c8197 100644 --- a/R/models-mask_rcnn.R +++ b/R/models-mask_rcnn.R @@ -287,7 +287,7 @@ maskrcnn_model <- torch::nn_module( batch_size <- images$shape[1] image_size <- images$shape[3:4] - final_results <- list() + final_results <- vector("list", batch_size) for (b in seq_len(batch_size)) { @@ -417,7 +417,7 @@ maskrcnn_model_v2 <- torch::nn_module( batch_size <- images$shape[1] image_size <- images$shape[3:4] - final_results <- list() + final_results <- vector("list", batch_size) for (b in seq_len(batch_size)) { props <- generate_proposals(features, rpn_out, image_size, c(4, 8, 16, 32), diff --git a/R/models-mobilenetv3.R b/R/models-mobilenetv3.R index da8fd433..fe6ce5be 100644 --- a/R/models-mobilenetv3.R +++ b/R/models-mobilenetv3.R @@ -216,40 +216,36 @@ MobileNetV3 <- nn_module( initialize = function(inverted_residual_setting, last_channel, num_classes = 1000, dropout = 0.2, norm_layer = nn_batch_norm2d) { - layers <- list() + n_conf <- length(inverted_residual_setting) + layers <- vector("list", n_conf + 2) firstconv_out <- inverted_residual_setting[[1]]$input_channels - layers <- c(layers, list( - Conv2dNormActivation( - 3, firstconv_out, kernel_size = 3, stride = 2, - norm_layer = norm_layer, activation_layer = nn_hardswish - ) - )) + layers[[1]] <- Conv2dNormActivation( + 3, firstconv_out, kernel_size = 3, stride = 2, + norm_layer = norm_layer, activation_layer = nn_hardswish + ) - for (conf in inverted_residual_setting) { - layers <- c(layers, list( - InvertedResidual( - input_channels = conf$input_channels, - expanded_channels = conf$expanded_channels, - out_channels = conf$out_channels, - kernel = conf$kernel, - stride = conf$stride, - use_se = conf$use_se, - use_hs = conf$use_hs, - dilation = conf$dilation, - norm_layer = norm_layer - ) - )) + for (i in seq_len(n_conf)) { + conf <- inverted_residual_setting[[i]] + layers[[i + 1]] <- InvertedResidual( + input_channels = conf$input_channels, + expanded_channels = conf$expanded_channels, + out_channels = conf$out_channels, + kernel = conf$kernel, + stride = conf$stride, + use_se = conf$use_se, + use_hs = conf$use_hs, + dilation = conf$dilation, + norm_layer = norm_layer + ) } - lastconv_in <- inverted_residual_setting[[length(inverted_residual_setting)]]$out_channels + lastconv_in <- inverted_residual_setting[[n_conf]]$out_channels lastconv_out <- 6 * lastconv_in - layers <- c(layers, list( - Conv2dNormActivation( - lastconv_in, lastconv_out, kernel_size = 1, - norm_layer = norm_layer, activation_layer = nn_hardswish - ) - )) + layers[[n_conf + 2]] <- Conv2dNormActivation( + lastconv_in, lastconv_out, kernel_size = 1, + norm_layer = norm_layer, activation_layer = nn_hardswish + ) self$features <- nn_sequential(!!!layers) self$avgpool <- nn_adaptive_avg_pool2d(1) diff --git a/R/models-mobilenetv3_large.R b/R/models-mobilenetv3_large.R index 908319ff..d9880776 100644 --- a/R/models-mobilenetv3_large.R +++ b/R/models-mobilenetv3_large.R @@ -142,12 +142,6 @@ mobilenet_v3_large_impl <- torch::nn_module( activation <- nn_hardswish - layers <- list() - layers[[length(layers) + 1]] <- conv_norm_act_v3(3, 16, stride = 2, - norm_layer = norm_layer, - activation_layer = activation) - input_channel <- 16 - cfgs <- list( list(3, 16, 16, FALSE, torch::nn_relu, 1), list(3, 64, 24, FALSE, torch::nn_relu, 2), @@ -166,17 +160,24 @@ mobilenet_v3_large_impl <- torch::nn_module( list(5, 960, 160, TRUE, activation, 1) ) - for (cfg in cfgs) { + layers <- vector("list", length(cfgs) + 2) + layers[[1]] <- conv_norm_act_v3(3, 16, stride = 2, + norm_layer = norm_layer, + activation_layer = activation) + input_channel <- 16 + + for (i in seq_along(cfgs)) { + cfg <- cfgs[[i]] k <- cfg[[1]]; exp <- cfg[[2]]; c <- cfg[[3]]; se <- cfg[[4]]; nl <- cfg[[5]]; s <- cfg[[6]] - layers[[length(layers) + 1]] <- inverted_residual_v3( + layers[[i + 1]] <- inverted_residual_v3( input_channel, exp, c, kernel_size = k, stride = s, use_se = se, activation_layer = nl, norm_layer = norm_layer ) input_channel <- c } - layers[[length(layers) + 1]] <- conv_norm_act_v3( + layers[[length(cfgs) + 2]] <- conv_norm_act_v3( input_channel, 960, kernel_size = 1, norm_layer = norm_layer, activation_layer = activation ) diff --git a/R/models-resnet.R b/R/models-resnet.R index d835fc0f..c0b9a12b 100644 --- a/R/models-resnet.R +++ b/R/models-resnet.R @@ -206,7 +206,7 @@ resnet <- torch::nn_module( ) } - layers <- list() + layers <- vector("list", blocks) layers[[1]] <- block(self$inplanes, planes, stride, downsample, self$groups, self$base_width, previous_dilation, norm_layer) self$inplanes <- planes * block$public_fields$expansion diff --git a/R/models-rfdetr_detection.R b/R/models-rfdetr_detection.R index 2792856a..80f73ee3 100644 --- a/R/models-rfdetr_detection.R +++ b/R/models-rfdetr_detection.R @@ -477,10 +477,10 @@ multiscale_projector <- nn_module( initialize = function(in_channels, out_channels, scale_factors, num_blocks = 3, layer_norm = FALSE) { self$scale_factors <- scale_factors - stages_sampling <- list() + stages_sampling <- vector("list", length(scale_factors)) for (i in seq_along(scale_factors)) { scale <- scale_factors[i] - level_modules <- list() + level_modules <- vector("list", length(in_channels)) for (j in seq_along(in_channels)) { in_dim <- in_channels[j] if (scale == 1.0) { @@ -511,18 +511,18 @@ multiscale_projector <- nn_module( } }, forward = function(x) { - results <- list() + results <- vector("list", length(self$stages)) for (i in seq_along(self$stages)) { - feat_fuse <- list() + feat_fuse <- vector("list", length(x)) for (j in seq_along(x)) { - feat_fuse[[length(feat_fuse) + 1]] <- self$stages_sampling[[i]][[j]](x[[j]]) + feat_fuse[[j]] <- self$stages_sampling[[i]][[j]](x[[j]]) } if (length(feat_fuse) > 1) { feat_fuse <- torch_cat(feat_fuse, dim = 2) } else { feat_fuse <- feat_fuse[[1]] } - results[[length(results) + 1]] <- self$stages[[i]](feat_fuse) + results[[i]] <- self$stages[[i]](feat_fuse) } results } @@ -663,10 +663,11 @@ rfdetr_backbone <- nn_module( feats <- self$encoder(x) feats <- self$projector(feats) if (!is.null(mask)) { - out <- list() - for (feat in feats) { + out <- vector("list", length(feats)) + for (i in seq_along(feats)) { + feat <- feats[[i]] m <- nnf_interpolate(mask$unsqueeze(1)$float(), size = feat$shape[3:4])$to(dtype = torch_bool())[1, , ] - out[[length(out) + 1]] <- list(tensors = feat, mask = m) + out[[i]] <- list(tensors = feat, mask = m) } out } else { @@ -688,15 +689,15 @@ rfdetr_joiner <- nn_module( } feats <- self[["0"]](x, mask) if (length(feats) > 0 && is.list(feats[[1]]) && !is.null(feats[[1]]$tensors)) { - pos <- list() + pos <- vector("list", length(feats)) for (i in seq_along(feats)) { pos[[i]] <- self[["1"]](feats[[i]]$tensors, align_dim_orders = FALSE) } list(feats, pos) } else { - pos <- list() - for (feat in feats) { - pos[[length(pos) + 1]] <- self[["1"]](feat, align_dim_orders = FALSE) + pos <- vector("list", length(feats)) + for (i in seq_along(feats)) { + pos[[i]] <- self[["1"]](feats[[i]], align_dim_orders = FALSE) } list(feats, pos) } @@ -729,7 +730,7 @@ gen_sineembed_for_position <- function(pos_tensor, dim = 128) { } gen_encoder_output_proposals <- function(memory, memory_padding_mask, spatial_shapes, unsigmoid = TRUE) { - proposals <- list() + proposals <- vector("list", nrow(spatial_shapes)) cur <- 1 for (lvl in seq_len(nrow(spatial_shapes))) { h <- as.integer(spatial_shapes[lvl, 1]) @@ -864,7 +865,7 @@ rfdetr_decoder <- nn_module( refpoints_unsigmoid = NULL, level_start_index = NULL, spatial_shapes = NULL, valid_ratios = NULL) { output <- tgt - intermediate <- list() + intermediate <- vector("list", self$num_layers) hs_refpoints <- list(refpoints_unsigmoid) d_model_half <- as.integer(memory$size(3) / 2) if (self$lite_refpoint_refine) { @@ -955,10 +956,10 @@ rfdetr_transformer <- nn_module( torch_stack(list(valid_ratio_w, valid_ratio_h), dim = -1) }, forward = function(srcs, masks, pos_embeds, refpoint_embed, query_feat) { - src_flatten <- list() - mask_flatten <- list() - lvl_pos_embed_flatten <- list() - spatial_shapes <- list() + src_flatten <- vector("list", length(srcs)) + mask_flatten <- vector("list", length(srcs)) + lvl_pos_embed_flatten <- vector("list", length(srcs)) + spatial_shapes <- vector("list", length(srcs)) for (lvl in seq_along(srcs)) { src <- srcs[[lvl]] c <- src$size(2) @@ -1005,10 +1006,10 @@ rfdetr_transformer <- nn_module( ) output_memory <- proposals[[1]] output_proposals <- proposals[[2]] - refpoint_embed_ts <- list() - memory_ts <- list() - boxes_ts <- list() gd <- if (self$training) self$group_detr else 1 + refpoint_embed_ts <- vector("list", gd) + memory_ts <- vector("list", gd) + boxes_ts <- vector("list", gd) for (g_idx in seq_len(gd)) { om <- self$enc_output_norm[[g_idx]](self$enc_output[[g_idx]](output_memory)) cls_enc_g <- self$enc_out_class_embed[[g_idx]](om) @@ -1125,13 +1126,14 @@ rfdetr_model <- nn_module( backbone_out <- self$backbone(x, mask) features <- backbone_out[[1]] poss <- backbone_out[[2]] - srcs <- list() - masks <- list() - for (feat in features) { - srcs[[length(srcs) + 1]] <- feat + srcs <- vector("list", length(features)) + masks <- if (is.null(mask)) list() else vector("list", length(features)) + for (i in seq_along(features)) { + feat <- features[[i]] + srcs[[i]] <- feat if (!is.null(mask)) { m <- nnf_interpolate(mask$unsqueeze(1)$float(), size = feat$shape[3:4])$squeeze(1)$to(dtype = torch_bool()) - masks[[length(masks) + 1]] <- m + masks[[i]] <- m } } refpoint_embed_weight <- self$refpoint_embed$weight @@ -1162,7 +1164,7 @@ rfdetr_model <- nn_module( out$pred_logits <- outputs_class[hs$size(1), , , ] out$pred_boxes <- outputs_coord[hs$size(1), , , ] if (self$aux_loss) { - aux <- list() + aux <- vector("list", hs$size(1) - 1) for (i in seq_len(hs$size(1) - 1)) { aux[[i]] <- list( pred_logits = outputs_class[i, , , ], @@ -1175,7 +1177,7 @@ rfdetr_model <- nn_module( if (self$two_stage) { gd <- if (self$training) self$group_detr else 1 hs_enc_list <- hs_enc$split(hs_enc$size(2) %/% gd, dim = 2) - cls_enc_list <- list() + cls_enc_list <- vector("list", gd) for (g_idx in seq_len(gd)) { cls_enc_list[[g_idx]] <- self$transformer$enc_out_class_embed[[g_idx]](hs_enc_list[[g_idx]]) } @@ -1222,7 +1224,7 @@ rfdetr_model <- nn_module( x2 <- torch_maximum(boxes_xyxy[, , 3], x1 + 2) y2 <- torch_maximum(boxes_xyxy[, , 4], y1 + 2) boxes_xyxy <- torch_stack(list(x1, y1, x2, y2), dim = -1)$clamp(max = clamp_max) - detections <- list() + detections <- vector("list", boxes_xyxy$size(1)) for (i in seq_len(boxes_xyxy$size(1))) { detections[[i]] <- list( scores = scores[i, ], @@ -1269,7 +1271,7 @@ rfdetr_postprocess <- nn_module( x2 <- torch_maximum(boxes_xyxy[, , 3], x1 + 2) y2 <- torch_maximum(boxes_xyxy[, , 4], y1 + 2) boxes_xyxy <- torch_stack(list(x1, y1, x2, y2), dim = -1)$clamp(min = 0) - results <- list() + results <- vector("list", boxes_xyxy$size(1)) for (i in seq_len(boxes_xyxy$size(1))) { results[[i]] <- list( scores = scores[i, ], diff --git a/R/models-vgg.R b/R/models-vgg.R index b68e9380..31f0bde7 100644 --- a/R/models-vgg.R +++ b/R/models-vgg.R @@ -46,13 +46,20 @@ VGG <- torch::nn_module( ) vgg_make_layers <- function(cfg, batch_norm) { - layers <- list() + n_layers <- sum(vapply( + cfg, + function(v) if (v == "M") 1L else if (batch_norm) 3L else 2L, + integer(1) + )) + layers <- vector("list", n_layers) + k <- 0L in_channels <- 3 for (v in cfg) { if (v == "M") { - layers[[length(layers) + 1]] <- torch::nn_max_pool2d( + k <- k + 1L + layers[[k]] <- torch::nn_max_pool2d( kernel_size = 2, stride = 2 ) @@ -60,15 +67,19 @@ vgg_make_layers <- function(cfg, batch_norm) { } else { v <- as.integer(v) - layers[[length(layers) + 1]] <- torch::nn_conv2d( + k <- k + 1L + layers[[k]] <- torch::nn_conv2d( in_channels = in_channels, out_channels = v, kernel_size = 3, padding = 1 ) - if (batch_norm) - layers[[length(layers) + 1]] <- torch::nn_batch_norm2d(num_features = v) + if (batch_norm) { + k <- k + 1L + layers[[k]] <- torch::nn_batch_norm2d(num_features = v) + } - layers[[length(layers) + 1]] <- torch::nn_relu(inplace = TRUE) + k <- k + 1L + layers[[k]] <- torch::nn_relu(inplace = TRUE) in_channels <- v } From 2e330cd6ad023c950576493d6bf9233f329c7a97 Mon Sep 17 00:00:00 2001 From: "srishti.dutta1111" Date: Sun, 12 Jul 2026 23:09:48 +0530 Subject: [PATCH 2/3] Use lapply/Map and a single dir_ls --- R/folder-dataset.R | 29 +++++++++++++---------------- R/models-rfdetr_detection.R | 24 ++++++------------------ 2 files changed, 19 insertions(+), 34 deletions(-) diff --git a/R/folder-dataset.R b/R/folder-dataset.R index d214047e..a7a47606 100644 --- a/R/folder-dataset.R +++ b/R/folder-dataset.R @@ -29,28 +29,25 @@ folder_make_dataset <- function(directory, class_to_idx, extensions = NULL, is_v } target_classes <- sort(names(class_to_idx)) - paths <- vector("list", length(target_classes)) - indexes <- vector("list", length(target_classes)) - for (i in seq_along(target_classes)) { + # List the whole tree once rather than calling fs::dir_ls() per class, then + # assign each entry to the top-level class directory it lives under. + entries <- fs::dir_ls(directory, recurse = TRUE) + entries <- entries[is_valid_file(entries)] - target_class <- target_classes[i] - class_index <- class_to_idx[target_class] - target_dir <- fs::path_join(c(directory, target_class)) + parts <- fs::path_split(fs::path_rel(entries, directory)) + first <- vapply(parts, `[[`, character(1), 1L) + keep <- lengths(parts) >= 2L & first %in% target_classes - if (!fs::is_dir(target_dir)) - next + entries <- entries[keep] + first <- first[keep] - fnames <- fs::dir_ls(target_dir, recurse = TRUE) - fnames <- fnames[is_valid_file(fnames)] - - paths[[i]] <- fnames - indexes[[i]] <- rep(class_index, length(fnames)) - } + # group by class in sorted-class order (stable within a class) + ord <- order(match(first, target_classes), method = "radix") list( - unlist(paths), - unlist(indexes) + as.character(entries[ord]), + unname(class_to_idx[first[ord]]) ) } diff --git a/R/models-rfdetr_detection.R b/R/models-rfdetr_detection.R index 80f73ee3..5608b204 100644 --- a/R/models-rfdetr_detection.R +++ b/R/models-rfdetr_detection.R @@ -513,10 +513,7 @@ multiscale_projector <- nn_module( forward = function(x) { results <- vector("list", length(self$stages)) for (i in seq_along(self$stages)) { - feat_fuse <- vector("list", length(x)) - for (j in seq_along(x)) { - feat_fuse[[j]] <- self$stages_sampling[[i]][[j]](x[[j]]) - } + feat_fuse <- Map(function(f, y) f(y), as.list(self$stages_sampling[[i]]), x) if (length(feat_fuse) > 1) { feat_fuse <- torch_cat(feat_fuse, dim = 2) } else { @@ -663,13 +660,10 @@ rfdetr_backbone <- nn_module( feats <- self$encoder(x) feats <- self$projector(feats) if (!is.null(mask)) { - out <- vector("list", length(feats)) - for (i in seq_along(feats)) { - feat <- feats[[i]] + lapply(feats, function(feat) { m <- nnf_interpolate(mask$unsqueeze(1)$float(), size = feat$shape[3:4])$to(dtype = torch_bool())[1, , ] - out[[i]] <- list(tensors = feat, mask = m) - } - out + list(tensors = feat, mask = m) + }) } else { feats } @@ -689,16 +683,10 @@ rfdetr_joiner <- nn_module( } feats <- self[["0"]](x, mask) if (length(feats) > 0 && is.list(feats[[1]]) && !is.null(feats[[1]]$tensors)) { - pos <- vector("list", length(feats)) - for (i in seq_along(feats)) { - pos[[i]] <- self[["1"]](feats[[i]]$tensors, align_dim_orders = FALSE) - } + pos <- lapply(feats, function(f) self[["1"]](f$tensors, align_dim_orders = FALSE)) list(feats, pos) } else { - pos <- vector("list", length(feats)) - for (i in seq_along(feats)) { - pos[[i]] <- self[["1"]](feats[[i]], align_dim_orders = FALSE) - } + pos <- lapply(feats, function(f) self[["1"]](f, align_dim_orders = FALSE)) list(feats, pos) } } From 6b18ebe4b74f316f6f21ce3bfe2b1d7b421f55c1 Mon Sep 17 00:00:00 2001 From: "srishti.dutta1111" Date: Sun, 12 Jul 2026 23:22:40 +0530 Subject: [PATCH 3/3] Convert remaining preallocated loops to lapply --- R/models-convnext_segmentation.R | 14 ++++---------- R/models-rfdetr_detection.R | 23 ++++++----------------- 2 files changed, 10 insertions(+), 27 deletions(-) diff --git a/R/models-convnext_segmentation.R b/R/models-convnext_segmentation.R index c2008575..84f27277 100644 --- a/R/models-convnext_segmentation.R +++ b/R/models-convnext_segmentation.R @@ -161,20 +161,14 @@ ppm_module <- torch::nn_module( }, forward = function(x) { target_size <- x$shape[3:4] - ppm_outs <- vector("list", length(self$stages)) - - for (i in seq_along(self$stages)) { - ppm_out <- self$stages[[i]](x) - ppm_out <- torch::nnf_interpolate( - ppm_out, + lapply(as.list(self$stages), function(stage) { + torch::nnf_interpolate( + stage(x), size = as.integer(target_size), mode = "bilinear", align_corners = FALSE ) - ppm_outs[[i]] <- ppm_out - } - - ppm_outs + }) } ) diff --git a/R/models-rfdetr_detection.R b/R/models-rfdetr_detection.R index 5608b204..56725bc4 100644 --- a/R/models-rfdetr_detection.R +++ b/R/models-rfdetr_detection.R @@ -1212,14 +1212,9 @@ rfdetr_model <- nn_module( x2 <- torch_maximum(boxes_xyxy[, , 3], x1 + 2) y2 <- torch_maximum(boxes_xyxy[, , 4], y1 + 2) boxes_xyxy <- torch_stack(list(x1, y1, x2, y2), dim = -1)$clamp(max = clamp_max) - detections <- vector("list", boxes_xyxy$size(1)) - for (i in seq_len(boxes_xyxy$size(1))) { - detections[[i]] <- list( - scores = scores[i, ], - labels = labels[i, ], - boxes = boxes_xyxy[i, , ] - ) - } + detections <- lapply(seq_len(boxes_xyxy$size(1)), function(i) { + list(scores = scores[i, ], labels = labels[i, ], boxes = boxes_xyxy[i, , ]) + }) return(list(detections = detections)) } out @@ -1259,15 +1254,9 @@ rfdetr_postprocess <- nn_module( x2 <- torch_maximum(boxes_xyxy[, , 3], x1 + 2) y2 <- torch_maximum(boxes_xyxy[, , 4], y1 + 2) boxes_xyxy <- torch_stack(list(x1, y1, x2, y2), dim = -1)$clamp(min = 0) - results <- vector("list", boxes_xyxy$size(1)) - for (i in seq_len(boxes_xyxy$size(1))) { - results[[i]] <- list( - scores = scores[i, ], - labels = labels[i, ], - boxes = boxes_xyxy[i, , ] - ) - } - results + lapply(seq_len(boxes_xyxy$size(1)), function(i) { + list(scores = scores[i, ], labels = labels[i, ], boxes = boxes_xyxy[i, , ]) + }) } )