Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
11 changes: 5 additions & 6 deletions R/dataset-cityscapes.R
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
16 changes: 9 additions & 7 deletions R/folder-dataset.R

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion readability instead of first allocation then iteration, it seems this use case could make use of the functionnal lapply() that do both at the same time

# Remplacement de la boucle for par lapply
res <- lapply(sort(names(class_to_idx)), function(target_class) {
  class_index <- class_to_idx[[target_class]] 
  target_dir <- fs::path_join(c(directory, target_class))
  
  # we may gather empty vectors that will be removed by unlist at the end
  if (!fs::is_dir(target_dir)) {
    return(list(paths = character(0), indexes = integer(0)))
  }
  
  fnames <- fs::dir_ls(target_dir, recurse = TRUE)
  fnames <- fnames[is_valid_file(fnames)]
  
  list(paths = fnames, indexes = rep(class_index, length(fnames)))
})

list(
  unlist(lapply(res, `[[`, "paths"), use.names = FALSE),
  unlist(lapply(res, `[[`, "indexes"), use.names = FALSE)
)

todo perfromance from that point, it becomes transparent that the code is running n_classes times the fs::dir_ls() what can be is extremely time consuming. I would recommand to make that ls_dir() once and then filter out invalid files, non-classes related files, and so on.

Original file line number Diff line number Diff line change
Expand Up @@ -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))

Expand All @@ -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)
)
}

Expand Down
6 changes: 3 additions & 3 deletions R/models-convnext_segmentation.R
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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]])
}
Expand All @@ -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]])
}
Expand Down
4 changes: 2 additions & 2 deletions R/models-deeplabv3.R
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
10 changes: 6 additions & 4 deletions R/models-efficientnet.R
Original file line number Diff line number Diff line change
Expand Up @@ -177,21 +177,23 @@ 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,
kernel_size = cfg$kernel, stride = s, expand_ratio = cfg$expand,
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)
Expand Down
14 changes: 7 additions & 7 deletions R/models-efficientnetv2.R
Original file line number Diff line number Diff line change
Expand Up @@ -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")) {
Expand All @@ -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
Expand Down
42 changes: 22 additions & 20 deletions R/models-faster_rcnn.R
Original file line number Diff line number Diff line change
Expand Up @@ -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]]
Expand Down Expand Up @@ -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]]
Expand All @@ -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)
Expand All @@ -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)
}
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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]])
Expand All @@ -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)
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 4 additions & 4 deletions R/models-lw_detr.R
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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])
Expand Down Expand Up @@ -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])
Expand All @@ -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))
Expand Down
4 changes: 2 additions & 2 deletions R/models-mask_rcnn.R
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {

Expand Down Expand Up @@ -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),
Expand Down
Loading
Loading