Skip to content

Commit

Permalink
Merge branch 'main' into feat/tflog-callback
Browse files Browse the repository at this point in the history
  • Loading branch information
sebffischer authored Oct 18, 2024
2 parents 3957614 + 6e2a68e commit c95d241
Show file tree
Hide file tree
Showing 73 changed files with 999 additions and 21 deletions.
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: mlr3torch
Title: Deep Learning with 'mlr3'
Version: 0.1.1-9000
Version: 0.1.2
Authors@R:
c(person(given = "Sebastian",
family = "Fischer",
Expand Down Expand Up @@ -106,6 +106,7 @@ Collate:
'PipeOpTorch.R'
'PipeOpTaskPreprocTorch.R'
'PipeOpTorchActivation.R'
'PipeOpTorchAdaptiveAvgPool.R'
'PipeOpTorchAvgPool.R'
'PipeOpTorchBatchNorm.R'
'PipeOpTorchBlock.R'
Expand Down
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ export(ModelDescriptor)
export(PipeOpModule)
export(PipeOpTaskPreprocTorch)
export(PipeOpTorch)
export(PipeOpTorchAdaptiveAvgPool1D)
export(PipeOpTorchAdaptiveAvgPool2D)
export(PipeOpTorchAdaptiveAvgPool3D)
export(PipeOpTorchAvgPool1D)
export(PipeOpTorchAvgPool2D)
export(PipeOpTorchAvgPool3D)
Expand Down
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# mlr3torch dev

* feat: Add parameter `num_interop_threads` to `LearnerTorch`
* feat: Add adaptive average pooling

# mlr3torch 0.1.2

* Don't use deprecated `data_formats` anymore
* Added `CallbackSetTB`, which allows logging that can be viewed by TensorBoard.

Expand Down
6 changes: 4 additions & 2 deletions R/LearnerTorch.R
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,8 @@ LearnerTorch = R6Class("LearnerTorch",
param_vals$device = auto_device(param_vals$device)
if (identical(param_vals$seed, "random")) param_vals$seed = sample.int(.Machine$integer.max, 1)

model = with_torch_settings(seed = param_vals$seed, num_threads = param_vals$num_threads, {
model = with_torch_settings(seed = param_vals$seed, num_threads = param_vals$num_threads,
num_interop_threads = param_vals$num_interop_threads, expr = {
learner_torch_train(self, private, super, task, param_vals)
})
model$task_col_info = copy(task$col_info[c(task$feature_names, task$target_names), c("id", "type", "levels")])
Expand All @@ -453,7 +454,8 @@ LearnerTorch = R6Class("LearnerTorch",
param_vals$device = auto_device(param_vals$device)
private$.verify_predict_task(task, param_vals)

with_torch_settings(seed = self$model$seed, num_threads = param_vals$num_threads, {
with_torch_settings(seed = self$model$seed, num_threads = param_vals$num_threads,
num_interop_threads = param_vals$num_interop_threads, expr = {
learner_torch_predict(self, private, super, task, param_vals)
})
},
Expand Down
126 changes: 126 additions & 0 deletions R/PipeOpTorchAdaptiveAvgPool.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
PipeOpTorchAdaptiveAvgPool = R6Class("PipeOpTorchAdaptiveAvgPool",
inherit = PipeOpTorch,
public = list(
initialize = function(id, d, param_vals = list()) {
private$.d = assert_int(d, lower = 1, upper = 3)
module_generator = switch(d, nn_adaptive_avg_pool1d, nn_adaptive_avg_pool2d, nn_adaptive_avg_pool3d)
check_vector = make_check_vector(private$.d)
param_set = ps(
output_size = p_uty(custom_check = check_vector, tags = c("required", "train"))
)

super$initialize(
id = id,
param_set = param_set,
param_vals = param_vals,
module_generator = module_generator
)
}
),
private = list(
.shapes_out = function(shapes_in, param_vals, task) {
list(adaptive_avg_output_shape(
shape_in = shapes_in[[1]],
conv_dim = private$.d,
output_size = param_vals$output_size
))
},
.d = NULL
)
)

adaptive_avg_output_shape = function(shape_in, conv_dim, output_size) {
shape_in = assert_integerish(shape_in, min.len = conv_dim, coerce = TRUE)

if (length(output_size) == 1) output_size = rep(output_size, conv_dim)

shape_head = utils::head(shape_in, -conv_dim)
if (length(shape_head) <= 1) warningf("Input tensor does not have batch dimension.")

shape_tail = output_size

c(shape_head, shape_tail)
}

#' @title 1D Adaptive Average Pooling
#'
#' @templateVar id nn_adaptive_avg_pool1d
#' @template pipeop_torch_channels_default
#' @template pipeop_torch
#' @template pipeop_torch_example
#'
#' @inherit torch::nnf_adaptive_avg_pool1d description
#'
#' @section Parameters:
#' * `output_size` :: `integer(1)`\cr
#' The target output size. A single number.
#'
#' @section Internals:
#' Calls [`nn_adaptive_avg_pool1d()`][torch::nn_adaptive_avg_pool1d] during training.
#' @export
PipeOpTorchAdaptiveAvgPool1D = R6Class("PipeOpTorchAdaptiveAvgPool1D", inherit = PipeOpTorchAdaptiveAvgPool,
public = list(
#' @description Creates a new instance of this [R6][R6::R6Class] class.
#' @template params_pipelines
initialize = function(id = "nn_adaptive_avg_pool1d", param_vals = list()) {
super$initialize(id = id, d = 1, param_vals = param_vals)
}
)
)

#' @title 2D Adaptive Average Pooling
#'
#' @templateVar id nn_adaptive_avg_pool2d
#' @template pipeop_torch_channels_default
#' @template pipeop_torch
#' @template pipeop_torch_example
#'
#' @inherit torch::nnf_adaptive_avg_pool2d description
#'
#' @section Parameters:
#' * `output_size` :: `integer()`\cr
#' The target output size. Can be a single number or a vector.
#'
#' @section Internals:
#' Calls [`nn_adaptive_avg_pool2d()`][torch::nn_adaptive_avg_pool2d] during training.
#' @export
PipeOpTorchAdaptiveAvgPool2D = R6Class("PipeOpTorchAdaptiveAvgPool2D", inherit = PipeOpTorchAdaptiveAvgPool,
public = list(
#' @description Creates a new instance of this [R6][R6::R6Class] class.
#' @template params_pipelines
initialize = function(id = "nn_adaptive_avg_pool2d", param_vals = list()) {
super$initialize(id = id, d = 2, param_vals = param_vals)
}
)
)

#' @title 3D Adaptive Average Pooling
#'
#' @templateVar id nn_adaptive_avg_pool3d
#' @template pipeop_torch_channels_default
#' @template pipeop_torch
#' @template pipeop_torch_example
#'
#' @inherit torch::nnf_adaptive_avg_pool3d description
#'
#' @section Parameters:
#' * `output_size` :: `integer()`\cr
#' The target output size. Can be a single number or a vector.
#'
#' @section Internals:
#' Calls [`nn_adaptive_avg_pool3d()`][torch::nn_adaptive_avg_pool3d] during training.
#' @export
PipeOpTorchAdaptiveAvgPool3D = R6Class("PipeOpTorchAdaptiveAvgPool3D", inherit = PipeOpTorchAdaptiveAvgPool,
public = list(
#' @description Creates a new instance of this [R6][R6::R6Class] class.
#' @template params_pipelines
initialize = function(id = "nn_adaptive_avg_pool3d", param_vals = list()) {
super$initialize(id = id, d = 3, param_vals = param_vals)
}
)
)

#' @include zzz.R
register_po("nn_adaptive_avg_pool1d", PipeOpTorchAdaptiveAvgPool1D)
register_po("nn_adaptive_avg_pool2d", PipeOpTorchAdaptiveAvgPool2D)
register_po("nn_adaptive_avg_pool3d", PipeOpTorchAdaptiveAvgPool3D)
6 changes: 3 additions & 3 deletions R/PipeOpTorchAvgPool.R
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ avg_output_shape = function(shape_in, conv_dim, padding, stride, kernel_size, ce
#' @template pipeop_torch
#' @template pipeop_torch_example
#'
#' @inherit torch::nnf_adaptive_avg_pool1d description
#' @inherit torch::nnf_avg_pool1d description
#'
#' @section Parameters:
#' * `kernel_size` :: (`integer()`)\cr
Expand Down Expand Up @@ -104,7 +104,7 @@ PipeOpTorchAvgPool1D = R6Class("PipeOpTorchAvgPool1D", inherit = PipeOpTorchAvgP
#' @template pipeop_torch
#' @template pipeop_torch_example
#'
#' @inherit torch::nnf_adaptive_avg_pool2d description
#' @inherit torch::nnf_avg_pool2d description
#'
#' @inheritSection mlr_pipeops_nn_avg_pool1d Parameters
#'
Expand All @@ -128,7 +128,7 @@ PipeOpTorchAvgPool2D = R6Class("PipeOpTorchAvgPool2D", inherit = PipeOpTorchAvgP
#' @template pipeop_torch
#' @template pipeop_torch_example
#'
#' @inherit torch::nnf_adaptive_avg_pool3d description
#' @inherit torch::nnf_avg_pool3d description
#'
#' @inheritSection mlr_pipeops_nn_avg_pool1d Parameters
#'
Expand Down
1 change: 1 addition & 0 deletions R/paramset_torchlearner.R
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ paramset_torchlearner = function(task_type) {
aggr = epochs_aggr, in_tune_fn = epochs_tune_fn, disable_in_tune = list(patience = 0)),
device = p_fct(tags = c("train", "predict", "required"), levels = mlr_reflections$torch$devices, init = "auto"),
num_threads = p_int(lower = 1L, tags = c("train", "predict", "required", "threads"), init = 1L),
num_interop_threads = p_int(lower = 1L, tags = c("train", "predict", "required"), init = 1L),
seed = p_int(tags = c("train", "predict", "required"), special_vals = list("random", NULL), init = "random"),
# evaluation
eval_freq = p_int(lower = 1L, tags = c("train", "required"), init = 1L),
Expand Down
17 changes: 12 additions & 5 deletions R/with_torch_settings.R
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
with_torch_settings = function(seed, num_threads = 1, expr) {
with_torch_settings = function(seed, num_threads = 1, num_interop_threads = 1, expr) {
old_num_threads = torch_get_num_threads()
if (!running_on_mac()) {
if (running_on_mac()) {
if (!isTRUE(all.equal(num_threads, 1L))) {
lg$warn("Cannot set number of threads on macOS.")
}
} else {
on.exit({torch_set_num_threads(old_num_threads)},
add = TRUE
)
torch_set_num_threads(num_threads)
} else {
if (!isTRUE(all.equal(num_threads, 1L))) {
lg$warn("Cannot set number of threads on macOS.")
}

if (num_interop_threads != torch_get_num_interop_threads()) {
result = try(torch::torch_set_num_interop_threads(num_interop_threads), silent = TRUE)
if (inherits(result, "try-error")) {
lg$warn(sprintf("Can only set the interop threads once, keeping the previous value %s", torch_get_num_interop_threads()))
}
}
# sets the seed back when exiting the function
Expand Down
4 changes: 4 additions & 0 deletions man-roxygen/paramset_torchlearner.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
#' * `num_threads` :: `integer(1)`\cr
#' The number of threads for intraop pararallelization (if `device` is `"cpu"`).
#' This value is initialized to 1.
#' * `num_interop_threads` :: `integer(1)`\cr
#' The number of threads for intraop and interop pararallelization (if `device` is `"cpu"`).
#' This value is initialized to 1.
#' Note that this can only be set once during a session and changing the value within an R session will raise a warning.
#' * `seed` :: `integer(1)` or `"random"` or `NULL`\cr
#' The torch seed that is used during training and prediction.
#' This value is initialized to `"random"`, which means that a random seed will be sampled at the beginning of the
Expand Down
4 changes: 4 additions & 0 deletions man/mlr_learners_torch.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit c95d241

Please sign in to comment.