From 87c2b8828f8c68a6e3b385b53a7f2448feba0781 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 11 Oct 2023 17:58:33 +0200 Subject: [PATCH 01/90] WIP: lazy tensor --- DESCRIPTION | 8 +- NAMESPACE | 15 ++ R/DataDescriptor.R | 131 +++++++++++++++++ R/PipeOpTorchConv.R | 2 +- R/PipeOpTorchIngress.R | 49 +++++++ R/TaskClassif_mnist.R | 98 +++++++++++++ R/bibentries.R | 10 ++ R/lazy_tensor.R | 86 +++++++++++ R/materialize.R | 167 +++++++++++++++++++++ R/paramset_torchlearner.R | 2 +- R/task_dataset.R | 2 + R/utils.R | 57 ++++++-- R/zzz.R | 7 +- data-raw/mnist.R | 0 inst/col_info/mnist.rds | Bin 0 -> 274 bytes lazy_tensor_old.R | 14 ++ man/DataDescriptor.Rd | 83 +++++++++++ man/ModelDescriptor.Rd | 1 + man/TorchIngressToken.Rd | 1 + man/as_lazy_tensor.Rd | 18 +++ man/is_lazy_tensor.Rd | 15 ++ man/lazy_tensor.Rd | 18 +++ man/materialize.Rd | 16 ++ man/mlr_learners.torch_featureless.Rd | 2 +- man/mlr_learners_torch_model.Rd | 1 + man/mlr_pipeops_module.Rd | 1 + man/mlr_pipeops_nn_avg_pool1d.Rd | 1 + man/mlr_pipeops_nn_avg_pool2d.Rd | 1 + man/mlr_pipeops_nn_avg_pool3d.Rd | 1 + man/mlr_pipeops_nn_batch_norm1d.Rd | 1 + man/mlr_pipeops_nn_batch_norm2d.Rd | 1 + man/mlr_pipeops_nn_batch_norm3d.Rd | 1 + man/mlr_pipeops_nn_celu.Rd | 1 + man/mlr_pipeops_nn_conv1d.Rd | 1 + man/mlr_pipeops_nn_conv2d.Rd | 1 + man/mlr_pipeops_nn_conv3d.Rd | 1 + man/mlr_pipeops_nn_conv_transpose1d.Rd | 1 + man/mlr_pipeops_nn_conv_transpose2d.Rd | 1 + man/mlr_pipeops_nn_conv_transpose3d.Rd | 1 + man/mlr_pipeops_nn_dropout.Rd | 1 + man/mlr_pipeops_nn_elu.Rd | 1 + man/mlr_pipeops_nn_flatten.Rd | 1 + man/mlr_pipeops_nn_gelu.Rd | 1 + man/mlr_pipeops_nn_glu.Rd | 1 + man/mlr_pipeops_nn_hardshrink.Rd | 1 + man/mlr_pipeops_nn_hardsigmoid.Rd | 1 + man/mlr_pipeops_nn_hardtanh.Rd | 1 + man/mlr_pipeops_nn_head.Rd | 1 + man/mlr_pipeops_nn_layer_norm.Rd | 1 + man/mlr_pipeops_nn_leaky_relu.Rd | 1 + man/mlr_pipeops_nn_linear.Rd | 1 + man/mlr_pipeops_nn_log_sigmoid.Rd | 1 + man/mlr_pipeops_nn_max_pool1d.Rd | 1 + man/mlr_pipeops_nn_max_pool2d.Rd | 1 + man/mlr_pipeops_nn_max_pool3d.Rd | 1 + man/mlr_pipeops_nn_merge.Rd | 1 + man/mlr_pipeops_nn_merge_cat.Rd | 1 + man/mlr_pipeops_nn_merge_prod.Rd | 1 + man/mlr_pipeops_nn_merge_sum.Rd | 2 + man/mlr_pipeops_nn_prelu.Rd | 1 + man/mlr_pipeops_nn_relu.Rd | 1 + man/mlr_pipeops_nn_relu6.Rd | 1 + man/mlr_pipeops_nn_reshape.Rd | 1 + man/mlr_pipeops_nn_rrelu.Rd | 1 + man/mlr_pipeops_nn_selu.Rd | 1 + man/mlr_pipeops_nn_sigmoid.Rd | 1 + man/mlr_pipeops_nn_softmax.Rd | 1 + man/mlr_pipeops_nn_softplus.Rd | 1 + man/mlr_pipeops_nn_softshrink.Rd | 1 + man/mlr_pipeops_nn_softsign.Rd | 1 + man/mlr_pipeops_nn_squeeze.Rd | 2 + man/mlr_pipeops_nn_tanh.Rd | 1 + man/mlr_pipeops_nn_tanhshrink.Rd | 1 + man/mlr_pipeops_nn_threshold.Rd | 1 + man/mlr_pipeops_torch.Rd | 1 + man/mlr_pipeops_torch_ingress.Rd | 2 + man/mlr_pipeops_torch_ingress_categ.Rd | 2 + man/mlr_pipeops_torch_ingress_img.Rd | 1 + man/mlr_pipeops_torch_ingress_ltnsr.Rd | 169 ++++++++++++++++++++++ man/mlr_pipeops_torch_ingress_num.Rd | 2 + man/mlr_pipeops_torch_loss.Rd | 1 + man/mlr_pipeops_torch_model.Rd | 1 + man/mlr_pipeops_torch_model_classif.Rd | 1 + man/mlr_pipeops_torch_model_regr.Rd | 1 + man/mlr_tasks_mnist.Rd | 39 +++++ man/model_descriptor_to_learner.Rd | 1 + man/model_descriptor_to_module.Rd | 1 + man/model_descriptor_union.Rd | 1 + man/nn_graph.Rd | 1 + tests/testthat/assets/nano_mnist/data.rds | Bin 0 -> 3021 bytes tests/testthat/helper_functions.R | 12 ++ tests/testthat/helper_tasks.R | 33 ++++- tests/testthat/test_DataDescriptor.R | 32 ++++ tests/testthat/test_ModelDescriptor.R | 2 +- tests/testthat/test_PipeOpTorchIngress.R | 23 +++ tests/testthat/test_lazy_tensor.R | 20 +++ tests/testthat/test_materialize.R | 25 ++++ 97 files changed, 1199 insertions(+), 26 deletions(-) create mode 100644 R/DataDescriptor.R create mode 100644 R/TaskClassif_mnist.R create mode 100644 R/lazy_tensor.R create mode 100644 R/materialize.R create mode 100644 data-raw/mnist.R create mode 100644 inst/col_info/mnist.rds create mode 100644 lazy_tensor_old.R create mode 100644 man/DataDescriptor.Rd create mode 100644 man/as_lazy_tensor.Rd create mode 100644 man/is_lazy_tensor.Rd create mode 100644 man/lazy_tensor.Rd create mode 100644 man/materialize.Rd create mode 100644 man/mlr_pipeops_torch_ingress_ltnsr.Rd create mode 100644 man/mlr_tasks_mnist.Rd create mode 100644 tests/testthat/assets/nano_mnist/data.rds create mode 100644 tests/testthat/test_DataDescriptor.R create mode 100644 tests/testthat/test_lazy_tensor.R create mode 100644 tests/testthat/test_materialize.R diff --git a/DESCRIPTION b/DESCRIPTION index b0017f9a..b2d23e66 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -58,13 +58,15 @@ Suggests: magick, progress, rmarkdown, + vctrs, viridis, torchvision, testthat (>= 3.0.0), zip Remotes: r-lib/zip, - mlr-org/mlr3@col_info + mlr-org/mlr3, + mlr-org/mlr3pipelines@feat/keep_results Config/testthat/edition: 3 NeedsCompilation: no ByteCompile: no @@ -81,6 +83,7 @@ Collate: 'CallbackSetProgress.R' 'ContextTorch.R' 'DataBackendLazy.R' + 'DataDescriptor.R' 'LearnerTorch.R' 'LearnerTorchImage.R' 'LearnerTorchAlexNet.R' @@ -110,13 +113,16 @@ Collate: 'PipeOpTorchReshape.R' 'PipeOpTorchSoftmax.R' 'ResamplingRowRoles.R' + 'TaskClassif_mnist.R' 'TaskClassif_tiny_imagenet.R' 'TorchDescriptor.R' 'TorchOptimizer.R' 'bibentries.R' 'cache.R' 'imageuri.R' + 'lazy_tensor.R' 'learner_torch_methods.R' + 'materialize.R' 'nn_graph.R' 'paramset_torchlearner.R' 'rd_info.R' diff --git a/NAMESPACE b/NAMESPACE index 6b884dc1..76314d6b 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,6 +1,7 @@ # Generated by roxygen2: do not edit by hand S3method("[",imageuri) +S3method("[",lazy_tensor) S3method("[<-",imageuri) S3method("[[",imageuri) S3method("[[<-",imageuri) @@ -9,6 +10,8 @@ S3method(as.data.table,DictionaryMlr3torchLosses) S3method(as.data.table,DictionaryMlr3torchOptimizers) S3method(as_imageuri,character) S3method(as_imageuri,imageuri) +S3method(as_lazy_tensor,DataDescriptor) +S3method(as_lazy_tensor,dataset) S3method(as_torch_callback,R6ClassGenerator) S3method(as_torch_callback,TorchCallback) S3method(as_torch_callback,character) @@ -24,6 +27,10 @@ S3method(as_torch_optimizer,character) S3method(as_torch_optimizer,torch_optimizer_generator) S3method(c,imageuri) S3method(col_info,DataBackendLazy) +S3method(format,lazy_tensor) +S3method(materialize,data.frame) +S3method(materialize,lazy_tensor) +S3method(materialize,list) S3method(print,ModelDescriptor) S3method(print,TorchIngressToken) S3method(reset_last_layer,AlexNet) @@ -40,12 +47,14 @@ S3method(t_opt,"NULL") S3method(t_opt,character) S3method(t_opts,"NULL") S3method(t_opts,character) +S3method(vec_ptype_abbr,lazy_tensor) export(CallbackSet) export(CallbackSetCheckpoint) export(CallbackSetHistory) export(CallbackSetProgress) export(ContextTorch) export(DataBackendLazy) +export(DataDescriptor) export(LearnerTorch) export(LearnerTorchAlexNet) export(LearnerTorchFeatureless) @@ -81,6 +90,7 @@ export(PipeOpTorchHead) export(PipeOpTorchIngress) export(PipeOpTorchIngressCategorical) export(PipeOpTorchIngressImage) +export(PipeOpTorchIngressLazyTensor) export(PipeOpTorchIngressNumeric) export(PipeOpTorchLayerNorm) export(PipeOpTorchLeakyReLU) @@ -120,6 +130,7 @@ export(TorchDescriptor) export(TorchIngressToken) export(TorchLoss) export(TorchOptimizer) +export(as_lazy_tensor) export(as_torch_callback) export(as_torch_callbacks) export(as_torch_loss) @@ -128,6 +139,9 @@ export(batchgetter_categ) export(batchgetter_num) export(callback_set) export(imageuri) +export(is_lazy_tensor) +export(lazy_tensor) +export(materialize) export(mlr3torch_callbacks) export(mlr3torch_losses) export(mlr3torch_optimizers) @@ -157,6 +171,7 @@ import(mlr3misc) import(mlr3pipelines) import(paradox) import(torch) +import(vctrs) importFrom(R6,R6Class) importFrom(R6,is.R6) importFrom(methods,formalArgs) diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R new file mode 100644 index 00000000..2978cd32 --- /dev/null +++ b/R/DataDescriptor.R @@ -0,0 +1,131 @@ +#' @title Data Descriptor +#' +#' @description +#' A data descriptor is a rather internal structure used in the [`lazy_tensor`] data type. +#' In essence it is an annotated [`torch::dataset`] and a preprocessing graph (consisting mosty of [`PipeOpModule`] +#' operators). The additional meta data (e.g. shapes) allows to preprocess [`lazy_tensors`] in an +#' [`mlr3pipelines::Graph`] just like any (non-lazy) data types. +#' +#' @param dataset ([`torch::dataset`])\cr +#' The torch dataset. +#' @param dataset_shapes (named `list()` of `integer()`s)\cr +#' The shapes of the output. +#' Names are the elements of the list returned by the dataset. +#' First dimension must be `NA`. +#' @param graph ([`Graph`])\cr +#' The preprocessing graph. +#' If left `NULL`, no preprocessing is applied to the data and `.input_map`, `.pointer` and `.pointer_shape` +#' are inferred in case the dataset returns only one element. +#' @param .input_map (`character()`)\cr +#' Character vector that must have the same length as the input of the graph. +#' Specifies how the data from the `dataset` is fed into the preprocessing graph. +#' @param .pointer (`character(2)` | `NULL`)\cr +#' Indicating an element on which a model is. Points to an output channel within `graph`: +#' Element 1 is the `PipeOp`'s id and element 2 is that `PipeOp`'s output channel. +#' @param .pointer_shape (`integer` | `NULL`)\cr +#' Shape of the output indicated by `.pointer`. Note that this is **without** the batch dimension as opposed +#' to the [`ModelDescriptor`]. The reason is that the .pointer_shape refers to exactly one element and hence +#' has no batch dimension. +#' @param clone_graph (`logical(1)`)\cr +#' Whether to clone the preprocessing graph. +#' +#' @export +#' @seealso ModelDescriptor, lazy_tensor +#' @examples +#' # Create a dataset +#' dsg = dataset( +#' initialize = function() self$x = torch_randn(10, 3, 3), +#' .getitem = function(i) self$x[i, ], +#' .length = function() nrow(self$x) +#' ) +#' ds = dsg() +#' +#' # Create the preprocessing graph +#' po_module = po("module", module = function(x) torch_reshape(x, c(-1, 9))) +#' po_module$output +#' graph = as_graph(po_module) +#' +#' # Create the data descriptor +#' +#' dd = DataDescriptor( +#' dataset = ds, +#' dataset_shapes = list(x = c(NA, 3, 3)), +#' graph = graph, +#' .input_map = "x", +#' .pointer = c("module", "output"), +#' .pointer_shape = c(NA, 9) +#' ) +#' +#' # with no preprocessing +#' dd1 = DataDescriptor(ds, list(x = c(NA, 3, 3))) +DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NULL, .pointer = NULL, + .pointer_shape = NULL, clone_graph = TRUE) { + assert_class(dataset, "dataset") + assert_shapes(dataset_shapes) + + if (is.null(graph)) { + if ((length(dataset_shapes) == 1L) && is.null(.input_map)) { + .input_map = names(dataset_shapes) + } + assert_true(length(.input_map) == 1L) + assert_subset(.input_map, names(dataset_shapes)) + + graph = as_graph(po("nop", id = paste0(class(dataset)[[1L]], "_", .input_map))) + .pointer = c(graph$output$op.id, graph$output$channel.name) + .pointer_shape = dataset_shapes[[.input_map]] + } else { + graph = as_graph(graph) + if (clone_graph) { + graph = graph$clone(deep = TRUE) + } + assert_true(length(graph$pipeops) >= 1L) + + if (any(is.null(.input_map), is.null(.pointer), is.null(.pointer_shape))) { + stopf("When passing a graph you need to specify .input_map, .pointer and .pointer_shape.") + } + + assert_choice(.pointer[[1]], names(graph$pipeops)) + assert_choice(.pointer[[2]], graph$pipeops[[.pointer[[1]]]]$output$name) + assert_subset(paste0(.pointer, collapse = "."), graph$output$name) + assert_integerish(.pointer_shape, min.len = 1L) + + assert_subset(.input_map, names(dataset_shapes)) + assert_true(length(.input_map) == length(graph$input$name)) + } + + # We get a warning that package:mlr3torch may not be available when loading (?) + dataset_hash = suppressWarnings(calculate_hash(dataset, dataset_shapes)) + obj = structure( + list( + dataset = dataset, + graph = graph, + dataset_shapes = dataset_shapes, + .input_map = .input_map, + .pointer = .pointer, + .pointer_shape = .pointer_shape, + .dataset_hash = dataset_hash, + .hash = NULL, # is set below + # Once a DataDescriptor is created the input PipeOps are fix, we save them + # here because they can be costly to compute + .graph_input = graph$input$name + ), + class = "DataDescriptor" + ) + + obj = set_data_descriptor_hash(obj) + + return(obj) +} + +# TODO: printer + +set_data_descriptor_hash = function(data_descriptor) { + data_descriptor$.hash = calculate_hash( + data_descriptor$.dataset_hash, + data_descriptor$graph$hash, + data_descriptor$.input_map, + data_descriptor$.pointer, + data_descriptor$.pointer_shape + ) + return(data_descriptor) +} diff --git a/R/PipeOpTorchConv.R b/R/PipeOpTorchConv.R index 53076404..5e5bee69 100644 --- a/R/PipeOpTorchConv.R +++ b/R/PipeOpTorchConv.R @@ -157,7 +157,7 @@ conv_output_shape = function(shape_in, conv_dim, padding, dilation, stride, kern shape_in = assert_integerish(shape_in, min.len = conv_dim + 1, coerce = TRUE) shape_head = utils::head(shape_in, -(conv_dim + 1)) if (length(shape_head) == 0) { - warningf("Input tensor does not have hve batch dimension") + warningf("Input tensor does not have have batch dimension.") } shape_tail = utils::tail(shape_in, conv_dim) c(shape_head, out_channels, diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index 77ccbe54..3b2b3b18 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -315,3 +315,52 @@ PipeOpTorchIngressImage = R6Class("PipeOpTorchIngressImage", ) ) register_po("torch_ingress_img", PipeOpTorchIngressImage) + +#' @title Ingress for Lazy Tensor +#' @name mlr_pipeops_torch_ingress_ltnsr +#' @description +#' Ingress for [`lazy_tensor`] column. +#' This ingress might not return the #' @inheritSection mlr_pipeops_torch_ingress Input and Output Channels +#' @inheritSection mlr_pipeops_torch_ingress State +#' +#' @section Parameters: +#' No parameters. +#' +#' @section Internals: +#' The output of the created batchgetter merely returns the data as is. +#' The dataset is then responsible to materialize the tensors. +#' By doing so, the data-loading can be made more efficient, e.g. when two different ingress tokens exist +#' for lazy tensors columns that share the same dataset. +#' @family PipeOps +#' @family Graph Network +#' @export +#' @examples +#' TODO: +PipeOpTorchIngressLazyTensor = R6Class("PipeOpTorchIngressLazyTensor", + inherit = PipeOpTorchIngress, + public = list( + #' @description + #' Creates a new instance of this [R6][R6::R6Class] class. + #' @template params_pipelines + initialize = function(id = "torch_ingress_ltnsr", param_vals = list()) { + super$initialize(id = id, param_vals = param_vals, feature_types = "lazy_tensor") + } + ), + private = list( + .shape = function(task, param_vals) { + lazy_cols = task$feature_types[get("type") == "lazy_tensor", "id"][[1L]] + if (length(lazy_cols) != 1L) { + stopf("PipeOpTorchIngressLazyTensor expects 1 lazy_tensor feature, but got %i.", length(lazy_cols)) + } + example = task$data(task$row_ids[1L], lazy_cols)[[1L]][[1L]] + attr(example, "data_descriptor")$.pointer_shape + }, + .get_batchgetter = function(task, param_vals) { + crate(function(data, device) { + data[[1L]] + }) + } + ) +) + +register_po("torch_ingress_ltnsr", PipeOpTorchIngressLazyTensor) diff --git a/R/TaskClassif_mnist.R b/R/TaskClassif_mnist.R new file mode 100644 index 00000000..9d8c1e44 --- /dev/null +++ b/R/TaskClassif_mnist.R @@ -0,0 +1,98 @@ +#' @title MNIST Image classification +#' @name mlr_tasks_mnist +#' @description +#' Classical MNIST image classification +#' +#' The underlying [`DataBackend`] contains columns `"label"`, `"image"`, `"row_id"`, `"split"`, where the last column +#' indicates whether the row belongs to the train or test set. +#' +#' The first 60000 rows belong to the training set, the last 10000 rows to the test set. +#' +#' @section Construction: +#' ``` +#' tsk("mnist") +#' ``` +#' +#' @section Meta Information: +#' `r rd_info_task_torch("mnist", missings = FALSE)` +#' +#' @references +#' `r format_bib("mnist")` +#' +NULL + +# @param path (`character(1)`)\cr +# The cache_dir/datasets/tiny_imagenet folder. +constructor_mnist = function(path) { + # path points to {cache_dir, tempfile}/data/mnist + d_train = torchvision::mnist_dataset(root = file.path(path), train = TRUE, download = TRUE) + # test set is already downloaded with the training set above + d_test = torchvision::mnist_dataset(root = file.path(path), train = FALSE) + + images_train = array(d_train$data, dim = c(60000, 1, 28, 28)) + images_test = array(d_test$data, dim = c(10000, 1, 28, 28)) + + images = array(NA, dim = c(70000, 1, 28, 28)) + images[1:60000, , , ] = images_train + images[60001:70000, , , ] = images_test + labels = factor(c(d_train$targets, d_test$targets), levels = 1:10, labels = as.character(0:9)) + + list(label = labels, image = images) +} + +load_task_mnist = function(id = "mnist") { + cached_constructor = function() { + # We need this as otherwise the factor level are differently ordered, + # which causes the hard-coded col-info to be wrong for some locales + # (whether a < A or A > a depends on the locale) + withr::with_locale(c(LC_COLLATE = "C"), { + data = cached(constructor_mnist, "datasets", "mnist")$data + }) + + ds = dataset( + initialize = function(images) { + self$images = torch_tensor(images, dtype = torch_float32()) + }, + .getbatch = function(idx) { + list(image = self$images[idx, , , drop = FALSE]) + }, + .length = function() dim(self$images)[1L] + )(data$image) + + data_descriptor = DataDescriptor(dataset = ds, list(image = c(NA, 1, 28, 28))) + + dt = data.table( + image = lazy_tensor(data_descriptor), + label = data$label, + row_id = seq_along(data$label), + split = factor(c(rep("train", 60000), rep("test", 10000))) + ) + + DataBackendDataTable$new(data = dt, primary_key = "row_id") + } + + backend = DataBackendLazy$new( + constructor = cached_constructor, + rownames = seq_len(70000), + col_info = load_col_info("mnist"), + primary_key = "row_id", + data_formats = "data.table" + ) + + task = TaskClassif$new( + backend = backend, + id = "mnist", + target = "label", + label = "MNIST Image Classifiacation", + ) + + backend$hash = task$man = "mlr3::mlr_tasks_mnist" + + task$row_roles$use = seq_len(60000) + task$row_roles$test = seq(from = 60001, 70000) + task$col_roles$feature = "image" + + return(task) +} + +register_task("mnist", load_task_mnist) diff --git a/R/bibentries.R b/R/bibentries.R index 57b8e127..6e4d7289 100644 --- a/R/bibentries.R +++ b/R/bibentries.R @@ -63,5 +63,15 @@ bibentries = c( # nolint start pages = "248--255", year = "2009", organization = "IEEE" + ), + mnist = bibentry("article", + author='Lecun, Y. and Bottou, L. and Bengio, Y. and Haffner, P.', + journal='Proceedings of the IEEE', + title='Gradient-based learning applied to document recognition', + year='1998', + volume='86', + number='11', + pages='2278-2324', + doi='10.1109/5.726791' ) ) # nolint end diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R new file mode 100644 index 00000000..aaac28b8 --- /dev/null +++ b/R/lazy_tensor.R @@ -0,0 +1,86 @@ +#' @title Create a lazy tensor +#' +#' @description +#' Create a lazy tensor. +#' @param data_descriptor ([`DataDescriptor`] or `NULL`)\cr +#' The data descriptor or `NULL` for a lazy tensor of length 0. +#' @param ids (`integer()`)\cr +#' The elements of the `data_descriptor` that the created lazy tensor contains. +#' @export +lazy_tensor = function(data_descriptor = NULL, ids = NULL) { + assert_class(data_descriptor, "DataDescriptor", null.ok = TRUE) + if (is.null(data_descriptor)) { + assert_integerish(ids, len = 0L, null.ok = TRUE) + return(new_lazy_tensor(NULL, integer(0))) + } + if (is.null(ids)) { + ids = seq_along(data_descriptor$dataset) + } else { + assert_integerish(ids, lower = 1L, upper = length(data_descriptor$dataset), any.missing = FALSE) + } + + new_lazy_tensor(data_descriptor, ids) +} + +new_lazy_tensor = function(data_descriptor, ids) { + vctrs::new_vctr(ids, data_descriptor = data_descriptor, class = "lazy_tensor") +} + +#' @export +format.lazy_tensor = function(x, ...) { # nolint + if (!length(x)) return(character(0)) + shape = paste0(attr(x, "data_descriptor")$.pointer_shape[-1L], collapse = "x") + map_chr(x, function(elt) { + sprintf("", shape) + }) +} + + +#' @title Convert to lazy tensor +#' @description +#' Convert a object to a [`lazy_tensor()`]. +#' @param x (any)\cr +#' Object to convert to a [`lazy_tensor()`] +#' @param ... (any)\cr +#' Additional arguments passed to the method. +#' @export +as_lazy_tensor = function(x, ...) { + UseMethod("as_lazy_tensor") +} + +#' @export +as_lazy_tensor.DataDescriptor = function(x, ids = NULL) { + lazy_tensor(data_descriptor, ids = ids) +} + +#' @export +as_lazy_tensor.dataset = function(x, dataset_shapes, ids = NULL, ...) { + dd = DataDescriptor(dataset = x, dataset_shapes = dataset_shapes, ...) + lazy_tensor(dd, ids) +} + + +#' @export +vec_ptype_abbr.lazy_tensor <- function(x, ...) { # nolint + "ltnsr" +} + +#' @export +`[.lazy_tensor` = function(x, i, ...) { # nolint + x = NextMethod() + if (length(x) == 0L) { + attr(x, "data_descriptor") = NULL + } + return(x) +} + +#' @title Check for lazy tensor +#' @description +#' Checks whether an object is a lazy tensor. +#' @param x (any)\cr +#' Object to check. +#' @export +is_lazy_tensor = function(x) { + inherits(x, "lazy_tensor") +} + diff --git a/R/materialize.R b/R/materialize.R new file mode 100644 index 00000000..087dc0cc --- /dev/null +++ b/R/materialize.R @@ -0,0 +1,167 @@ +#' @title Materialize Lazy Tensor Columns +#' @description +#' This will materialize all columns from a `data.frame` containing [`lazy_tensor()`] columns. +#' @details +#' Caching is applied to ensure that each batch from the datasets wrapped by the lazy tensors is only loaded once. +#' It is also ensured that each graph is only applied once to a given input batch, i.e. different columns +#' can share the same graph, dataset and indices but point to different outputs. +#' @export +materialize = function(x, device = "cpu", ...) { + UseMethod("materialize") +} + +#' @export +materialize.list = function(x, device = "cpu") { + input_cache = new.env() # nolint + output_cache = new.env() # nolint + + keep_results_prev = list() + walk(x, function(col) { + keep+ + if (is_lazy_tensor(col)) { + keep_results_prev[[graph$hash]] = graph$keep_results + attr(col, "data_descriptor")$graph$keep_results = character() + + } + }) + # clean up the keep_results after + on.exit({walk(x, function(col) { + if (is_lazy_tensor(x)) { + graph = attr(x, "data_descriptor")$graph + graph$keep_results = keep_results_prev[[graph$hash]] + } + + })}, add = TRUE) + + walk(x, function(col) { + if (is_lazy_tensor(col)) { + dd = attr(col, "data_descriptor") + dd$graph$keep_results = union(dd$graph$keep_results, dd$.pointer[1L]) + } + }) + + # TODO: No hashing when there is only one column + map(x, function(col) { + if (!is_lazy_tensor(col)) { + return(col) + } + data_descriptor = attr(col, "data_descriptor") + dataset_hash = data_descriptor$.dataset_hash + + ds = data_descriptor$dataset + + ids = vec_data(col) + + input_hash = calculate_hash(dataset_hash, ids) + + if (!exists(input_hash, input_cache, inherits = FALSE)) { + input = if (is.null(ds$.getbatch)) { # .getindex is never NULL but a function that errs if it was not defined + torch_cat(map(ids, function(id) ds$.getitem(id)), dim = 1L) + } else { + ds$.getbatch(ids) + } + + input_cache[[input_hash]] = input + } else { + input = input_cache[[input_hash]] + } + + input = set_names(input[data_descriptor$.input_map], data_descriptor$graph$.graph_input) + + output_hash = calculate_hash(ids, data_descriptor$.hash) + + if (!exists(output_hash, output_cache, inherits = FALSE)) { + data_descriptor$graph$train(input, single_input = FALSE) + output = map(data_descriptor$graph$pipeops[data_descriptor$graph$keep_results], ".result") + output_cache[[output_hash]] = output + } else { + output = output_cache[[output_hash]] + } + # FIXME: This will fail when the .pointer is not an output of the graph + # https://github.com/mlr-org/mlr3torch/issues/138 + + output[[data_descriptor$.pointer[1L]]][[data_descriptor$.pointer[2L]]]$to(device = device) + }) +} + +#' @export +materialize.lazy_tensor = function(x, device = "cpu", cache = NULL) { + do_caching = !is.null(cache) + ids = vec_data(x) + + data_descriptor = attr(x, "data_descriptor") + ds = data_descriptor$dataset + graph = data_descriptor$graph + prev_results = graph$keep_results + on.exit({graph$keep_results = prev_results}, add = TRUE) + if (test_flag(prev_results)) { + graph$keep_results = data_descriptor$.pointer[1L] + } else { + graph$keep_results = union(prev_results, data_descriptor$.pointer[1L]) + } + + if (do_caching) { + output_hash = calculate_hash(ids, data_descriptor$.hash) + output_hit = exists(output_hash, cache$output, inherits = FALSE) + + if (output_hit) { + return(cache$output[[output_hash]][[data_descriptor$.pointer]]) + } + + input_hash = calculate_hash(dataset_hash, ids) + input_hit = exists(input_hash, cache$input, inherits = FALSE) + + if (input_hit) { + input = cache$input[[input_hash]] + input_hit = TRUE + } + } + + if (!do_caching || !input_hit) { + input = if (is.null(ds$.getbatch)) { # .getindex is never NULL but a function that errs if it was not defined + tmp = transpose_list(map(ids, function(id) map(ds$.getitem(id), function(x) x$unsqueeze(1)))) + map(tmp, function(x) torch_cat(x, dim = 1L)) + } else { + ds$.getbatch(ids) + } + } + + if (do_caching && !input_hit) { + cache$input[[input_hash]] = input + } + + # input is the output of a dataset so it can contain more than what we need for the graph, + # also we need to set the correct names. + # This is done after retrieving the element from the cache / before saving the element to the cache because + # this can change + + browser() + input = set_names(input[data_descriptor$.input_map], data_descriptor$.graph_input) + + graph$train(input, single_input = FALSE) + output = map(data_descriptor$graph$keep_results, function(id) graph$pipeops[[id]]$.result) + output = set_names(output, data_descriptor$graph$keep_results) + + if (do_caching) { + cache$output[[output_hash]] = output + } + + # discard the results + walk(data_descriptor$graph$pipeops[data_descriptor$graph$keep_results], function(x) x$.result = NULL) + + output = output[[data_descriptor$.pointer[1L]]][[data_descriptor$.pointer[2L]]]$to(device = device) +} + + +#' @method materialize data.frame +#' @export +materialize.data.frame = materialize.list + + +batchgetter_lazy_tensor = function(data, device, cache = NULL) { + if (is.null(cache)) { + materialize(data[[1L]])[[1L]] + + + } +} diff --git a/R/paramset_torchlearner.R b/R/paramset_torchlearner.R index 5173a9ff..7fcb686a 100644 --- a/R/paramset_torchlearner.R +++ b/R/paramset_torchlearner.R @@ -26,7 +26,7 @@ make_check_measures = function(task_type) { return("Measures must not require a learner or model.") } return(TRUE) - }, task_type = task_type, .parent = topenv()) + }, task_type, .parent = topenv()) } diff --git a/R/task_dataset.R b/R/task_dataset.R index 86f2f439..70d58e82 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -61,6 +61,8 @@ task_dataset = dataset( x = lapply(self$feature_ingress_tokens, function(it) { it$batchgetter(datapool[, it$features, with = FALSE], self$device) }) + x = materialize(x, device = self$device) + y = if (!is.null(self$target_batchgetter)) { self$target_batchgetter(datapool[, self$task$target_names, with = FALSE], self$device) diff --git a/R/utils.R b/R/utils.R index ba53fe54..4248cab7 100644 --- a/R/utils.R +++ b/R/utils.R @@ -36,7 +36,7 @@ make_check_vector = function(d) { } tmp = if (d == 1) "." else sprintf(" or %s.", d) sprintf("Must be an integerish vector of length 1%s", tmp) - }, d = d, .parent = topenv()) + }, d, .parent = topenv()) } check_function_or_null = function(x) check_function(x, null.ok = TRUE) @@ -60,17 +60,6 @@ broadcast_list = function(...) { Reduce(broadcast, list(...)) } -assert_shape = function(shape, name) { - if (!(is.na(shape[[1L]]) && sum(is.na(shape)) == 1)) { - stopf("Input '%s' has shape (%s) but must have exactly one NA in the first dimension (batch size).", - name, paste0(shape, collapse = ", ")) - } -} - -assert_shapes = function(shapes) { - iwalk(shapes, function(shape, name) assert_shape(shape, name)) -} - check_nn_module_generator = function(x) { if (inherits(x, "nn_module_generator")) { return(TRUE) @@ -159,3 +148,47 @@ test_equal_col_info = function(x, y) { } + +# a function that has argument names 'names' and returns its arguments as a named list. +# used to simulate argument matching for `...`-functions. +# example: +# f = argument_matcher(c("a", "b", "c")) +# f(1, 2, 3) --> list(a = 1, b = 2, c = 3) +# f(1, 2, a = 3) --> list(a = 3, b = 1, c = 2) +# usecase: +# ff = function(...) { +# l = argument_matcher(c("a", "b", "c"))(...) +# l$a + l$b +# } +# # behaves like +# ff(a, b, c) a + b +# (Except in the aqward case of missing args) +argument_matcher = function(args) { + fn = as.function(c(named_list(args, substitute()), quote(as.list(environment())))) + environment(fn) = topenv() + fn +} + +as_shape = function(shape) { + assert_integerish(shape) + if (!is.na(shape[1L])) { + shape = c(NA_integer_, shape) + } + assert_integerish(shape[-1], any.missing = FALSE) + shape +} + +assert_shape = function(shape, null.ok = FALSE) { # nolint + if (is.null(shape) && null.ok) return(TRUE) + + assert_integerish(shape, min.len = 2L) + if (!(is.na(shape[[1L]]) || anyNA(shape[-1L]))) { + stopf("Shape must have exactly one NA in the batch dimension.") + } + TRUE +} + +assert_shapes = function(shapes) { + assert_list(shapes, names = "unique", min.len = 1L) + walk(shapes, assert_shape) +} diff --git a/R/zzz.R b/R/zzz.R index 5f260f8e..7a4ae234 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -8,6 +8,7 @@ #' @import torch #' @import mlr3pipelines #' @import mlr3 +#' @import vctrs #' @importFrom tools R_user_dir #' #' @section Options: @@ -18,14 +19,14 @@ "_PACKAGE" # to silence RCMD check -utils::globalVariables(c("self", "private", "super")) +utils::globalVariables(c("self", "private", "super", "..")) mlr3torch_pipeops = new.env() mlr3torch_learners = new.env() mlr3torch_tasks = new.env() mlr3torch_resamplings = new.env() mlr3torch_pipeop_tags = c("torch", "activation") -mlr3torch_feature_types = c(img = "imageuri") +mlr3torch_feature_types = c(img = "imageuri", ltnsr = "lazy_tensor") # metainf must be manually added in the register_mlr3pipelines function # Because the value is substituted, we cannot pass it through this function @@ -50,7 +51,7 @@ register_learner = function(name, constructor) { # For this reason, we need this hacky solution here, might change in the future in mlr3misc fn = crate(function() { invoke(constructor$new, task_type = task_type, .args = as.list(match.call()[-1])) - }, constructor = constructor, task_type = task_type, .parent = topenv()) + }, constructor, task_type, .parent = topenv()) fmls = formals(constructor$public_methods$initialize) fmls$task_type = NULL formals(fn) = fmls diff --git a/data-raw/mnist.R b/data-raw/mnist.R new file mode 100644 index 00000000..e69de29b diff --git a/inst/col_info/mnist.rds b/inst/col_info/mnist.rds new file mode 100644 index 0000000000000000000000000000000000000000..f28bbe19cec311b37822db972404bec3c8a2346c GIT binary patch literal 274 zcmV+t0qy=DiwFP!000001D%oGYQr!Lh1Dd@XvScpu(w#)|GF306Kt@%qBcq~xNfn< zMt8LbAI+3vmCTnT*nB#&jxFWA0)QNfT=uabjNe{gu4WQV4+(&CS%rL)K55ptA`L7q z$i|@bo6osvG!?eia8i6~@oP6{a$)1Os>LNAqZ8wpR+J_IrUw^*eRQniiP5#fjl!+M zox;7sgTkZ2lfq2ld2mY>#eylYHpU)}6D{jctLSh|Ay(y4%#On-c(>J=m6krphQweZ z!>iTgtS|nSt?Rm<^rof75R&&*4Kmh@3rl~L){A3ea8dU&_6}_w$hMwZ5ijG~51Ri^ Y8>ReMrY1U!1`gu;3wPIW1!)2R0DJg`5dZ)H literal 0 HcmV?d00001 diff --git a/lazy_tensor_old.R b/lazy_tensor_old.R new file mode 100644 index 00000000..253d60de --- /dev/null +++ b/lazy_tensor_old.R @@ -0,0 +1,14 @@ +#' @export +format.lazy_tensor = function(x, ...) { # nolint + if (!length(x)) return(character(0)) + shape = paste0(x$shape[-1L], collapse = "x") + map_chr(x, function(elt) { + sprintf("", shape) + }) +} + + +#' @export +vec_ptype_abbr.lazy_tensor <- function(x, ...) { # nolint + "ltnsr" +} diff --git a/man/DataDescriptor.Rd b/man/DataDescriptor.Rd new file mode 100644 index 00000000..063f43c3 --- /dev/null +++ b/man/DataDescriptor.Rd @@ -0,0 +1,83 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/DataDescriptor.R +\name{DataDescriptor} +\alias{DataDescriptor} +\title{Data Descriptor} +\usage{ +DataDescriptor( + dataset, + dataset_shapes, + graph = NULL, + .input_map = NULL, + .pointer = NULL, + .pointer_shape = NULL, + clone_graph = TRUE +) +} +\arguments{ +\item{dataset}{(\code{\link[torch:dataset]{torch::dataset}})\cr +The torch dataset.} + +\item{dataset_shapes}{(named \code{list()} of \code{integer()}s)\cr +The shapes of the output. +Names are the elements of the list returned by the dataset. +First dimension must be \code{NA}.} + +\item{graph}{(\code{\link{Graph}})\cr +The preprocessing graph. +If left \code{NULL}, no preprocessing is applied to the data and \code{.input_map}, \code{.pointer} and \code{.pointer_shape} +are inferred in case the dataset returns only one element.} + +\item{.input_map}{(\code{character()})\cr +Character vector that must have the same length as the input of the graph. +Specifies how the data from the \code{dataset} is fed into the preprocessing graph.} + +\item{.pointer}{(\code{character(2)} | \code{NULL})\cr +Indicating an element on which a model is. Points to an output channel within \code{graph}: +Element 1 is the \code{PipeOp}'s id and element 2 is that \code{PipeOp}'s output channel.} + +\item{.pointer_shape}{(\code{integer} | \code{NULL})\cr +Shape of the output indicated by \code{.pointer}. Note that this is \strong{without} the batch dimension as opposed +to the \code{\link{ModelDescriptor}}. The reason is that the .pointer_shape refers to exactly one element and hence +has no batch dimension.} + +\item{clone_graph}{(\code{logical(1)})\cr +Whether to clone the preprocessing graph.} +} +\description{ +A data descriptor is a rather internal structure used in the \code{\link{lazy_tensor}} data type. +In essence it is an annotated \code{\link[torch:dataset]{torch::dataset}} and a preprocessing graph (consisting mosty of \code{\link{PipeOpModule}} +operators). The additional meta data (e.g. shapes) allows to preprocess \code{\link{lazy_tensors}} in an +\code{\link[mlr3pipelines:Graph]{mlr3pipelines::Graph}} just like any (non-lazy) data types. +} +\examples{ +# Create a dataset +dsg = dataset( + initialize = function() self$x = torch_randn(10, 3, 3), + .getitem = function(i) self$x[i, ], + .length = function() nrow(self$x) +) +ds = dsg() + +# Create the preprocessing graph +po_module = po("module", module = function(x) torch_reshape(x, c(-1, 9))) +po_module$output +graph = as_graph(po_module) + +# Create the data descriptor + +dd = DataDescriptor( + dataset = ds, + dataset_shapes = list(x = c(NA, 3, 3)), + graph = graph, + .input_map = "x", + .pointer = c("module", "output"), + .pointer_shape = c(NA, 9) +) + +# with no preprocessing +dd1 = DataDescriptor(ds, list(x = c(NA, 3, 3))) +} +\seealso{ +ModelDescriptor, lazy_tensor +} diff --git a/man/ModelDescriptor.Rd b/man/ModelDescriptor.Rd index ca509b60..b5d55034 100644 --- a/man/ModelDescriptor.Rd +++ b/man/ModelDescriptor.Rd @@ -79,6 +79,7 @@ Other Graph Network: \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_img}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch}}, diff --git a/man/TorchIngressToken.Rd b/man/TorchIngressToken.Rd index 9ab9fbe6..fee5554a 100644 --- a/man/TorchIngressToken.Rd +++ b/man/TorchIngressToken.Rd @@ -57,6 +57,7 @@ Other Graph Network: \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_img}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch}}, diff --git a/man/as_lazy_tensor.Rd b/man/as_lazy_tensor.Rd new file mode 100644 index 00000000..95c17cf1 --- /dev/null +++ b/man/as_lazy_tensor.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lazy_tensor.R +\name{as_lazy_tensor} +\alias{as_lazy_tensor} +\title{Convert to lazy tensor} +\usage{ +as_lazy_tensor(x, ...) +} +\arguments{ +\item{x}{(any)\cr +Object to convert to a \code{\link[=lazy_tensor]{lazy_tensor()}}} + +\item{...}{(any)\cr +Additional arguments passed to the method.} +} +\description{ +Convert a object to a \code{\link[=lazy_tensor]{lazy_tensor()}}. +} diff --git a/man/is_lazy_tensor.Rd b/man/is_lazy_tensor.Rd new file mode 100644 index 00000000..02e5e216 --- /dev/null +++ b/man/is_lazy_tensor.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lazy_tensor.R +\name{is_lazy_tensor} +\alias{is_lazy_tensor} +\title{Check for lazy tensor} +\usage{ +is_lazy_tensor(x) +} +\arguments{ +\item{x}{(any)\cr +Object to check.} +} +\description{ +Checks whether an object is a lazy tensor. +} diff --git a/man/lazy_tensor.Rd b/man/lazy_tensor.Rd new file mode 100644 index 00000000..209069fd --- /dev/null +++ b/man/lazy_tensor.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lazy_tensor.R +\name{lazy_tensor} +\alias{lazy_tensor} +\title{Create a lazy tensor} +\usage{ +lazy_tensor(data_descriptor = NULL, ids = NULL) +} +\arguments{ +\item{data_descriptor}{(\code{\link{DataDescriptor}} or \code{NULL})\cr +The data descriptor or \code{NULL} for a lazy tensor of length 0.} + +\item{ids}{(\code{integer()})\cr +The elements of the \code{data_descriptor} that the created lazy tensor contains.} +} +\description{ +Create a lazy tensor. +} diff --git a/man/materialize.Rd b/man/materialize.Rd new file mode 100644 index 00000000..77a2a75f --- /dev/null +++ b/man/materialize.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/materialize.R +\name{materialize} +\alias{materialize} +\title{Materialize Lazy Tensor Columns} +\usage{ +materialize(x, device = "cpu", ...) +} +\description{ +This will materialize all columns from a \code{data.frame} containing \code{\link[=lazy_tensor]{lazy_tensor()}} columns. +} +\details{ +Caching is applied to ensure that each batch from the datasets wrapped by the lazy tensors is only loaded once. +It is also ensured that each graph is only applied once to a given input batch, i.e. different columns +can share the same graph, dataset and indices but point to different outputs. +} diff --git a/man/mlr_learners.torch_featureless.Rd b/man/mlr_learners.torch_featureless.Rd index 12855c68..0db8e2d9 100644 --- a/man/mlr_learners.torch_featureless.Rd +++ b/man/mlr_learners.torch_featureless.Rd @@ -28,7 +28,7 @@ lrn("regr.torch_featureless", ...) \item classif: 'response', 'prob' \item regr: 'response' } -\item Feature Types: \dQuote{logical}, \dQuote{integer}, \dQuote{numeric}, \dQuote{character}, \dQuote{factor}, \dQuote{ordered}, \dQuote{POSIXct}, \dQuote{imageuri} +\item Feature Types: \dQuote{logical}, \dQuote{integer}, \dQuote{numeric}, \dQuote{character}, \dQuote{factor}, \dQuote{ordered}, \dQuote{POSIXct}, \dQuote{imageuri}, \dQuote{lazy_tensor} \item Required Packages: \CRANpkg{mlr3}, \CRANpkg{mlr3torch}, \CRANpkg{torch} } } diff --git a/man/mlr_learners_torch_model.Rd b/man/mlr_learners_torch_model.Rd index fc1f816e..ce94fb8c 100644 --- a/man/mlr_learners_torch_model.Rd +++ b/man/mlr_learners_torch_model.Rd @@ -53,6 +53,7 @@ Other Graph Network: \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_img}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch}}, diff --git a/man/mlr_pipeops_module.Rd b/man/mlr_pipeops_module.Rd index 5d2cb04b..52e3a8d9 100644 --- a/man/mlr_pipeops_module.Rd +++ b/man/mlr_pipeops_module.Rd @@ -91,6 +91,7 @@ Other Graph Network: \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_img}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch}}, diff --git a/man/mlr_pipeops_nn_avg_pool1d.Rd b/man/mlr_pipeops_nn_avg_pool1d.Rd index 48e166e0..aa30f4fb 100644 --- a/man/mlr_pipeops_nn_avg_pool1d.Rd +++ b/man/mlr_pipeops_nn_avg_pool1d.Rd @@ -105,6 +105,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_avg_pool2d.Rd b/man/mlr_pipeops_nn_avg_pool2d.Rd index cafb8158..63dcedcf 100644 --- a/man/mlr_pipeops_nn_avg_pool2d.Rd +++ b/man/mlr_pipeops_nn_avg_pool2d.Rd @@ -105,6 +105,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_avg_pool3d.Rd b/man/mlr_pipeops_nn_avg_pool3d.Rd index 3a05c828..d7c79589 100644 --- a/man/mlr_pipeops_nn_avg_pool3d.Rd +++ b/man/mlr_pipeops_nn_avg_pool3d.Rd @@ -105,6 +105,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_batch_norm1d.Rd b/man/mlr_pipeops_nn_batch_norm1d.Rd index 9e897fc9..7c508d49 100644 --- a/man/mlr_pipeops_nn_batch_norm1d.Rd +++ b/man/mlr_pipeops_nn_batch_norm1d.Rd @@ -103,6 +103,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_batch_norm2d.Rd b/man/mlr_pipeops_nn_batch_norm2d.Rd index 27135eb7..b311e42d 100644 --- a/man/mlr_pipeops_nn_batch_norm2d.Rd +++ b/man/mlr_pipeops_nn_batch_norm2d.Rd @@ -103,6 +103,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_batch_norm3d.Rd b/man/mlr_pipeops_nn_batch_norm3d.Rd index ca5e91f7..3cb0ca60 100644 --- a/man/mlr_pipeops_nn_batch_norm3d.Rd +++ b/man/mlr_pipeops_nn_batch_norm3d.Rd @@ -103,6 +103,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_celu.Rd b/man/mlr_pipeops_nn_celu.Rd index 542afbfa..ebe7046b 100644 --- a/man/mlr_pipeops_nn_celu.Rd +++ b/man/mlr_pipeops_nn_celu.Rd @@ -94,6 +94,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_conv1d.Rd b/man/mlr_pipeops_nn_conv1d.Rd index a607c5de..59dbf860 100644 --- a/man/mlr_pipeops_nn_conv1d.Rd +++ b/man/mlr_pipeops_nn_conv1d.Rd @@ -109,6 +109,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_conv2d.Rd b/man/mlr_pipeops_nn_conv2d.Rd index baff3529..a3fa342c 100644 --- a/man/mlr_pipeops_nn_conv2d.Rd +++ b/man/mlr_pipeops_nn_conv2d.Rd @@ -109,6 +109,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_conv3d.Rd b/man/mlr_pipeops_nn_conv3d.Rd index 8904477e..082dd671 100644 --- a/man/mlr_pipeops_nn_conv3d.Rd +++ b/man/mlr_pipeops_nn_conv3d.Rd @@ -109,6 +109,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_conv_transpose1d.Rd b/man/mlr_pipeops_nn_conv_transpose1d.Rd index e2091c2d..edb55f4b 100644 --- a/man/mlr_pipeops_nn_conv_transpose1d.Rd +++ b/man/mlr_pipeops_nn_conv_transpose1d.Rd @@ -112,6 +112,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_conv_transpose2d.Rd b/man/mlr_pipeops_nn_conv_transpose2d.Rd index d26d2de7..d8dacb30 100644 --- a/man/mlr_pipeops_nn_conv_transpose2d.Rd +++ b/man/mlr_pipeops_nn_conv_transpose2d.Rd @@ -111,6 +111,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_conv_transpose3d.Rd b/man/mlr_pipeops_nn_conv_transpose3d.Rd index 444c58f3..76fa706e 100644 --- a/man/mlr_pipeops_nn_conv_transpose3d.Rd +++ b/man/mlr_pipeops_nn_conv_transpose3d.Rd @@ -111,6 +111,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_dropout.Rd b/man/mlr_pipeops_nn_dropout.Rd index 7fae00ed..7c5f3d2f 100644 --- a/man/mlr_pipeops_nn_dropout.Rd +++ b/man/mlr_pipeops_nn_dropout.Rd @@ -97,6 +97,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_elu.Rd b/man/mlr_pipeops_nn_elu.Rd index ef3bce13..ee8745e5 100644 --- a/man/mlr_pipeops_nn_elu.Rd +++ b/man/mlr_pipeops_nn_elu.Rd @@ -95,6 +95,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_flatten.Rd b/man/mlr_pipeops_nn_flatten.Rd index dc092b3d..ea0cabc9 100644 --- a/man/mlr_pipeops_nn_flatten.Rd +++ b/man/mlr_pipeops_nn_flatten.Rd @@ -93,6 +93,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_gelu.Rd b/man/mlr_pipeops_nn_gelu.Rd index 06216bc9..c3659258 100644 --- a/man/mlr_pipeops_nn_gelu.Rd +++ b/man/mlr_pipeops_nn_gelu.Rd @@ -92,6 +92,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_glu.Rd b/man/mlr_pipeops_nn_glu.Rd index 696c3e9d..2a82f15b 100644 --- a/man/mlr_pipeops_nn_glu.Rd +++ b/man/mlr_pipeops_nn_glu.Rd @@ -92,6 +92,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_hardshrink.Rd b/man/mlr_pipeops_nn_hardshrink.Rd index 3f805673..bc36d117 100644 --- a/man/mlr_pipeops_nn_hardshrink.Rd +++ b/man/mlr_pipeops_nn_hardshrink.Rd @@ -92,6 +92,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_hardsigmoid.Rd b/man/mlr_pipeops_nn_hardsigmoid.Rd index f54879e3..bc491251 100644 --- a/man/mlr_pipeops_nn_hardsigmoid.Rd +++ b/man/mlr_pipeops_nn_hardsigmoid.Rd @@ -89,6 +89,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_hardtanh.Rd b/man/mlr_pipeops_nn_hardtanh.Rd index a3affede..54dcebb5 100644 --- a/man/mlr_pipeops_nn_hardtanh.Rd +++ b/man/mlr_pipeops_nn_hardtanh.Rd @@ -90,6 +90,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_head.Rd b/man/mlr_pipeops_nn_head.Rd index 04a88662..7e2db85e 100644 --- a/man/mlr_pipeops_nn_head.Rd +++ b/man/mlr_pipeops_nn_head.Rd @@ -97,6 +97,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_layer_norm.Rd b/man/mlr_pipeops_nn_layer_norm.Rd index 894c761f..2bc95fab 100644 --- a/man/mlr_pipeops_nn_layer_norm.Rd +++ b/man/mlr_pipeops_nn_layer_norm.Rd @@ -99,6 +99,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_leaky_relu.Rd b/man/mlr_pipeops_nn_leaky_relu.Rd index 0c2891d1..29de56e5 100644 --- a/man/mlr_pipeops_nn_leaky_relu.Rd +++ b/man/mlr_pipeops_nn_leaky_relu.Rd @@ -95,6 +95,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_linear.Rd b/man/mlr_pipeops_nn_linear.Rd index 0eda6889..88b5ab1b 100644 --- a/man/mlr_pipeops_nn_linear.Rd +++ b/man/mlr_pipeops_nn_linear.Rd @@ -97,6 +97,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_log_sigmoid.Rd b/man/mlr_pipeops_nn_log_sigmoid.Rd index bb69680c..bd8d59db 100644 --- a/man/mlr_pipeops_nn_log_sigmoid.Rd +++ b/man/mlr_pipeops_nn_log_sigmoid.Rd @@ -89,6 +89,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_max_pool1d.Rd b/man/mlr_pipeops_nn_max_pool1d.Rd index 5c13e3e7..cb5bf6b7 100644 --- a/man/mlr_pipeops_nn_max_pool1d.Rd +++ b/man/mlr_pipeops_nn_max_pool1d.Rd @@ -103,6 +103,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_max_pool2d.Rd b/man/mlr_pipeops_nn_max_pool2d.Rd index e87d84e4..b3939784 100644 --- a/man/mlr_pipeops_nn_max_pool2d.Rd +++ b/man/mlr_pipeops_nn_max_pool2d.Rd @@ -103,6 +103,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_max_pool3d.Rd b/man/mlr_pipeops_nn_max_pool3d.Rd index 0555adf9..d7aa6fce 100644 --- a/man/mlr_pipeops_nn_max_pool3d.Rd +++ b/man/mlr_pipeops_nn_max_pool3d.Rd @@ -103,6 +103,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_merge.Rd b/man/mlr_pipeops_nn_merge.Rd index 897341b7..06629f1a 100644 --- a/man/mlr_pipeops_nn_merge.Rd +++ b/man/mlr_pipeops_nn_merge.Rd @@ -85,6 +85,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_merge_cat.Rd b/man/mlr_pipeops_nn_merge_cat.Rd index a4f47b38..8f8edc87 100644 --- a/man/mlr_pipeops_nn_merge_cat.Rd +++ b/man/mlr_pipeops_nn_merge_cat.Rd @@ -99,6 +99,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_merge_prod.Rd b/man/mlr_pipeops_nn_merge_prod.Rd index 5620dfe1..9a8aa49b 100644 --- a/man/mlr_pipeops_nn_merge_prod.Rd +++ b/man/mlr_pipeops_nn_merge_prod.Rd @@ -95,6 +95,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_merge_sum.Rd b/man/mlr_pipeops_nn_merge_sum.Rd index cd440eb1..41a4244f 100644 --- a/man/mlr_pipeops_nn_merge_sum.Rd +++ b/man/mlr_pipeops_nn_merge_sum.Rd @@ -95,6 +95,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, @@ -151,6 +152,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_prelu.Rd b/man/mlr_pipeops_nn_prelu.Rd index 07b3322a..0bc935cc 100644 --- a/man/mlr_pipeops_nn_prelu.Rd +++ b/man/mlr_pipeops_nn_prelu.Rd @@ -97,6 +97,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_relu.Rd b/man/mlr_pipeops_nn_relu.Rd index 4cb183ee..96fd8627 100644 --- a/man/mlr_pipeops_nn_relu.Rd +++ b/man/mlr_pipeops_nn_relu.Rd @@ -92,6 +92,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_relu6.Rd b/man/mlr_pipeops_nn_relu6.Rd index e7d09288..ba4c765e 100644 --- a/man/mlr_pipeops_nn_relu6.Rd +++ b/man/mlr_pipeops_nn_relu6.Rd @@ -92,6 +92,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_reshape.Rd b/man/mlr_pipeops_nn_reshape.Rd index 5e1133f1..7b69db1b 100644 --- a/man/mlr_pipeops_nn_reshape.Rd +++ b/man/mlr_pipeops_nn_reshape.Rd @@ -94,6 +94,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_rrelu.Rd b/man/mlr_pipeops_nn_rrelu.Rd index 7b9ce398..e746fed9 100644 --- a/man/mlr_pipeops_nn_rrelu.Rd +++ b/man/mlr_pipeops_nn_rrelu.Rd @@ -96,6 +96,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_selu.Rd b/man/mlr_pipeops_nn_selu.Rd index d818ea82..1f7365da 100644 --- a/man/mlr_pipeops_nn_selu.Rd +++ b/man/mlr_pipeops_nn_selu.Rd @@ -95,6 +95,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_sigmoid.Rd b/man/mlr_pipeops_nn_sigmoid.Rd index 7227cb16..735eef01 100644 --- a/man/mlr_pipeops_nn_sigmoid.Rd +++ b/man/mlr_pipeops_nn_sigmoid.Rd @@ -89,6 +89,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_softmax.Rd b/man/mlr_pipeops_nn_softmax.Rd index b9c143c6..9e3ba8fd 100644 --- a/man/mlr_pipeops_nn_softmax.Rd +++ b/man/mlr_pipeops_nn_softmax.Rd @@ -93,6 +93,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_softplus.Rd b/man/mlr_pipeops_nn_softplus.Rd index b709cec5..a486be90 100644 --- a/man/mlr_pipeops_nn_softplus.Rd +++ b/man/mlr_pipeops_nn_softplus.Rd @@ -94,6 +94,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_softshrink.Rd b/man/mlr_pipeops_nn_softshrink.Rd index 204ccb7e..8385d8be 100644 --- a/man/mlr_pipeops_nn_softshrink.Rd +++ b/man/mlr_pipeops_nn_softshrink.Rd @@ -92,6 +92,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_softsign.Rd b/man/mlr_pipeops_nn_softsign.Rd index 5d8bd176..ee2a75e2 100644 --- a/man/mlr_pipeops_nn_softsign.Rd +++ b/man/mlr_pipeops_nn_softsign.Rd @@ -89,6 +89,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_squeeze.Rd b/man/mlr_pipeops_nn_squeeze.Rd index b96a6937..27e9cf9d 100644 --- a/man/mlr_pipeops_nn_squeeze.Rd +++ b/man/mlr_pipeops_nn_squeeze.Rd @@ -120,6 +120,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, @@ -176,6 +177,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_tanh.Rd b/man/mlr_pipeops_nn_tanh.Rd index 6fb87b0d..297cc8ac 100644 --- a/man/mlr_pipeops_nn_tanh.Rd +++ b/man/mlr_pipeops_nn_tanh.Rd @@ -89,6 +89,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_tanhshrink.Rd b/man/mlr_pipeops_nn_tanhshrink.Rd index 7211bc92..74e5766e 100644 --- a/man/mlr_pipeops_nn_tanhshrink.Rd +++ b/man/mlr_pipeops_nn_tanhshrink.Rd @@ -89,6 +89,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_nn_threshold.Rd b/man/mlr_pipeops_nn_threshold.Rd index a40378dc..c2eb8741 100644 --- a/man/mlr_pipeops_nn_threshold.Rd +++ b/man/mlr_pipeops_nn_threshold.Rd @@ -96,6 +96,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_torch.Rd b/man/mlr_pipeops_torch.Rd index 7a938eb4..a56184d5 100644 --- a/man/mlr_pipeops_torch.Rd +++ b/man/mlr_pipeops_torch.Rd @@ -238,6 +238,7 @@ Other Graph Network: \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_img}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{model_descriptor_to_learner}()}, diff --git a/man/mlr_pipeops_torch_ingress.Rd b/man/mlr_pipeops_torch_ingress.Rd index 33a6c2b9..800061a9 100644 --- a/man/mlr_pipeops_torch_ingress.Rd +++ b/man/mlr_pipeops_torch_ingress.Rd @@ -83,6 +83,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_loss}}, \code{\link{mlr_pipeops_torch_model_classif}}, @@ -96,6 +97,7 @@ Other Graph Network: \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_img}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch}}, \code{\link{model_descriptor_to_learner}()}, diff --git a/man/mlr_pipeops_torch_ingress_categ.Rd b/man/mlr_pipeops_torch_ingress_categ.Rd index cd012d5e..5abeb625 100644 --- a/man/mlr_pipeops_torch_ingress_categ.Rd +++ b/man/mlr_pipeops_torch_ingress_categ.Rd @@ -91,6 +91,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, @@ -104,6 +105,7 @@ Other Graph Network: \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_img}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch}}, diff --git a/man/mlr_pipeops_torch_ingress_img.Rd b/man/mlr_pipeops_torch_ingress_img.Rd index 033d56e2..13f9cd7e 100644 --- a/man/mlr_pipeops_torch_ingress_img.Rd +++ b/man/mlr_pipeops_torch_ingress_img.Rd @@ -56,6 +56,7 @@ Other Graph Network: \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch}}, diff --git a/man/mlr_pipeops_torch_ingress_ltnsr.Rd b/man/mlr_pipeops_torch_ingress_ltnsr.Rd new file mode 100644 index 00000000..d8d471e7 --- /dev/null +++ b/man/mlr_pipeops_torch_ingress_ltnsr.Rd @@ -0,0 +1,169 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchIngress.R +\name{mlr_pipeops_torch_ingress_ltnsr} +\alias{mlr_pipeops_torch_ingress_ltnsr} +\alias{PipeOpTorchIngressLazyTensor} +\title{Ingress for Lazy Tensor} +\description{ +Ingress for \code{\link{lazy_tensor}} column. +This ingress might not return the #' @inheritSection mlr_pipeops_torch_ingress Input and Output Channels +} +\section{Parameters}{ + +No parameters. +} + +\section{Internals}{ + +The output of the created batchgetter merely returns the data as is. +The dataset is then responsible to materialize the tensors. +By doing so, the data-loading can be made more efficient, e.g. when two different ingress tokens exist +for lazy tensors columns that share the same dataset. +} + +\section{State}{ + +The state is set to the input shape. +} + +\examples{ +TODO: +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}}, +\code{\link{mlr_pipeops_torch_model}} + +Other Graph Network: +\code{\link{ModelDescriptor}()}, +\code{\link{TorchIngressToken}()}, +\code{\link{mlr_learners_torch_model}}, +\code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_img}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{model_descriptor_to_learner}()}, +\code{\link{model_descriptor_to_module}()}, +\code{\link{model_descriptor_union}()}, +\code{\link{nn_graph}()} +} +\concept{Graph Network} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorchIngress]{mlr3torch::PipeOpTorchIngress}} -> \code{PipeOpTorchIngressLazyTensor} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchIngressLazyTensor-new}{\code{PipeOpTorchIngressLazyTensor$new()}} +\item \href{#method-PipeOpTorchIngressLazyTensor-clone}{\code{PipeOpTorchIngressLazyTensor$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchIngressLazyTensor-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchIngressLazyTensor$new( + id = "torch_ingress_ltnsr", + param_vals = list() +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchIngressLazyTensor-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchIngressLazyTensor$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_torch_ingress_num.Rd b/man/mlr_pipeops_torch_ingress_num.Rd index e677e88e..f3691f3d 100644 --- a/man/mlr_pipeops_torch_ingress_num.Rd +++ b/man/mlr_pipeops_torch_ingress_num.Rd @@ -40,6 +40,7 @@ Other Graph Network: \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_img}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch}}, \code{\link{model_descriptor_to_learner}()}, @@ -97,6 +98,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, \code{\link{mlr_pipeops_torch_model_classif}}, diff --git a/man/mlr_pipeops_torch_loss.Rd b/man/mlr_pipeops_torch_loss.Rd index e1e04bbe..174f68e9 100644 --- a/man/mlr_pipeops_torch_loss.Rd +++ b/man/mlr_pipeops_torch_loss.Rd @@ -87,6 +87,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_model_classif}}, diff --git a/man/mlr_pipeops_torch_model.Rd b/man/mlr_pipeops_torch_model.Rd index db642859..3978d5cc 100644 --- a/man/mlr_pipeops_torch_model.Rd +++ b/man/mlr_pipeops_torch_model.Rd @@ -111,6 +111,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_torch_model_classif.Rd b/man/mlr_pipeops_torch_model_classif.Rd index b3ba6ef3..79da502b 100644 --- a/man/mlr_pipeops_torch_model_classif.Rd +++ b/man/mlr_pipeops_torch_model_classif.Rd @@ -98,6 +98,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_pipeops_torch_model_regr.Rd b/man/mlr_pipeops_torch_model_regr.Rd index 632bf092..e19cd20c 100644 --- a/man/mlr_pipeops_torch_model_regr.Rd +++ b/man/mlr_pipeops_torch_model_regr.Rd @@ -98,6 +98,7 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, diff --git a/man/mlr_tasks_mnist.Rd b/man/mlr_tasks_mnist.Rd new file mode 100644 index 00000000..53c4c4a2 --- /dev/null +++ b/man/mlr_tasks_mnist.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TaskClassif_mnist.R +\name{mlr_tasks_mnist} +\alias{mlr_tasks_mnist} +\title{MNIST Image classification} +\description{ +Classical MNIST image classification + +The underlying \code{\link{DataBackend}} contains columns \code{"label"}, \code{"image"}, \code{"row_id"}, \code{"split"}, where the last column +indicates whether the row belongs to the train or test set. + +The first 60000 rows belong to the training set, the last 10000 rows to the test set. +} +\section{Construction}{ + + +\if{html}{\out{
}}\preformatted{tsk("mnist") +}\if{html}{\out{
}} +} + +\section{Meta Information}{ + +\itemize{ +\item Task type: \dQuote{classif} +\item Properties: \dQuote{multiclass} +\item Has Missings: no +\item Target: \dQuote{label} +\item Features: \dQuote{image} +\item Backend Dimension: 70000x4 +\item Default Roles (use / test / holdout): 60000, 10000, 0 +} +} + +\references{ +Lecun, Y., Bottou, L., Bengio, Y., Haffner, P. (1998). +\dQuote{Gradient-based learning applied to document recognition.} +\emph{Proceedings of the IEEE}, \bold{86}(11), 2278-2324. +\doi{10.1109/5.726791}. +} diff --git a/man/model_descriptor_to_learner.Rd b/man/model_descriptor_to_learner.Rd index 30224fcc..5a3b0103 100644 --- a/man/model_descriptor_to_learner.Rd +++ b/man/model_descriptor_to_learner.Rd @@ -26,6 +26,7 @@ Other Graph Network: \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_img}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch}}, diff --git a/man/model_descriptor_to_module.Rd b/man/model_descriptor_to_module.Rd index 59f0c719..35920f30 100644 --- a/man/model_descriptor_to_module.Rd +++ b/man/model_descriptor_to_module.Rd @@ -37,6 +37,7 @@ Other Graph Network: \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_img}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch}}, diff --git a/man/model_descriptor_union.Rd b/man/model_descriptor_union.Rd index 2fd5d2a6..bfb1e4fd 100644 --- a/man/model_descriptor_union.Rd +++ b/man/model_descriptor_union.Rd @@ -43,6 +43,7 @@ Other Graph Network: \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_img}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch}}, diff --git a/man/nn_graph.Rd b/man/nn_graph.Rd index 46e8b84e..c8f53c8f 100644 --- a/man/nn_graph.Rd +++ b/man/nn_graph.Rd @@ -42,6 +42,7 @@ Other Graph Network: \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_img}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch}}, diff --git a/tests/testthat/assets/nano_mnist/data.rds b/tests/testthat/assets/nano_mnist/data.rds new file mode 100644 index 0000000000000000000000000000000000000000..f2b51d059403d8c92c061322844d483375ee0547 GIT binary patch literal 3021 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 PnvVYgHZbyZ=z9PF8e34M literal 0 HcmV?d00001 diff --git a/tests/testthat/helper_functions.R b/tests/testthat/helper_functions.R index f2348400..46efa9ab 100644 --- a/tests/testthat/helper_functions.R +++ b/tests/testthat/helper_functions.R @@ -242,3 +242,15 @@ expect_graph = function(g, n_nodes = NULL, n_edges = NULL) { expect_flag(g$is_trained) } + +random_dataset = dataset("random_dataset", + initialize = function(..., n = 10) { + self$x = torch_randn(n, ...) + }, + .getitem = function(i) { + list(x = self$x[i, ..]) + }, + .length = function() { + nrow(self$x) + } +) diff --git a/tests/testthat/helper_tasks.R b/tests/testthat/helper_tasks.R index 379f0b0d..0507c9d0 100644 --- a/tests/testthat/helper_tasks.R +++ b/tests/testthat/helper_tasks.R @@ -27,16 +27,37 @@ nano_dogs_vs_cats = function(id = "nano_dogs_vs_cats") { nano_mnist = function(id = "nano_mnist") { assert_string(id) path = testthat::test_path("assets", "nano_mnist") - image_names = list.files(path) - uris = normalizePath(file.path(path, image_names)) + data = readRDS(file.path(path, "data.rds")) - images = imageuri(uris) + ds = dataset( + initialize = function(images) { + self$images = torch_tensor(images, dtype = torch_float32()) + }, + .getbatch = function(idx) { + list(image = self$images[idx, , , drop = FALSE]) + }, + .length = function() dim(self$images)[1L] + )(data$image) + + data_descriptor = DataDescriptor(dataset = ds, list(image = c(NA, 1, 28, 28))) + + dt = data.table( + image = lazy_tensor(data_descriptor), + label = droplevels(data$label), + row_id = seq_along(data$label) + ) + + backend = DataBackendDataTable$new(data = dt, primary_key = "row_id") - labels = map_chr(image_names, function(name) {strsplit(name, split = "")[[1L]][1L]}) + task = TaskClassif$new( + backend = backend, + id = "nano_mnisst", + target = "label", + label = "MNIST Nano" + ) - dat = data.table(x = images, letter = labels) + task$col_roles$feature = "image" - task = as_task_classif(dat, id = "nano_mnist", label = "Letter Classification", target = "letter") task } diff --git a/tests/testthat/test_DataDescriptor.R b/tests/testthat/test_DataDescriptor.R new file mode 100644 index 00000000..a1757e80 --- /dev/null +++ b/tests/testthat/test_DataDescriptor.R @@ -0,0 +1,32 @@ +test_that("DataDescriptor works", { + ds = dataset( + initialize = function() { + self$x = torch_randn(10, 5, 3) + }, + .getitem = function(i) { + list(x = self$x[i, ..]) + }, + .length = function() { + nrow(self$x) + } + )() + + dd = DataDescriptor(ds, dataset_shapes = list(x = c(NA, 5, 3))) + expect_class(dd, "DataDescriptor") + expect_equal(dd$.pointer_shape, c(NA, 5, 3)) + expect_class(dd$graph$pipeops[[1L]], "PipeOpNOP") + expect_true(length(dd$graph$pipeops) == 1L) + expect_equal(dd$.pointer, c(dd$graph$output$op.id, dd$graph$output$channel.name)) + expect_string(dd$.dataset_hash) + expect_string(dd$.hash) + expect_false(dd$.dataset_hash == dd$.hash) + + dd1 = DataDescriptor(ds, dataset_shapes = list(x = c(NA, 5, 3))) + expect_equal(dd$dataset_shapes, dd1$dataset_shapes) + + expect_error(DataDescriptor(ds), "missing") + + graph = as_graph(po("nop", id = "nop")) + + expect_error(DataDescriptor(ds, dataset_shapes = list(x = c(5, 4)), "When passing a graph")) +}) diff --git a/tests/testthat/test_ModelDescriptor.R b/tests/testthat/test_ModelDescriptor.R index 3bc04891..76368145 100644 --- a/tests/testthat/test_ModelDescriptor.R +++ b/tests/testthat/test_ModelDescriptor.R @@ -196,7 +196,7 @@ test_that("model_descriptor_union basic checks", { expect_identical(observed_edges, expected_edges) }) -test_that("model_desriptor_union verifies input correctly", { +test_that("model_descriptor_union verifies input correctly", { expect_error(model_descriptor_union(list(), list()), regexp = "Must inherit from class") task = tsk("iris") diff --git a/tests/testthat/test_PipeOpTorchIngress.R b/tests/testthat/test_PipeOpTorchIngress.R index 799d688e..323dc56a 100644 --- a/tests/testthat/test_PipeOpTorchIngress.R +++ b/tests/testthat/test_PipeOpTorchIngress.R @@ -21,3 +21,26 @@ test_that("PipeOpTorchIngressImage", { task = nano_imagenet()$cbind(data.frame(x1 = 1:10)) expect_po_ingress(po_ingress, task) }) + +test_that("PipeOpTorchIngressLazyTensor", { + task = nano_mnist() + po_ingress = po("torch_ingress_ltnsr") + + output = po_ingress$train(list(task))[[1L]] + ds = task_dataset(task, output$ingress, device = "cpu") + + batch = ds$.getbatch(1:2) + expect_permutation(names(batch), c("x", "y", ".index")) + expect_equal(names(batch$x), "torch_ingress_ltnsr.input") + expect_class(batch$x[[1L]], "torch_tensor") + expect_true(batch$x$torch_ingress_ltnsr.input$dtype == torch_float()) + expect_true(batch$x$torch_ingress_ltnsr.input$device == torch_device("cpu")) + expect_equal(batch$x$torch_ingress_ltnsr.input$shape, c(2, 1, 28, 28)) + + ds_meta = task_dataset(task, output$ingress, device = "meta") + batch_meta = ds_meta$.getbatch(2:3) + expect_true(batch_meta$x$torch_ingress_ltnsr.input$device == torch_device("meta")) + + task$cbind(data.frame(row_id = 1:10, x_num = 1:10)) + expect_po_ingress(po_ingress, task) +}) diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R new file mode 100644 index 00000000..c1bfee56 --- /dev/null +++ b/tests/testthat/test_lazy_tensor.R @@ -0,0 +1,20 @@ +test_that("lazy_tensor works", { + dd1 = DataDescriptor(random_dataset(5, 4), list(x = c(NA, 5, 4))) + dd2 = DataDescriptor(random_dataset(5, 4), list(x = c(NA, 5, 4))) + + lt = lazy_tensor() + expect_class(lt, "lazy_tensor") + expect_true(length(lt) == 0L) + expect_true(is.null(attr(lt, "data_descriptor"))) + + lt1 = lazy_tensor(dd1) + lt2 = lazy_tensor(dd2) + + expect_error(c(lt1, lt2), "attributes are incompatible") + + lt1_empty = lt1[integer(0)] + expect_true(is.null(attr(lt1_empty, "data_descriptor"))) + expect_class(lt1_empty, "lazy_tensor") + + lt1_empty[1] = lt1[1] +}) diff --git a/tests/testthat/test_materialize.R b/tests/testthat/test_materialize.R new file mode 100644 index 00000000..dfe90868 --- /dev/null +++ b/tests/testthat/test_materialize.R @@ -0,0 +1,25 @@ +test_that("materialize works on lazy_tensor", { + ds = random_dataset(5, 4, n = 10) + lt = as_lazy_tensor(ds, list(x = c(NA, 5, 4))) + + output = materialize(lt, device = "cpu") + expect_class(output, "torch_tensor") + expect_equal(output$shape, c(10, 5, 4)) + expect_true(output$device == torch_device("cpu")) + expect_true(torch_equal(output, ds$x)) + + output_meta = materialize(lt, device = "meta") + expect_true(output_meta$device == torch_device("meta")) +}) + +test_that("materialize works", { + df = nano_mnist()$data(1:10, cols = "image") + + out = materialize(df) + expect_list(out) + expect_equal(names(out), "image") + expect_class(out, "torch_tensor") + expect_equal(out$shape, "torch_tensor") +}) + + From a1a997c3665da94a2133f95e14ff8912ff787369 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Thu, 12 Oct 2023 09:18:13 +0200 Subject: [PATCH 02/90] materialization starts working --- NAMESPACE | 1 + R/lazy_tensor.R | 22 +++- R/materialize.R | 161 ++++++++++++++++-------------- man/materialize.Rd | 32 +++++- tests/testthat/test_materialize.R | 14 ++- 5 files changed, 146 insertions(+), 84 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 76314d6b..0a19ef53 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -12,6 +12,7 @@ S3method(as_imageuri,character) S3method(as_imageuri,imageuri) S3method(as_lazy_tensor,DataDescriptor) S3method(as_lazy_tensor,dataset) +S3method(as_lazy_tensor,torch_tensor) S3method(as_torch_callback,R6ClassGenerator) S3method(as_torch_callback,TorchCallback) S3method(as_torch_callback,character) diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index aaac28b8..a12077ff 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -49,16 +49,32 @@ as_lazy_tensor = function(x, ...) { } #' @export -as_lazy_tensor.DataDescriptor = function(x, ids = NULL) { - lazy_tensor(data_descriptor, ids = ids) +as_lazy_tensor.DataDescriptor = function(x, ids = NULL) { # nolint + lazy_tensor(x, ids = ids) } #' @export -as_lazy_tensor.dataset = function(x, dataset_shapes, ids = NULL, ...) { +as_lazy_tensor.dataset = function(x, dataset_shapes, ids = NULL, ...) { # nolint dd = DataDescriptor(dataset = x, dataset_shapes = dataset_shapes, ...) lazy_tensor(dd, ids) } +#' @export +as_lazy_tensor.torch_tensor = function(x) { # nolint + ds = dataset( + initialize = function(x) { + self$x = x + }, + .getbatch = function(ids) { + list(x = self$x[ids, .., drop = FALSE]) # nolint + }, + .length = function(ids) { + dim(self$x)[1L] + } + )(x) + as_lazy_tensor(ds, dataset_shapes = list(x = c(NA, dim(x)))) +} + #' @export vec_ptype_abbr.lazy_tensor <- function(x, ...) { # nolint diff --git a/R/materialize.R b/R/materialize.R index 087dc0cc..72cdb0f3 100644 --- a/R/materialize.R +++ b/R/materialize.R @@ -1,36 +1,57 @@ #' @title Materialize Lazy Tensor Columns #' @description -#' This will materialize all columns from a `data.frame` containing [`lazy_tensor()`] columns. +#' This will materialize a [`lazy_tensor()`] or a [`data.frame()`] / [`list()`] containing -- among other things -- +#' [`lazy_tensor()`] columns. +#' I.e. the data described in the underlying [`DataDescriptors`] is loaded for the indices in the [`lazy_tensor()`] +#' and is afterwards put on the specified device. +#' #' @details -#' Caching is applied to ensure that each batch from the datasets wrapped by the lazy tensors is only loaded once. -#' It is also ensured that each graph is only applied once to a given input batch, i.e. different columns -#' can share the same graph, dataset and indices but point to different outputs. +#' Materializing a lazy tensor consists of: +#' 1. Loading the data from the internal dataset of the [`DataDescriptor`]. +#' 2. Processing these batches in the preprocessing [`Graph`]s. +#' 3. Returning the result of the [`PipeOp`] pointed to by the [`DataDescriptor`] (`.pointer`). +#' +#' With multiple [`lazy_tensor`] columns we can benefit from caching because: +#' a) Output(s) from the dataset might be input to multiple graphs. +#' b) Different lazy tensors might be outputs from the same graph. +#' +#' For this reason it is possible to provide a cache environment. +#' The hash key for a) is the hash of the indices and the dataset. +#' The hash key for b) is the hash of the indices dataset and preprocessing graph. +#' @return ([`torch_tensor()`] or [`list()`]) #' @export +#' @examples +#' lt1 = as_lazy_tensor(torch_randn(10, 3)) +#' materialize(lt1) +#' lt2 = as_lazy_tensor(torch_randn(10, 4)) +#' d = data.frame(lt1 = lt1, lt2 = lt2) +#' materialize(d) materialize = function(x, device = "cpu", ...) { + assert_choice(device, mlr_reflections$torch$devices) UseMethod("materialize") } #' @export -materialize.list = function(x, device = "cpu") { - input_cache = new.env() # nolint - output_cache = new.env() # nolint +#' @return (`list()`) +materialize.list = function(x, device = "cpu") { # nolint + cache = if (sum(map_lgl(x, is_lazy_tensor)) > 1L) { + new.env() + } keep_results_prev = list() walk(x, function(col) { - keep+ if (is_lazy_tensor(col)) { + graph = attr(col, "data_descriptor")$graph keep_results_prev[[graph$hash]] = graph$keep_results - attr(col, "data_descriptor")$graph$keep_results = character() - + graph$keep_results = character() } }) # clean up the keep_results after - on.exit({walk(x, function(col) { + on.exit({walk(x, function(col) { # nolint if (is_lazy_tensor(x)) { graph = attr(x, "data_descriptor")$graph graph$keep_results = keep_results_prev[[graph$hash]] } - })}, add = TRUE) walk(x, function(col) { @@ -42,77 +63,78 @@ materialize.list = function(x, device = "cpu") { # TODO: No hashing when there is only one column map(x, function(col) { - if (!is_lazy_tensor(col)) { - return(col) - } - data_descriptor = attr(col, "data_descriptor") - dataset_hash = data_descriptor$.dataset_hash - - ds = data_descriptor$dataset - - ids = vec_data(col) - - input_hash = calculate_hash(dataset_hash, ids) - - if (!exists(input_hash, input_cache, inherits = FALSE)) { - input = if (is.null(ds$.getbatch)) { # .getindex is never NULL but a function that errs if it was not defined - torch_cat(map(ids, function(id) ds$.getitem(id)), dim = 1L) - } else { - ds$.getbatch(ids) - } - - input_cache[[input_hash]] = input - } else { - input = input_cache[[input_hash]] - } - - input = set_names(input[data_descriptor$.input_map], data_descriptor$graph$.graph_input) - - output_hash = calculate_hash(ids, data_descriptor$.hash) - - if (!exists(output_hash, output_cache, inherits = FALSE)) { - data_descriptor$graph$train(input, single_input = FALSE) - output = map(data_descriptor$graph$pipeops[data_descriptor$graph$keep_results], ".result") - output_cache[[output_hash]] = output + if (is_lazy_tensor(col)) { + materialize_internal(col, device = device, cache = cache, set_keep_results = FALSE) } else { - output = output_cache[[output_hash]] + col } - # FIXME: This will fail when the .pointer is not an output of the graph - # https://github.com/mlr-org/mlr3torch/issues/138 - - output[[data_descriptor$.pointer[1L]]][[data_descriptor$.pointer[2L]]]$to(device = device) }) } + #' @export -materialize.lazy_tensor = function(x, device = "cpu", cache = NULL) { +#' @return ([`torch_tensor()`]) +materialize.lazy_tensor = function(x, device = "cpu") { # nolint + materialize_internal(x = x, device = device, cache = NULL, set_keep_results = TRUE) +} + +#' @title Materialize a Lazy Tensor +#' @description +#' Materializing a lazy tensor consists of: +#' 1. Loading the data from the internal dataset of the [`DataDescriptor`]. +#' 2. Processing these batches in the preprocessing [`Graph`]s. +#' 3. Returning the result of the [`PipeOp`] pointed to by the [`DataDescriptor`] (`.pointer`). +#' +#' With multiple [`lazy_tensor`] columns we can benefit from caching because: +#' a) Output(s) from the dataset might be input to multiple graphs. +#' b) Different lazy tensors might be outputs from the same graph. +#' +#' For this reason it is possible to provide a cache environment. +#' The hash key for a) is the hash of the indices and the dataset. +#' The hash key for b) is the hash of the indices dataset and preprocessing graph. +#' +#' @param x ([`lazy_tensor()`])\cr +#' The lazy tensor to materialize. +#' @param device (`character(1L)`)\cr +#' The device to put the materialized tensor on (after running the preprocessing graph). +#' @param cache (`NULL` or `environment()`)\cr +#' Whether to cache the (intermediate) results of the materialization. +#' This can make data loading faster when multiple `lazy_tensor`s reference the same dataset or graph. +#' @param set_keep_results (`logical(1)`)\cr +#' In some cases, the `.pointer` of a [`DataDescriptor`] might point to a non-terminal node in which case the +#' this result is not part of the output of the [`Graph`]. +#' Therefore we have to include this as part of the `keep_results` field of the [`Graph`]. +#' When caching is done, this should be set to `FALSE` as otherwise data will be discarded that might be relevant +#' for materializing other lazy tensor columns. +#' @return [`lazy_tensor()`] +#' @noRd +materialize_internal = function(x, device = "cpu", cache = NULL, set_keep_results = is.null(cache)) { do_caching = !is.null(cache) ids = vec_data(x) data_descriptor = attr(x, "data_descriptor") ds = data_descriptor$dataset graph = data_descriptor$graph - prev_results = graph$keep_results - on.exit({graph$keep_results = prev_results}, add = TRUE) - if (test_flag(prev_results)) { + + if (set_keep_results) { + prev_results = graph$keep_results + on.exit({graph$keep_results = prev_results}, add = TRUE) # nolint graph$keep_results = data_descriptor$.pointer[1L] - } else { - graph$keep_results = union(prev_results, data_descriptor$.pointer[1L]) } if (do_caching) { output_hash = calculate_hash(ids, data_descriptor$.hash) - output_hit = exists(output_hash, cache$output, inherits = FALSE) + output_hit = exists(output_hash, cache, inherits = FALSE) if (output_hit) { - return(cache$output[[output_hash]][[data_descriptor$.pointer]]) + return(cache[[output_hash]][[data_descriptor$.pointer]]) } - input_hash = calculate_hash(dataset_hash, ids) - input_hit = exists(input_hash, cache$input, inherits = FALSE) + input_hash = calculate_hash(data_descriptor$.dataset_hash, ids) + input_hit = exists(input_hash, cache, inherits = FALSE) if (input_hit) { - input = cache$input[[input_hash]] + input = cache[[input_hash]] input_hit = TRUE } } @@ -127,7 +149,7 @@ materialize.lazy_tensor = function(x, device = "cpu", cache = NULL) { } if (do_caching && !input_hit) { - cache$input[[input_hash]] = input + cache[[input_hash]] = input } # input is the output of a dataset so it can contain more than what we need for the graph, @@ -135,7 +157,6 @@ materialize.lazy_tensor = function(x, device = "cpu", cache = NULL) { # This is done after retrieving the element from the cache / before saving the element to the cache because # this can change - browser() input = set_names(input[data_descriptor$.input_map], data_descriptor$.graph_input) graph$train(input, single_input = FALSE) @@ -143,25 +164,17 @@ materialize.lazy_tensor = function(x, device = "cpu", cache = NULL) { output = set_names(output, data_descriptor$graph$keep_results) if (do_caching) { - cache$output[[output_hash]] = output + cache[[output_hash]] = output } # discard the results walk(data_descriptor$graph$pipeops[data_descriptor$graph$keep_results], function(x) x$.result = NULL) - output = output[[data_descriptor$.pointer[1L]]][[data_descriptor$.pointer[2L]]]$to(device = device) + output[[data_descriptor$.pointer[1L]]][[data_descriptor$.pointer[2L]]]$to(device = device) } #' @method materialize data.frame #' @export -materialize.data.frame = materialize.list - - -batchgetter_lazy_tensor = function(data, device, cache = NULL) { - if (is.null(cache)) { - materialize(data[[1L]])[[1L]] - - - } -} +#' @return ([`list()`]) +materialize.data.frame = materialize.list # nolint diff --git a/man/materialize.Rd b/man/materialize.Rd index 77a2a75f..08184574 100644 --- a/man/materialize.Rd +++ b/man/materialize.Rd @@ -6,11 +6,35 @@ \usage{ materialize(x, device = "cpu", ...) } +\value{ +(\code{\link[=torch_tensor]{torch_tensor()}} or \code{\link[=list]{list()}}) +} \description{ -This will materialize all columns from a \code{data.frame} containing \code{\link[=lazy_tensor]{lazy_tensor()}} columns. +This will materialize a \code{\link[=lazy_tensor]{lazy_tensor()}} or a \code{\link[=data.frame]{data.frame()}} / \code{\link[=list]{list()}} containing -- among other things -- +\code{\link[=lazy_tensor]{lazy_tensor()}} columns. +I.e. the data described in the underlying \code{\link{DataDescriptors}} is loaded for the indices in the \code{\link[=lazy_tensor]{lazy_tensor()}} +and is afterwards put on the specified device. } \details{ -Caching is applied to ensure that each batch from the datasets wrapped by the lazy tensors is only loaded once. -It is also ensured that each graph is only applied once to a given input batch, i.e. different columns -can share the same graph, dataset and indices but point to different outputs. +Materializing a lazy tensor consists of: +\enumerate{ +\item Loading the data from the internal dataset of the \code{\link{DataDescriptor}}. +\item Processing these batches in the preprocessing \code{\link{Graph}}s. +\item Returning the result of the \code{\link{PipeOp}} pointed to by the \code{\link{DataDescriptor}} (\code{.pointer}). +} + +With multiple \code{\link{lazy_tensor}} columns we can benefit from caching because: +a) Output(s) from the dataset might be input to multiple graphs. +b) Different lazy tensors might be outputs from the same graph. + +For this reason it is possible to provide a cache environment. +The hash key for a) is the hash of the indices and the dataset. +The hash key for b) is the hash of the indices dataset and preprocessing graph. +} +\examples{ +lt1 = as_lazy_tensor(torch_randn(10, 3)) +materialize(lt1) +lt2 = as_lazy_tensor(torch_randn(10, 4)) +d = data.frame(lt1 = lt1, lt2 = lt2) +materialize(d) } diff --git a/tests/testthat/test_materialize.R b/tests/testthat/test_materialize.R index dfe90868..a5a8a656 100644 --- a/tests/testthat/test_materialize.R +++ b/tests/testthat/test_materialize.R @@ -12,14 +12,22 @@ test_that("materialize works on lazy_tensor", { expect_true(output_meta$device == torch_device("meta")) }) -test_that("materialize works", { +test_that("materialize works for data.frame", { df = nano_mnist()$data(1:10, cols = "image") out = materialize(df) expect_list(out) expect_equal(names(out), "image") - expect_class(out, "torch_tensor") - expect_equal(out$shape, "torch_tensor") + expect_class(out$image, "torch_tensor") + expect_equal(out$image$shape, c(10, 1, 28, 28)) +}) + +test_that("caching of datasets works", { + # TODO +}) + +test_that("caching of graphs works", { + # TODO }) From e5c5a324353369c068df67631299f2cb513a3db7 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Thu, 12 Oct 2023 17:34:56 +0200 Subject: [PATCH 03/90] progress on lazy tensor transform --- DESCRIPTION | 4 +- NAMESPACE | 2 + R/DataBackendLazy.R | 2 +- R/PipeOpModule.R | 5 +- R/PipeOpTorch.R | 18 +- R/PipeOpTorchIngress.R | 10 +- R/PipeOpTorchLazyTransform.R | 199 ++++++++++++++++++ R/TaskClassif_mnist.R | 6 +- R/TaskClassif_tiny_imagenet.R | 6 +- R/lazy_tensor.R | 42 ++++ R/merge_graphs.R | 44 ++++ R/task_dataset.R | 38 +++- R/utils.R | 4 + R/zzz.R | 20 ++ data-raw/mnist.R | 4 + inst/col_info/mnist.rds | Bin 274 -> 266 bytes inst/col_info/tiny_imagenet.rds | Bin 2790 -> 2781 bytes man/PipeOpTorchTransformResize.Rd | 68 ++++++ man/batchgetter_categ.Rd | 5 +- man/batchgetter_num.Rd | 5 +- man/merge_graphs.Rd | 11 + man/mlr_pipeops_torch.Rd | 3 +- man/mlr_pipeops_torch_lazy_transform.Rd | 120 +++++++++++ tests/testthat/helper_functions.R | 2 +- tests/testthat/helper_tasks.R | 10 +- tests/testthat/test_PipeOpTorchIngress.R | 12 ++ .../testthat/test_PipeOpTorchLazyTransform.R | 24 +++ tests/testthat/test_lazy_tensor.R | 47 +++++ tests/testthat/test_task_dataset.R | 13 ++ 29 files changed, 688 insertions(+), 36 deletions(-) create mode 100644 R/PipeOpTorchLazyTransform.R create mode 100644 R/merge_graphs.R create mode 100644 man/PipeOpTorchTransformResize.Rd create mode 100644 man/merge_graphs.Rd create mode 100644 man/mlr_pipeops_torch_lazy_transform.Rd create mode 100644 tests/testthat/test_PipeOpTorchLazyTransform.R diff --git a/DESCRIPTION b/DESCRIPTION index b2d23e66..497f4ae4 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -42,7 +42,7 @@ Imports: checkmate (>= 2.2.0), coro, lgr, - mlr3misc (>= 0.11.0), + mlr3misc (>= 0.13.0), methods, data.table, paradox (>= 0.11.0), @@ -103,6 +103,7 @@ Collate: 'PipeOpTorchHead.R' 'PipeOpTorchIngress.R' 'PipeOpTorchLayerNorm.R' + 'PipeOpTorchLazyTransform.R' 'PipeOpTorchLinear.R' 'TorchLoss.R' 'PipeOpTorchLoss.R' @@ -123,6 +124,7 @@ Collate: 'lazy_tensor.R' 'learner_torch_methods.R' 'materialize.R' + 'merge_graphs.R' 'nn_graph.R' 'paramset_torchlearner.R' 'rd_info.R' diff --git a/NAMESPACE b/NAMESPACE index 0a19ef53..9b0877e0 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -94,6 +94,7 @@ export(PipeOpTorchIngressImage) export(PipeOpTorchIngressLazyTensor) export(PipeOpTorchIngressNumeric) export(PipeOpTorchLayerNorm) +export(PipeOpTorchLazyTransform) export(PipeOpTorchLeakyReLU) export(PipeOpTorchLinear) export(PipeOpTorchLogSigmoid) @@ -124,6 +125,7 @@ export(PipeOpTorchSqueeze) export(PipeOpTorchTanh) export(PipeOpTorchTanhShrink) export(PipeOpTorchThreshold) +export(PipeOpTorchTransformResize) export(PipeOpTorchUnsqueeze) export(ResamplingRowRoles) export(TorchCallback) diff --git a/R/DataBackendLazy.R b/R/DataBackendLazy.R index 9612e564..9a156b80 100644 --- a/R/DataBackendLazy.R +++ b/R/DataBackendLazy.R @@ -220,7 +220,7 @@ DataBackendLazy = R6Class("DataBackendLazy", ), private = list( .calculate_hash = function() { - get_private(self$backend)$.calculate_hash() + suppressWarnings(get_private(self$backend)$.calculate_hash()) }, .constructor = NULL, .backend = NULL, diff --git a/R/PipeOpModule.R b/R/PipeOpModule.R index 5f41fa61..07f44859 100644 --- a/R/PipeOpModule.R +++ b/R/PipeOpModule.R @@ -125,7 +125,10 @@ PipeOpModule = R6Class("PipeOpModule", .predict = function(inputs) { rep(list(NULL), nrow(self$output)) }, - .multi_output = FALSE + .multi_output = FALSE, + .additional_phash_input = function() { + list(address(self$module), self$input$name, self$output$name, self$packages) + } ) ) diff --git a/R/PipeOpTorch.R b/R/PipeOpTorch.R index ee035846..bf05504d 100644 --- a/R/PipeOpTorch.R +++ b/R/PipeOpTorch.R @@ -249,22 +249,24 @@ PipeOpTorch = R6Class("PipeOpTorch", #' [`PipeOp`] during training must return a named `list()`, where the names of the list are the #' names out the output channels. The default is `"output"`. initialize = function(id, module_generator, param_set = ps(), param_vals = list(), - inname = "input", outname = "output", packages = "torch", tags = NULL) { + inname = "input", outname = "output", packages = "torch", tags = NULL, variant_types = FALSE) { self$module_generator = assert_class(module_generator, "nn_module_generator", null.ok = TRUE) assert_character(inname, .var.name = "input channel names") assert_character(outname, .var.name = "output channel names", min.len = 1L) assert_character(tags, null.ok = TRUE) assert_character(packages, any.missing = FALSE) - input = data.table(name = inname, train = "ModelDescriptor", predict = "Task") - output = data.table(name = outname, train = "ModelDescriptor", predict = "Task") + packages = union(packages, "torch") + data_type = if (variant_types) "*" else "ModelDescriptor" + input = data.table(name = inname, train = data_type, predict = "*") + output = data.table(name = outname, train = data_type, predict = "*") assert_r6(param_set, "ParamSet") - walk(param_set$params, function(p) { - if (!(("train" %in% p$tags) && !("predict" %in% p$tags))) { - stopf("Parameters of PipeOps inheriting from PipeOpTorch must only be active during training.") - } - }) + #walk(param_set$params, function(p) { + # if (!(("train" %in% p$tags) && !("predict" %in% p$tags))) { + # stopf("Parameters of PipeOps inheriting from PipeOpTorch must only be active during training.") + # } + #}) super$initialize( id = id, diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index 3b2b3b18..3444ff95 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -252,8 +252,6 @@ PipeOpTorchIngressCategorical = R6Class("PipeOpTorchIngressCategorical", c(NA, length(task$feature_names)) }, .get_batchgetter = function(task, param_vals) { - # Note that this function can only be called successfully if either select is TRUE or the task contains - # only factors and logicals. In both cases the formula below is correct batchgetter_categ } ) @@ -356,11 +354,13 @@ PipeOpTorchIngressLazyTensor = R6Class("PipeOpTorchIngressLazyTensor", attr(example, "data_descriptor")$.pointer_shape }, .get_batchgetter = function(task, param_vals) { - crate(function(data, device) { - data[[1L]] - }) + batchgetter_lazy_tensor } ) ) +batchgetter_lazy_tensor = function(data, device, cache) { + materialize_internal(x = data[[1L]], device = device, cache = cache) +} + register_po("torch_ingress_ltnsr", PipeOpTorchIngressLazyTensor) diff --git a/R/PipeOpTorchLazyTransform.R b/R/PipeOpTorchLazyTransform.R new file mode 100644 index 00000000..5c898aec --- /dev/null +++ b/R/PipeOpTorchLazyTransform.R @@ -0,0 +1,199 @@ +#' @title Base Class for Lazy Transformations +#' @name mlr_pipeops_torch_lazy_transform +#' +#' @description +#' This is the base class for lazy tensor transformations. +#' These can either be used as preprocessing for [`lazy_tensor`] objects or as part of the +#' graph contained in the [`ModelDescriptor`]. +#' Currently the `PipeOp` must have exactly one inut and one output. +#' +#' @section Inheriting: +#' You need to: +#' * Either provide a function as argument `fn` or overwrite the private `.make_module()` method. +#' See [`PipeOpTorch`] for how to do this. +#' * In case the transformation changes the tensor shapes you must provide a private `.shapes_out()` method like +#' for [`PipeOpTorch`]. It can be assumed that the first dimension is `NA`, i.e. the batch dimension. +#' +#' Depending on the data-loader, this function is either applied individually to each tensor from a batch and then +#' concatenated, or to the whole batch at once and should return the same result in both cases. +#' +#' @section Input and Output Channels: +#' During *training*, all inputs and outputs are of class [`Task`] or [`ModelDescriptor`]. +#' During *prediction*, all inputs and outputs are of class [`Task`] or [`ModelDescriptor`]. +#' +#' @template pipeop_torch_state_default +#' @section Parameters: +#' The [`ParamSet`][paradox::ParamSet] is specified by the child class inheriting from [`PipeOpTorchLazyTransform`]. +#' The name `augment` is reserved and must not be used. +#' +#' @template param_id +#' @template param_param_vals +#' @template param_param_set +#' @param packages (`character()`)\cr +#' The packages the function depends on. +#' If `fn` is from a namespace and no value is provided the namespace is automatically set. +#' @param fn (`function()`)\cr +#' A function that will be applied to a (lazy) tensor. +#' Additional arguments can be passed as parameters. +#' During actual preprocessing the (lazy) tensor will be passed by position. +#' +#' @export +PipeOpTorchLazyTransform = R6Class("PipeOpTorchLazyTransform", + inherit = PipeOpTorch, + public = list( + #' @description Creates a new instance of this [R6][R6::R6Class] class. + initialize = function(fn, id = "lazy_transform", param_vals = list(), param_set = ps(), packages = character(0)) { + private$.fn = assert_function(fn, null.ok = TRUE) + if (isNamespace(environment(fn)) && (length(packages) == 0)) { + packages = getNamespaceName(environment(fn)) + } + + param_set$add(ps( + augment = p_lgl(tags = c("train", "predict")) + )) + param_set$set_values(augment = FALSE) + + super$initialize( + id = id, + # TODO: Generalize this to arbitrary number of inputs and outputs + inname = "input", + outname = "output", + param_vals = param_vals, + param_set = param_set, + packages = packages, + module_generator = NULL, + variant_types = TRUE + ) + + } + ), + private = list( + .fn = NULL, + .make_module = function(shapes_in, param_vals, task) { + augment = param_vals$augment + param_vals$augment = NULL + trafo = private$.fn + fn = crate(function(x) { + invoke(.f = trafo, x, .args = param_vals) + }, param_vals, trafo, .parent = topenv()) + + if (augment) { + nn_module(self$id, + initialize = function(fn) { + self$fn = fn + }, + forward = function(x) { + if (self$training) { + self$fn(x) + } else { + x + } + } + )(fn) + } else { + nn_module(self$id, + initialize = function(fn) { + self$fn = fn + }, + forward = function(x) { + self$fn(x) + } + )(fn) + } + }, + .train = function(inputs) { + if (test_class(inputs[[1L]], "ModelDescriptor")) { + super$.train(inputs) + } else if (test_class(inputs[[1L]], "Task")) { + private$.transform_task(inputs) + } else { + stopf("Unsupported input type '%s'.", class(inputs)[[1L]]) + } + }, + .predict = function(inputs) { + if (test_class(inputs[[1L]], "ModelDescriptor")) { + super$.predict(inputs) + } else if (test_class(inputs[[1L]], "Task")) { + private$.transform_task(inputs) + } + }, + .transform_task = function(inputs) { + intask = inputs[[1L]]$clone(deep = TRUE) + + lazy_cols = intask$feature_types[get("type") == "lazy_tensor", "id"][[1L]] + if (length(lazy_cols) != 1L) { + stopf("Can only use PipeOpTorchLazyTransform on tasks with exactly one lazy tensor column.") + } + lt = intask$data(cols = lazy_cols)[[1L]] + + self$state = list(lazy_cols) + + shapes_in = attr(lt[[1L]], "data_descriptor")$.pointer_shape + + fn = private$.make_module(shapes_in = shapes_in, param_vals = self$param_set$values, task = intask) + + po_fn = PipeOpModule$new( + id = self$id, + module = fn, + inname = self$input$name, + outname = self$output$name, + packages = self$packages + ) + + shapes_out = self$shapes_out(shapes_in, intask) + lt_processed = transform_lazy_tensor(lt, po_fn, shapes_out[[1L]]) + new_col = set_names(data.table(lt_processed), lazy_cols) + + list(intask$select(setdiff(intask$feature_names, lazy_cols))$cbind(new_col)) + }, + .additional_phash_input = function() { + list(self$param_set$ids(), private$.fn, self$packages) + } + ) +) + +#' @include zzz.R +register_po("lazy_transform", PipeOpTorchLazyTransform) + + +#' @title Resize an Object +#' @description +#' See [`torchvision::transform_resize()`] for more information. +#' Creates a new instance of this [R6][R6::R6Class] class. +#' @template param_id +#' @template param_param_vals +#' @export +PipeOpTorchTransformResize = R6Class("PipeOpTOrchTransformResize", + inherit = PipeOpTorchLazyTransform, + public = list( + initialize = function(id = "transform_resize", param_vals = list()) { + param_set = ps( + size = p_uty(tags = c("train", "required")), + interpolation = p_fct(levels = magick::filter_types(), special_vals = list(0L, 2L, 3L), + tags = "train", default = 2L + ) + ) + super$initialize( + id = id, + packages = "torchvision", + param_set = param_set, + param_vals = param_vals, + fn = torchvision::transform_resize + ) + } + ), + private = list( + .shapes_out = function(shapes_in, param_vals, task) { + size = param_vals$size + shape = shapes_in[[1L]] + assert_true(length(shape) > 2) + height = shape[[length(shape) - 1L]] + width = shape[[length(shape)]] + s = torchvision::transform_resize(torch_ones(c(1, height, width), device = "meta"), size = size)$shape[2:3] + list(c(shape[seq_len(length(shape) - 2L)], s)) + } + ) +) + +#' @include zzz.R +register_po("transform_resize", PipeOpTorchTransformResize) diff --git a/R/TaskClassif_mnist.R b/R/TaskClassif_mnist.R index 9d8c1e44..b46ceac3 100644 --- a/R/TaskClassif_mnist.R +++ b/R/TaskClassif_mnist.R @@ -64,18 +64,18 @@ load_task_mnist = function(id = "mnist") { dt = data.table( image = lazy_tensor(data_descriptor), label = data$label, - row_id = seq_along(data$label), + ..row_id = seq_along(data$label), split = factor(c(rep("train", 60000), rep("test", 10000))) ) - DataBackendDataTable$new(data = dt, primary_key = "row_id") + DataBackendDataTable$new(data = dt, primary_key = "..row_id") } backend = DataBackendLazy$new( constructor = cached_constructor, rownames = seq_len(70000), col_info = load_col_info("mnist"), - primary_key = "row_id", + primary_key = "..row_id", data_formats = "data.table" ) diff --git a/R/TaskClassif_tiny_imagenet.R b/R/TaskClassif_tiny_imagenet.R index 04cb7f67..70ec51e8 100644 --- a/R/TaskClassif_tiny_imagenet.R +++ b/R/TaskClassif_tiny_imagenet.R @@ -83,15 +83,15 @@ load_task_tiny_imagenet = function(id = "tiny_imagenet") { dt = cached(constructor_tiny_imagenet, "datasets", "tiny_imagenet")$data }) dt$image = imageuri(dt$image) - dt$row_id = seq_len(nrow(dt)) - DataBackendDataTable$new(data = dt, primary_key = "row_id") + dt$..row_id = seq_len(nrow(dt)) + DataBackendDataTable$new(data = dt, primary_key = "..row_id") } backend = DataBackendLazy$new( constructor = cached_constructor, rownames = seq_len(120000), col_info = load_col_info("tiny_imagenet"), - primary_key = "row_id", + primary_key = "..row_id", data_formats = "data.table" ) diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index a12077ff..d733237a 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -100,3 +100,45 @@ is_lazy_tensor = function(x) { inherits(x, "lazy_tensor") } +#' @title Transform Lazy Tensor +#' @description +#' Input must be PipeOpModule with exactly one input and one output +#' shape must be shape with NA in first dimension +#' @param lt ([`lazy_tensor`])\cr +#' A lazy tensor vector. +#' @param pipeop ([`PipeOpModule`])\cr +#' The pipeop to be added to the preprocessing graph(s) of the lazy tensor. +#' Must have one input and one output. +#' @param shape (`integer()`)\cr +#' The shape of the lazy tensor (without the batch dimension). +#' @param clone_graph (`logical(1)`)\cr +#' Whether to clone the graph from the data descriptor. +#' @noRd +transform_lazy_tensor = function(lt, pipeop, shape, clone_graph = TRUE) { + assert_lazy_tensor(lt) + assert_class(pipeop, "PipeOpModule") + assert_true(nrow(pipeop$input) == 1L) + assert_true(nrow(pipeop$output) == 1L) + assert_shape(shape) + assert_flag(clone_graph) + + data_descriptor = attr(lt, "data_descriptor") + + if (clone_graph) { + data_descriptor$graph = data_descriptor$graph$clone(deep = TRUE) + } + + data_descriptor$graph$add_pipeop(pipeop$clone(deep = TRUE)) + data_descriptor$graph$add_edge( + src_id = data_descriptor$.pointer[1L], + src_channel = data_descriptor$.pointer[2L], + dst_id = pipeop$id, + dst_channel = pipeop$input$name + ) + + data_descriptor$.pointer = c(pipeop$id, pipeop$output$name) + data_descriptor$.pointer_shape = shape + data_descriptor = set_data_descriptor_hash(data_descriptor) + + new_lazy_tensor(data_descriptor, vec_data(lt)) +} diff --git a/R/merge_graphs.R b/R/merge_graphs.R new file mode 100644 index 00000000..19bf279a --- /dev/null +++ b/R/merge_graphs.R @@ -0,0 +1,44 @@ +#' note that this mo +merge_graphs = function(g1, g2, in_place = FALSE) { + if (in_place) { + graph = g1 + } else { + graph = g1$clone(deep = TRUE) + } + # if graphs are identical, we don't need to worry about copying stuff + if (!identical(g1, g2)) { + # PipeOps that have the same ID that occur in both graphs must be identical. + common_names = intersect(names(graph$pipeops), names(g2$pipeops)) + if (!identical(map(graph$pipeops[common_names], "hash"), map(g2$pipeops[common_names], "hash"))) { + not_identical = map_lgl(common_names, function(name) { + !identical(graph$pipeops[[name]]$hash, g2$pipeops[[name]]$hash) + }) + stopf("Both graphs have PipeOps with ID(s) %s but they don't have the same hashes.", + paste0("'", common_names[not_identical], "'", collapse = ", ") + ) + } + + # copy all PipeOps that are in g2 but not in g1 + graph$pipeops = c(graph$pipeops, g2$pipeops[setdiff(names(g2$pipeops), common_names)]) + + # clear param_set cache + graph$.__enclos_env__$private$.param_set = NULL + + # edges that are in md2's graph that were not in md1's graph + new_edges = g2$edges[!graph$edges, on = c("src_id", "src_channel", "dst_id", "dst_channel")] + + # IDs and channel names that get new input edges. These channels must not already have incoming edges in md1. + new_input_edges = unique(new_edges[, c("dst_id", "dst_channel"), with = FALSE]) + + forbidden_edges = graph$edges[new_input_edges, on = c("dst_id", "dst_channel"), nomatch = NULL] + + if (nrow(forbidden_edges)) { + stopf("PipeOp(s) %s have differing incoming edges in g1 and g2", + paste(forbidden_edges$dst_id, collapse = ", ")) + + } + graph$edges = rbind(graph$edges, new_edges) + } + + return(graph) +} diff --git a/R/task_dataset.R b/R/task_dataset.R index 70d58e82..5aadee7a 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -45,6 +45,29 @@ task_dataset = dataset( self$task = assert_r6(task$clone(deep = TRUE), "Task") self$feature_ingress_tokens = assert_list(feature_ingress_tokens, types = "TorchIngressToken", names = "unique") + lazy_tensor_features = self$task$feature_types[get("type") == "lazy_tensor"][[1L]] + self$cache_lazy_tensors = length(lazy_tensor_features) > 1L + + + # Here, we could have multiple `lazy_tensor` columns that share parts of the graph + # We try to merge those graphs if possible + if (length(lazy_tensor_features) > 1L) { + first_row = self$task$data(self$task$row_ids[1L], cols = lazy_tensor_features) + graphs = map(first_row, function(x) attr(x, "data_descriptor")$graph) + graphs = graphs[!duplicated(graphs)] + graphs[[1L]] = graphs[[1L]]$clone(deep = TRUE) + merged_graph = try(Reduce(function(x, y) merge_graphs(x, y, in_place = TRUE), graphs), silent = TRUE) + + if (!inherits(merged_graph, "try-error")) { + data = self$task$data(cols = lazy_tensor_features) + data = map_dtc(data, function(x) { + attr(x, "data_descriptor")$graph = merged_graph + x + }) + task$cbind(data) + } + } + iwalk(feature_ingress_tokens, function(it, nm) { if (length(it$features) == 0) { stopf("Received ingress token '%s' with no features.", nm) @@ -57,11 +80,12 @@ task_dataset = dataset( self$device = assert_choice(device, mlr_reflections$torch$devices) }, .getbatch = function(index) { + cache = if (self$cache_lazy_tensors) new.env() + datapool = self$task$data(rows = self$task$row_ids[index], cols = self$all_features) x = lapply(self$feature_ingress_tokens, function(it) { - it$batchgetter(datapool[, it$features, with = FALSE], self$device) + it$batchgetter(datapool[, it$features, with = FALSE], self$device, cache = cache) }) - x = materialize(x, device = self$device) y = if (!is.null(self$target_batchgetter)) { self$target_batchgetter(datapool[, self$task$target_names, with = FALSE], @@ -137,8 +161,10 @@ dataset_num_categ = function(task, param_vals) { #' `data.table` to be converted to a `tensor`. #' @param device (`character(1)`)\cr #' The device on which the tensor should be created. +#' @param ... (any)\cr +#' Unused. #' @export -batchgetter_num = function(data, device) { +batchgetter_num = function(data, device, ...) { torch_tensor( data = as.matrix(data), dtype = torch_float(), @@ -157,8 +183,10 @@ batchgetter_num = function(data, device) { #' `data.table` to be converted to a `tensor`. #' @param device (`character(1)`)\cr #' The device. +#' @param ... (any)\cr +#' Unused. #' @export -batchgetter_categ = function(data, device) { +batchgetter_categ = function(data, device, ...) { torch_tensor( data = as.matrix(data[, lapply(.SD, as.integer)]), dtype = torch_long(), @@ -168,7 +196,7 @@ batchgetter_categ = function(data, device) { get_batchgetter_img = function(imgshape) { - crate(function(data, device) { + crate(function(data, device, ...) { tensors = lapply(data[[1]], function(uri) { tnsr = torchvision::transform_to_tensor(magick::image_read(uri)) assert_true(length(tnsr$shape) == length(imgshape) && all(tnsr$shape == imgshape)) diff --git a/R/utils.R b/R/utils.R index 4248cab7..e82ee2de 100644 --- a/R/utils.R +++ b/R/utils.R @@ -192,3 +192,7 @@ assert_shapes = function(shapes) { assert_list(shapes, names = "unique", min.len = 1L) walk(shapes, assert_shape) } + +assert_lazy_tensor = function(x) { + assert_class(x, "lazy_tensor") +} diff --git a/R/zzz.R b/R/zzz.R index 7a4ae234..253fff83 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -118,6 +118,26 @@ register_mlr3pipelines = function() { if (Sys.getenv("IN_PKGDOWN") == "true") { lg$set_threshold("warn") } + + if (Sys.getenv("DEVTOOLS_LOAD", unset = "") == "mlr3torch") { + # When loading mlr3torch with devtools, we always get a warning when hashing lazy tensors. + # mlr3misc's calculate_hash function calls digest::digest which in turn serializes objects. + # When mlr3torch is loaded with devtools the `$initialize()` method of the dataset that underpins the lazy tensor + # behaves differently than when loaded with library() and always throws the warning: + # "package:mlr3torch" might not be avaiable when loading. + # + # Because this is quite annoying, we here suppress warnings that arise from the calculate_hash function. + + fn = force(mlr3misc::calculate_hash) + calculate_hash = mlr3misc::crate(function(...) { + suppressWarnings(fn(...)) + }, .parent = getNamespace("mlr3misc"), fn) + + unlockBinding("calculate_hash", parent.env(getNamespace("mlr3"))) + assign("calculate_hash", calculate_hash, envir = parent.env(getNamespace("mlr3"))) + lockBinding("calculate_hash", parent.env(getNamespace("mlr3"))) + } + } .onUnload = function(libPaths) { # nolint diff --git a/data-raw/mnist.R b/data-raw/mnist.R index e69de29b..831e43bd 100644 --- a/data-raw/mnist.R +++ b/data-raw/mnist.R @@ -0,0 +1,4 @@ +devtools::load_all() + +ci = col_info(get_private(tsk("mnist")$backend)$.constructor()) +saveRDS(ci, here::here("inst/col_info/mnist.rds")) diff --git a/inst/col_info/mnist.rds b/inst/col_info/mnist.rds index f28bbe19cec311b37822db972404bec3c8a2346c..f0f375d4329dbdbc56c5822f4977d77e426ce598 100644 GIT binary patch literal 266 zcmV+l0rmbLiwFP!000001C5Z~N&_(vg~#1(wJU;B@GT7fTVKE@Q1Gry+u0JBrX?Aa zdgX)5uGx|)HCGZ6zB!XQ$;^8V03}pqJO>eB@b>z0HHp!9mjF1AyNYYnC+!NCqygiM zI0Yxh`1R-1E;Jc7Y$Yo{W&GMsggDD?BJXDm*Dn6rK-WDUw(T1<}UDqjga$`r9fxTv13>WfF`1Fe=$@bZSGU58{v+ zjNLNAqZ8wpR+J_IrUw^*eRQniiP5#fjl!+M zox;7sgTkZ2lfq2ld2mY>#eylYHpU)}6D{jctLSh|Ay(y4%#On-c(>J=m6krphQweZ z!>iTgtS|nSt?Rm<^rof75R&&*4Kmh@3rl~L){A3ea8dU&_6}_w$hMwZ5ijG~51Ri^ Y8>ReMrY1U!1`gu;3wPIW1!)2R0DJg`5dZ)H diff --git a/inst/col_info/tiny_imagenet.rds b/inst/col_info/tiny_imagenet.rds index f2ef6093363805a35662e7fcea9a01ad0f159f2f..306f1a2c58072746764971cd6426922bef3b8a8a 100644 GIT binary patch literal 2781 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 literal 2790 zcmV}?kKMKrKC#z(u^oHebrQQl8=?)6ra0@OKpzUUK)YDy z@({O1EG!$fZW{q?%U7Le-GJN?AUBh@ppiKC)8Oh?tNzDz&nwcLuaP%Ws|$SRWjU|eAx0j z7?-%?ID2$5@kdez(Fu2B@Md!smzbCOXX^d5lC_vcTzO7s$fx~^SB^K(xD&xiaaAsM@1=15`e7ga-MF3a>7Y<8 zMi;Z-6|akqe$8v%h(Xq@Gn2-anRTWTTlQ*fI`N5*TsBNz8<&stn5&8hXT0CC!6>yK z__RxXx4E)qjtblr#yXQ1IIMVO3in4GZD;YfWkj)=+-Yuoq==s>H)g8m&;yanih42K z-+|L|wl0u`g2e>rQe+xS&{FhlQl+_fEAA?E^d{fq0Fr#x`=A}!V$J<-nc;ULV9C73 zM^H~6#)|d{J?x7WW=mum_Dv;t-Lr{z29Mwap55rorbduhU^}`%9)5Ftp3oJY{))zu z6z)gM1B7+p`yD1k^~)%7h#8H1Drh(lY|1W{ob7DhY3u(BWjx0X(%R*Ol7T zqvG_StrV(Z9U-m&3+IJ{CN^V2C0!G>lFhS{z9{dfl_EO?I5?QvrG(NXXIgf}yV*Qq zl8u=Fq2vsWr~?3L0Q_?8%ef3^m=3d(bp+7Mg;{r`@lPr=6fmce<`zrp!xZKYfGZgbg(9vWLWK?dHc!uwsCkS>pj4!qhcZ(}6 z-to8^6;@|~&Vk91D{2GRI>NB8@p1%9!dF5re)+T-Lk;j_}fAo|&KOT#i`0b1QJT)JcY?Yao=u-WEYa(|D2-v#&cElTZByrI4L@@R_X3PklfkPt1pI*G z3};Uvu_LgN?Zh7TOR)=-Vj_bVL z!-fw~iQGZ6&3>1~2aPBwe%1h42&u_^$n9|PY*&a6fYw&wcE~m2FfBwh)J9xMg;;r0 z?!|PC)qq#lf};b^Tw`WP7>xg6l))epO~4z(5<%MUm!NvmxN-2Xxh#0xj5rV+?Rjij zWV2T^<4_SqXI^;gg!d+2v{k%A!hur}g)mZ#7lS&9#FVs+`9d-N-IaguL`Hs8Xd)gU= zu<)aN=tGjX()W}e5-3VSv=N(>#0M+s#;A-(cRFKA2srC#4uB~l&)jDHcOz0Hq&j)* zlMbLMIJ2^&&8{S&e8u;9;ZJ%(!PwimaW+>xvfvRgzQMVC?M$18pCA;uZdD>2$d@Kt z-x+0wwG(8)AS0F2dFoP>fo<1~v;+Y7@v<&QK6wR=?nymK@UvG^JH%7p!`%>tc57nF zfV-1}(b;r9-o^J8x{ER6!UmydV1f|@@)6|kxf0kJMId0KmaTEwR38q2 zSAc^fKnIz`e;z1mP*6$)Qi=d~iCBxJb`v0TEqjh^0xGjgyq4A$1GzhxE7HVONd}IG z(f6yQ=RmJ=d@Yc@A#o}RLlJI@Y_vf}ZWDG>6A|Qta zD=A|`oY8e0u*weZSpf6(ME=yuH*d&9sljhaQII-@%sjPf#9b-gDg+kcK8awxfaAf+ zFuq8I>{YzmOs7Hy`2)PQFi2|DjZ$aMsb8R&=jF_(?g7hsInJR)nD4V)egKe5cLKng zhF`xR28ZQZ55R?Z{s~1!wuK`E$MB}GXDCx&Q8q&>#%~;DwcpxN*Rh(bIH5anD{}5o zDzU3_@W3tGJ$9mX68fA&9~4xT7k}RYQK;B6n$$xuLVQLkH-D>Olt4Pl;_9VhyX(fT z+OyTBhn|3^SiFbQpz&()7@(~a>on(>BzCc;rydcm9_#q(6cLpP{pglY6OUmy0g}3~JjBv6viG?|3RRr!~Y>HYF~O2LZ_eJq$&zH}hLoaS@` z)PAO-%91?4o43XVKbP>4Ugb~^;lOw%M|f+RVrq}DgHUV+L?@eqHSZy>wi6G8m_)Kj zr_NvcQCYmu8ZRMg*OD|8a$PE9?7v&;df?=T1sug{l39oNwA)WjH^wHo?arE`lt5IAx~y8}lpDn3HtyQ%?Fs`^(AhVROKM- zZGn1)N \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{\link[mlr3torch:PipeOpTorchLazyTransform]{mlr3torch::PipeOpTorchLazyTransform}} -> \code{PipeOpTOrchTransformResize} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTOrchTransformResize-new}{\code{PipeOpTorchTransformResize$new()}} +\item \href{#method-PipeOpTOrchTransformResize-clone}{\code{PipeOpTorchTransformResize$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTOrchTransformResize-new}{}}} +\subsection{Method \code{new()}}{ +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchTransformResize$new(id = "transform_resize", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +The id for of the new object.} + +\item{\code{param_vals}}{(named \code{list()})\cr +Parameter values to be set after construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTOrchTransformResize-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchTransformResize$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/batchgetter_categ.Rd b/man/batchgetter_categ.Rd index dc898fbb..7a721561 100644 --- a/man/batchgetter_categ.Rd +++ b/man/batchgetter_categ.Rd @@ -4,7 +4,7 @@ \alias{batchgetter_categ} \title{Batchgetter for Categorical data} \usage{ -batchgetter_categ(data, device) +batchgetter_categ(data, device, ...) } \arguments{ \item{data}{(\code{data.table})\cr @@ -12,6 +12,9 @@ batchgetter_categ(data, device) \item{device}{(\code{character(1)})\cr The device.} + +\item{...}{(any)\cr +Unused.} } \description{ Converts a data frame of categorical data into a long tensor by converting the data to integers. diff --git a/man/batchgetter_num.Rd b/man/batchgetter_num.Rd index b7ff4b9b..4b8ffa84 100644 --- a/man/batchgetter_num.Rd +++ b/man/batchgetter_num.Rd @@ -4,7 +4,7 @@ \alias{batchgetter_num} \title{Batchgetter for Numeric Data} \usage{ -batchgetter_num(data, device) +batchgetter_num(data, device, ...) } \arguments{ \item{data}{(\code{data.table()})\cr @@ -12,6 +12,9 @@ batchgetter_num(data, device) \item{device}{(\code{character(1)})\cr The device on which the tensor should be created.} + +\item{...}{(any)\cr +Unused.} } \description{ Converts a data frame of numeric data into a float tensor by calling \code{as.matrix()}. diff --git a/man/merge_graphs.Rd b/man/merge_graphs.Rd new file mode 100644 index 00000000..1ecfac76 --- /dev/null +++ b/man/merge_graphs.Rd @@ -0,0 +1,11 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/merge_graphs.R +\name{merge_graphs} +\alias{merge_graphs} +\title{note that this mo} +\usage{ +merge_graphs(g1, g2, in_place = FALSE) +} +\description{ +note that this mo +} diff --git a/man/mlr_pipeops_torch.Rd b/man/mlr_pipeops_torch.Rd index a56184d5..26386db0 100644 --- a/man/mlr_pipeops_torch.Rd +++ b/man/mlr_pipeops_torch.Rd @@ -292,7 +292,8 @@ Creates a new instance of this \link[R6:R6Class]{R6} class. inname = "input", outname = "output", packages = "torch", - tags = NULL + tags = NULL, + variant_types = FALSE )}\if{html}{\out{}} } diff --git a/man/mlr_pipeops_torch_lazy_transform.Rd b/man/mlr_pipeops_torch_lazy_transform.Rd new file mode 100644 index 00000000..66da478c --- /dev/null +++ b/man/mlr_pipeops_torch_lazy_transform.Rd @@ -0,0 +1,120 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchLazyTransform.R +\name{mlr_pipeops_torch_lazy_transform} +\alias{mlr_pipeops_torch_lazy_transform} +\alias{PipeOpTorchLazyTransform} +\title{Base Class for Lazy Transformations} +\description{ +This is the base class for lazy tensor transformations. +These can either be used as preprocessing for \code{\link{lazy_tensor}} objects or as part of the +graph contained in the \code{\link{ModelDescriptor}}. +Currently the \code{PipeOp} must have exactly one inut and one output. +} +\section{Inheriting}{ + +You need to: +\itemize{ +\item Either provide a function as argument \code{fn} or overwrite the private \code{.make_module()} method. +See \code{\link{PipeOpTorch}} for how to do this. +\item In case the transformation changes the tensor shapes you must provide a private \code{.shapes_out()} method like +for \code{\link{PipeOpTorch}}. It can be assumed that the first dimension is \code{NA}, i.e. the batch dimension. +} + +Depending on the data-loader, this function is either applied individually to each tensor from a batch and then +concatenated, or to the whole batch at once and should return the same result in both cases. +} + +\section{Input and Output Channels}{ + +During \emph{training}, all inputs and outputs are of class \code{\link{Task}} or \code{\link{ModelDescriptor}}. +During \emph{prediction}, all inputs and outputs are of class \code{\link{Task}} or \code{\link{ModelDescriptor}}. +} + +\section{State}{ + +The state is the value calculated by the public method \code{shapes_out()}. +} + +\section{Parameters}{ + +The \code{\link[paradox:ParamSet]{ParamSet}} is specified by the child class inheriting from \code{\link{PipeOpTorchLazyTransform}}. +} + +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchLazyTransform} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchLazyTransform-new}{\code{PipeOpTorchLazyTransform$new()}} +\item \href{#method-PipeOpTorchLazyTransform-clone}{\code{PipeOpTorchLazyTransform$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchLazyTransform-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchLazyTransform$new( + fn, + id = "lazy_transform", + param_vals = list(), + param_set = ps(), + packages = character(0) +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{fn}}{(\verb{function()})\cr +A function that will be applied to a (lazy) tensor. +Additional arguments can be passed as parameters. +During actual preprocessing the (lazy) tensor will be passed by position.} + +\item{\code{id}}{(\code{character(1)})\cr +The id for of the new object.} + +\item{\code{param_vals}}{(named \code{list()})\cr +Parameter values to be set after construction.} + +\item{\code{param_set}}{(\code{paradox::ParamSet})\cr +The parameter set.} + +\item{\code{packages}}{(\code{character()})\cr +The packages the function depends on. +If \code{fn} is from a namespace and no value is provided the namespace is automatically set.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchLazyTransform-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchLazyTransform$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/tests/testthat/helper_functions.R b/tests/testthat/helper_functions.R index 46efa9ab..e78ff384 100644 --- a/tests/testthat/helper_functions.R +++ b/tests/testthat/helper_functions.R @@ -19,7 +19,7 @@ expect_po_ingress = function(po_ingress, task) { ds = task_dataset(task, ingress, device = "cpu") batch = ds$.getbatch(1) x = batch$x[[1L]] - testthat::expect_true(torch_equal(x, token$ingress[[1L]]$batchgetter(task$data(1, token$task$feature_names), "cpu"))) + testthat::expect_true(torch_equal(x, token$ingress[[1L]]$batchgetter(task$data(1, token$task$feature_names), "cpu", cache = NULL))) } expect_man_exists = function(man) { diff --git a/tests/testthat/helper_tasks.R b/tests/testthat/helper_tasks.R index 0507c9d0..42109805 100644 --- a/tests/testthat/helper_tasks.R +++ b/tests/testthat/helper_tasks.R @@ -30,9 +30,9 @@ nano_mnist = function(id = "nano_mnist") { data = readRDS(file.path(path, "data.rds")) ds = dataset( - initialize = function(images) { + initialize = crate(function(images) { self$images = torch_tensor(images, dtype = torch_float32()) - }, + }), .getbatch = function(idx) { list(image = self$images[idx, , , drop = FALSE]) }, @@ -44,14 +44,14 @@ nano_mnist = function(id = "nano_mnist") { dt = data.table( image = lazy_tensor(data_descriptor), label = droplevels(data$label), - row_id = seq_along(data$label) + ..row_id = seq_along(data$label) ) - backend = DataBackendDataTable$new(data = dt, primary_key = "row_id") + backend = DataBackendDataTable$new(data = dt, primary_key = "..row_id") task = TaskClassif$new( backend = backend, - id = "nano_mnisst", + id = "nano_mnist", target = "label", label = "MNIST Nano" ) diff --git a/tests/testthat/test_PipeOpTorchIngress.R b/tests/testthat/test_PipeOpTorchIngress.R index 323dc56a..f50f3d2f 100644 --- a/tests/testthat/test_PipeOpTorchIngress.R +++ b/tests/testthat/test_PipeOpTorchIngress.R @@ -41,6 +41,18 @@ test_that("PipeOpTorchIngressLazyTensor", { batch_meta = ds_meta$.getbatch(2:3) expect_true(batch_meta$x$torch_ingress_ltnsr.input$device == torch_device("meta")) + task_old = task$clone() task$cbind(data.frame(row_id = 1:10, x_num = 1:10)) expect_po_ingress(po_ingress, task) + + graph = po("torch_ingress_ltnsr") %>>% + po("nn_flatten") %>>% + po("nn_linear", out_features = 10) %>>% + po("nn_relu") %>>% + po("nn_head") %>>% + po("torch_loss", "cross_entropy") %>>% + po("torch_optimizer") %>>% + po("torch_model_classif", epochs = 1L, device = "cpu", batch_size = 16) + + graph$train(task_old) }) diff --git a/tests/testthat/test_PipeOpTorchLazyTransform.R b/tests/testthat/test_PipeOpTorchLazyTransform.R new file mode 100644 index 00000000..0260eba1 --- /dev/null +++ b/tests/testthat/test_PipeOpTorchLazyTransform.R @@ -0,0 +1,24 @@ +test_that("PipeOpTorchLazyTransform works for preprocessing", { + task = nano_mnist() + po_resize = po("transform_resize", size = c(10, 10)) + + task1 = po_resize$train(list(task))[[1L]] + + lt = task1$data(cols = "image") + +}) + +test_that("PipeOpTorchLazyTransform works in Graph", { + task = nano_mnist() + + graph = po("torch_ingress_ltnsr") %>>% + po("transform_resize", size = c(10, 10)) %>>% + po("nn_flatten") %>>% + po("nn_head") %>>% + po("torch_optimizer") %>>% + po("torch_loss", "cross_entropy") %>>% + po("torch_model_classif", epochs = 1L, device = "cpu", batch_size = 16) + + graph$train(task)[[1L]] + +}) diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index c1bfee56..c2a66794 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -18,3 +18,50 @@ test_that("lazy_tensor works", { lt1_empty[1] = lt1[1] }) + +test_that("transform_lazy_tensor works", { + lt = as_lazy_tensor(torch_randn(16, 2, 5)) + lt_mat = materialize(lt) + + expect_equal(lt_mat$shape, c(16, 2, 5)) + + mod = nn_module( + forward = function(x) { + torch_reshape(x, c(-1, 10)) + } + )() + po_module = po("module", module = mod, id = "mod") + + new_shape = c(NA, 10) + + lt1 = transform_lazy_tensor(lt, po_module, new_shape) + + dd1 = attr(lt1, "data_descriptor") + expect_equal(dd$graph$edges, + data.table(src_id = "dataset_x", src_channel = "output", dst_id = "mod", dst_channel = "input") + ) + + dd = attr(lt, "data_descriptor") + + # graph was cloned + expect_true(!identical(dd1$graph, dd$graph)) + # pipeop was cloned + expect_true(!identical(dd1$graph$pipeops$dataset_x, dd$graph$pipeops$dataset_x)) + + # .pointer was set + expect_equal(dd1$.pointer, c("mod", "output")) + + # .pointer_shape was set + expect_equal(dd1$.pointer_shape, c(NA, 10)) + + # hash was updated + expect_false(dd$.hash == dd1$.hash) + expect_true(dd$.dataset_hash == dd1$.dataset_hash) + + # materialization gives correct result + lt1_mat = materialize(lt1) + expect_equal(lt1_mat$shape, c(16, 10)) + + lt1_mat = torch_reshape(lt1_mat, c(-1, 2, 5)) + expect_true(torch_equal(lt1_mat, lt_mat)) +}) diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index cebd497d..19e83e91 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -292,3 +292,16 @@ test_that("dataset_img works", { batch_meta = ds_meta$.getbatch(1) expect_true(batch_meta$x$image$device$type == "meta") }) + +test_that("task_dataset works with multiple lazy_tensor columns", { + task = nano_mnist() + graph = po("torch_ingress_ltnsr") %>>% + po("transform_resize", size = c(40, 40)) %>>% + list( + po("transform_resize_1", size = c(30, 30)), + po("transform_resize_2", size = c(15, 15)) + ) + + graph$train(task) + +}) From ca0c6c97663ad0ff66baf62005564408fdc06dda Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 13 Oct 2023 13:45:00 +0200 Subject: [PATCH 04/90] sperate preproc and trafo class, generate pipeops programatically --- DESCRIPTION | 4 +- NAMESPACE | 4 +- R/PipeOpModule.R | 7 +- R/PipeOpTorch.R | 17 +- R/PipeOpTorchLazyPreproc.R | 87 ++++++++ R/PipeOpTorchLazyTrafo.R | 142 +++++++++++++ R/PipeOpTorchLazyTransform.R | 199 ------------------ R/register_lazy.R | 100 +++++++++ R/task_dataset.R | 3 + man/PipeOpTorchTransformResize.Rd | 68 ------ man/mlr_pipeops_module.Rd | 4 +- man/mlr_pipeops_torch.Rd | 3 +- man/mlr_pipeops_torch_lazy_trafo.Rd | 151 +++++++++++++ man/mlr_pipeops_torch_lazy_transform.Rd | 120 ----------- man/preproc_and_lazy.Rd | 9 + tests/testthat/helper_autotest.R | 5 + .../testthat/test_PipeOpTorchLazyTransform.R | 26 +++ tests/testthat/test_PipeOpTorchPreprocess.R | 4 + tests/testthat/test_task_dataset.R | 5 +- 19 files changed, 554 insertions(+), 404 deletions(-) create mode 100644 R/PipeOpTorchLazyPreproc.R create mode 100644 R/PipeOpTorchLazyTrafo.R delete mode 100644 R/PipeOpTorchLazyTransform.R create mode 100644 R/register_lazy.R delete mode 100644 man/PipeOpTorchTransformResize.Rd create mode 100644 man/mlr_pipeops_torch_lazy_trafo.Rd delete mode 100644 man/mlr_pipeops_torch_lazy_transform.Rd create mode 100644 man/preproc_and_lazy.Rd create mode 100644 tests/testthat/test_PipeOpTorchPreprocess.R diff --git a/DESCRIPTION b/DESCRIPTION index 497f4ae4..e5482f58 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -103,7 +103,8 @@ Collate: 'PipeOpTorchHead.R' 'PipeOpTorchIngress.R' 'PipeOpTorchLayerNorm.R' - 'PipeOpTorchLazyTransform.R' + 'PipeOpTorchLazyPreproc.R' + 'PipeOpTorchLazyTrafo.R' 'PipeOpTorchLinear.R' 'TorchLoss.R' 'PipeOpTorchLoss.R' @@ -128,6 +129,7 @@ Collate: 'nn_graph.R' 'paramset_torchlearner.R' 'rd_info.R' + 'register_lazy.R' 'reset_last_layer.R' 'task_dataset.R' 'utils.R' diff --git a/NAMESPACE b/NAMESPACE index 9b0877e0..7c9443b9 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -64,6 +64,7 @@ export(LearnerTorchMLP) export(LearnerTorchModel) export(ModelDescriptor) export(PipeOpModule) +export(PipeOpTaskPreprocLazy) export(PipeOpTorch) export(PipeOpTorchAvgPool1D) export(PipeOpTorchAvgPool2D) @@ -94,7 +95,7 @@ export(PipeOpTorchIngressImage) export(PipeOpTorchIngressLazyTensor) export(PipeOpTorchIngressNumeric) export(PipeOpTorchLayerNorm) -export(PipeOpTorchLazyTransform) +export(PipeOpTorchLazyTrafo) export(PipeOpTorchLeakyReLU) export(PipeOpTorchLinear) export(PipeOpTorchLogSigmoid) @@ -125,7 +126,6 @@ export(PipeOpTorchSqueeze) export(PipeOpTorchTanh) export(PipeOpTorchTanhShrink) export(PipeOpTorchThreshold) -export(PipeOpTorchTransformResize) export(PipeOpTorchUnsqueeze) export(ResamplingRowRoles) export(TorchCallback) diff --git a/R/PipeOpModule.R b/R/PipeOpModule.R index 07f44859..95054490 100644 --- a/R/PipeOpModule.R +++ b/R/PipeOpModule.R @@ -83,8 +83,8 @@ PipeOpModule = R6Class("PipeOpModule", #' @description #' Creates a new instance of this [R6][R6::R6Class] class. #' @template param_id - #' @param module ([`nn_module`])\cr - #' The torch module that is being wrapped. + #' @param module ([`nn_module`] or `function()`)\cr + #' The torch module or function that is being wrapped. #' @param inname (`character()`)\cr #' The names of the input channels. #' @param outname (`character()`)\cr @@ -95,7 +95,8 @@ PipeOpModule = R6Class("PipeOpModule", initialize = function(id = "module", module = nn_identity(), inname = "input", outname = "output", param_vals = list(), packages = character(0)) { private$.multi_output = length(outname) > 1L - self$module = assert_class(module, "nn_module") + self$module = assert(check_class(module, "nn_module"), check_class(module, "function"), combine = "or") + self$module = module assert_names(outname, type = "strict") assert_character(packages, any.missing = FALSE) diff --git a/R/PipeOpTorch.R b/R/PipeOpTorch.R index bf05504d..ac431b9e 100644 --- a/R/PipeOpTorch.R +++ b/R/PipeOpTorch.R @@ -249,7 +249,7 @@ PipeOpTorch = R6Class("PipeOpTorch", #' [`PipeOp`] during training must return a named `list()`, where the names of the list are the #' names out the output channels. The default is `"output"`. initialize = function(id, module_generator, param_set = ps(), param_vals = list(), - inname = "input", outname = "output", packages = "torch", tags = NULL, variant_types = FALSE) { + inname = "input", outname = "output", packages = "torch", tags = NULL) { self$module_generator = assert_class(module_generator, "nn_module_generator", null.ok = TRUE) assert_character(inname, .var.name = "input channel names") assert_character(outname, .var.name = "output channel names", min.len = 1L) @@ -257,9 +257,8 @@ PipeOpTorch = R6Class("PipeOpTorch", assert_character(packages, any.missing = FALSE) packages = union(packages, "torch") - data_type = if (variant_types) "*" else "ModelDescriptor" - input = data.table(name = inname, train = data_type, predict = "*") - output = data.table(name = outname, train = data_type, predict = "*") + input = data.table(name = inname, train = "ModelDescriptor", predict = "*") + output = data.table(name = outname, train = "ModelDescriptor", predict = "*") assert_r6(param_set, "ParamSet") #walk(param_set$params, function(p) { @@ -296,9 +295,15 @@ PipeOpTorch = R6Class("PipeOpTorch", } else { assert_list(shapes_in, len = nrow(self$input), types = "numeric") } - pv = self$param_set$get_values() - set_names(private$.shapes_out(shapes_in, pv, task = task), self$output$name) + s = if (is.null(private$.shapes_out)) { + shapes_in + } else { + pv = self$param_set$get_values() + private$.shapes_out(shapes_in, pv, task = task, self$output$name) + } + + set_names(s, self$output$name) } # TODO: printer that calls the nn_module's printer diff --git a/R/PipeOpTorchLazyPreproc.R b/R/PipeOpTorchLazyPreproc.R new file mode 100644 index 00000000..1bf7e583 --- /dev/null +++ b/R/PipeOpTorchLazyPreproc.R @@ -0,0 +1,87 @@ +#' @export +PipeOpTaskPreprocLazy = R6Class("PipeOpTaskPreprocLazy", + inherit = PipeOpTaskPreproc, + public = list( + initialize = function(fn, id = "lazy_preproc", param_vals = list(), param_set = ps(), packages = character(0)) { + private$.fn = assert_function(fn, null.ok = FALSE) + + if ("augment" %in% param_set$ids()) { + stopf("Parameter name 'augment' is reserved and cannot be used.") + } + if (is.null(private$.shapes_out)) { + param_set$add(ps( + augment = p_lgl(tags = c("predict", "required")) + )) + param_set$set_values(augment = FALSE) + } + + super$initialize( + id = id, + param_vals = param_vals, + feature_types = "lazy_tensor" + ) + } + ), + private = list( + .train_dt = function(dt, levels, target) { + if (ncol(dt) != 1L) { + # Check only during train as this will ensure it also holds during predict + stop("Can only use PipeOpTorchLazyTrafo on tasks with exactly one lazy tensor column.") + } + param_vals = self$param_set$get_values(tags = "train") + + trafo = private$.fn + + fn = if (length(param_vals)) { + crate(function(x) { + invoke(.f = trafo, x, .args = param_vals) + }, param_vals, trafo, .parent = topenv()) + } else { + trafo + } + + self$state = list() + + private$.transform_dt(dt, fn) + }, + .predict_dt = function(dt, levels) { + param_vals = self$param_set$get_values(tags = "predict") + augment = param_vals$augment + param_vals$augment = NULL + + # augment can be NULL (in case the pipeopf changes the output shape and hence augmentation is not supported) + # or a logical(1) + fn = if (isTRUE(augment)) { + identity + } else { + trafo = private$.fn + crate(function(x) { + invoke(.f = trafo, x, .args = param_vals) + }, param_vals, trafo, .parent = topenv()) + } + + private$.transform_dt(dt, fn) + }, + .transform_dt = function(dt, fn) { + po_fn = PipeOpModule$new( + id = self$id, + module = fn, + inname = self$input$name, + outname = self$output$name, + packages = self$packages + ) + + lt = dt[[1L]] + + shapes_in = attr(lt[[1L]], "data_descriptor")$.pointer_shape + + shapes_out = self$shapes_out(shapes_in, intask) + dt[[1L]] = transform_lazy_tensor(lt, po_fn, shapes_out[[1L]]) + return(dt) + }, + .fn = NULL, + .additional_phash_input = function() { + list(self$param_set$ids(), private$.fn, self$packages) + } + ) +) diff --git a/R/PipeOpTorchLazyTrafo.R b/R/PipeOpTorchLazyTrafo.R new file mode 100644 index 00000000..5b6b7d57 --- /dev/null +++ b/R/PipeOpTorchLazyTrafo.R @@ -0,0 +1,142 @@ +#' @title Base Class for Lazy Transformations +#' @name mlr_pipeops_torch_lazy_trafo +#' +#' @description +#' This `PipeOp` represents simple preprocessing transformations of torch tensors. +#' These can be used in two situations: +#' +#' 1. To preprocess a task, which works analogous to standard preprocessing PipeOps like [`PipeOpPCA`]. +#' Because the [`lazy_tensor()`] does not make any assumptions on how the data is stored, the transformation is +#' applied lazily, i.e. when [`materialize()`] is called. +#' During trainig of a learner, this transformation will be a applied during data-loading on the CPU. +#' +#' 2. To add a preprocessing step in an [`nn_graph()`] that is being built up in a [`ModelDescriptor`]. +#' In this case, the transformation is applied during the forward pass of the model, i.e. the tensor is then +#' also on the specified device. +#' +#' Currently the `PipeOp` must have exactly one inut and one output. +#' +#' @section Inheriting: +#' You need to: +#' * Initialize the `fn` argument. This function should take one torch tensor as input and return a torch tensor. +#' Additional parameters that are passed to the function can be specified via the parameter set. +#' This function needs to be a simple, stateless function, see section *Internals* for more information. +#' * In case the transformation changes the tensor shape you must provide a private `.shapes_out()` method like +#' for [`PipeOpTorch`]. +#' +#' @section Input and Output Channels: +#' During *training*, all inputs and outputs are of class [`Task`] or [`ModelDescriptor`]. +#' During *prediction*, all inputs and outputs are of class [`Task`] or [`ModelDescriptor`]. +#' +#' @template pipeop_torch_state_default +#' @section Parameters: +#' * `augment` :: `logical(1)`\cr +#' This parameter is only present when the `PipeOp` does not modify the input shape. +#' Whether the transformation is applied only during training (`TRUE`) or also during prediction (also includes +#' validation; `FALSE`). +#' This parameter is initalized to `FALSE`. +#' +#' Additional parameters can be specified by the class. +#' +#' @section Internals: +#' +#' Applied to a **Task**: +#' +#' When this PipeOp is used for preprocessing, it creates a [`PipeOpModule`] from the function `fn` (additionally +#' passing the `param_vals` if there are any) and then adds it to the preprocessing graph that is part of the +#' [`DataDescriptor`] contained in the [`lazy_tensor`] column that is being preprocessed. +#' When the outpuf of this pipeop is then preprocessed by a different `PipeOpTorchLazyTrafo` a deep clone of the +#' preprocessing graph is done. However, this deep clone does not clone the environment of the +#' function or its attributes in case they have a state (as e.g. in [`nn_module()`]s). +#' When setting the parameter `augment` this meanst that the preprcessing +#' +#' Applied to a **ModelDescriptor** +#' +#' +#' +#' +#' @template param_id +#' @template param_param_vals +#' @template param_param_set +#' @param packages (`character()`)\cr +#' The packages the function depends on. +#' @param fn (`function()`)\cr +#' A function that will be applied to a (lazy) tensor. +#' Additional arguments can be passed as parameters. +#' During actual preprocessing the (lazy) tensor will be passed by position. +#' The transformation is always applied to a whole batch of tensors, i.e. the first dimension is the batch dimension. +#' +#' @export +PipeOpTorchLazyTrafo = R6Class("PipeOpTorchLazyTrafo", + inherit = PipeOpTorch, + public = list( + #' @description Creates a new instance of this [R6][R6::R6Class] class. + initialize = function(fn, id = "lazy_trafo", param_vals = list(), param_set = ps(), packages = character(0)) { + private$.fn = assert_function(fn, null.ok = FALSE) + + if ("augment" %in% param_set$ids()) { + stopf("Parameter name 'augment' is reserved and cannot be used.") + } + + if (is.null(private$.shapes_out)) { + param_set$add(ps( + augment = p_lgl(tags = c("train", "required")) + )) + param_set$set_values(augment = FALSE) + } + + super$initialize( + id = id, + inname = "input", + outname = "output", + param_vals = param_vals, + param_set = param_set, + packages = packages, + module_generator = NULL + ) + + } + ), + private = list( + .fn = NULL, + .make_module = function(shapes_in, param_vals, task) { + # this function is only called when the input is the ModelDescriptor + augment = param_vals$augment + param_vals$augment = NULL + trafo = private$.fn + fn = if (length(param_vals)) { + crate(function(x) { + invoke(.f = trafo, x, .args = param_vals) + }, param_vals, trafo, .parent = topenv()) + } else { + trafo + } + + # augment can be NULL or logical(1) + if (!isTRUE(augment)) { + return(fn) + } + + nn_module(self$id, + initialize = function(fn) { + self$fn = fn + }, + forward = function(x) { + if (self$training) { + self$fn(x) + } else { + x + } + } + )(fn) + }, + .additional_phash_input = function() { + list(self$param_set$ids(), private$.fn, self$packages) + } + ) +) + +#' @include zzz.R +register_po("lazy_trafo", PipeOpTorchLazyTrafo) + + diff --git a/R/PipeOpTorchLazyTransform.R b/R/PipeOpTorchLazyTransform.R deleted file mode 100644 index 5c898aec..00000000 --- a/R/PipeOpTorchLazyTransform.R +++ /dev/null @@ -1,199 +0,0 @@ -#' @title Base Class for Lazy Transformations -#' @name mlr_pipeops_torch_lazy_transform -#' -#' @description -#' This is the base class for lazy tensor transformations. -#' These can either be used as preprocessing for [`lazy_tensor`] objects or as part of the -#' graph contained in the [`ModelDescriptor`]. -#' Currently the `PipeOp` must have exactly one inut and one output. -#' -#' @section Inheriting: -#' You need to: -#' * Either provide a function as argument `fn` or overwrite the private `.make_module()` method. -#' See [`PipeOpTorch`] for how to do this. -#' * In case the transformation changes the tensor shapes you must provide a private `.shapes_out()` method like -#' for [`PipeOpTorch`]. It can be assumed that the first dimension is `NA`, i.e. the batch dimension. -#' -#' Depending on the data-loader, this function is either applied individually to each tensor from a batch and then -#' concatenated, or to the whole batch at once and should return the same result in both cases. -#' -#' @section Input and Output Channels: -#' During *training*, all inputs and outputs are of class [`Task`] or [`ModelDescriptor`]. -#' During *prediction*, all inputs and outputs are of class [`Task`] or [`ModelDescriptor`]. -#' -#' @template pipeop_torch_state_default -#' @section Parameters: -#' The [`ParamSet`][paradox::ParamSet] is specified by the child class inheriting from [`PipeOpTorchLazyTransform`]. -#' The name `augment` is reserved and must not be used. -#' -#' @template param_id -#' @template param_param_vals -#' @template param_param_set -#' @param packages (`character()`)\cr -#' The packages the function depends on. -#' If `fn` is from a namespace and no value is provided the namespace is automatically set. -#' @param fn (`function()`)\cr -#' A function that will be applied to a (lazy) tensor. -#' Additional arguments can be passed as parameters. -#' During actual preprocessing the (lazy) tensor will be passed by position. -#' -#' @export -PipeOpTorchLazyTransform = R6Class("PipeOpTorchLazyTransform", - inherit = PipeOpTorch, - public = list( - #' @description Creates a new instance of this [R6][R6::R6Class] class. - initialize = function(fn, id = "lazy_transform", param_vals = list(), param_set = ps(), packages = character(0)) { - private$.fn = assert_function(fn, null.ok = TRUE) - if (isNamespace(environment(fn)) && (length(packages) == 0)) { - packages = getNamespaceName(environment(fn)) - } - - param_set$add(ps( - augment = p_lgl(tags = c("train", "predict")) - )) - param_set$set_values(augment = FALSE) - - super$initialize( - id = id, - # TODO: Generalize this to arbitrary number of inputs and outputs - inname = "input", - outname = "output", - param_vals = param_vals, - param_set = param_set, - packages = packages, - module_generator = NULL, - variant_types = TRUE - ) - - } - ), - private = list( - .fn = NULL, - .make_module = function(shapes_in, param_vals, task) { - augment = param_vals$augment - param_vals$augment = NULL - trafo = private$.fn - fn = crate(function(x) { - invoke(.f = trafo, x, .args = param_vals) - }, param_vals, trafo, .parent = topenv()) - - if (augment) { - nn_module(self$id, - initialize = function(fn) { - self$fn = fn - }, - forward = function(x) { - if (self$training) { - self$fn(x) - } else { - x - } - } - )(fn) - } else { - nn_module(self$id, - initialize = function(fn) { - self$fn = fn - }, - forward = function(x) { - self$fn(x) - } - )(fn) - } - }, - .train = function(inputs) { - if (test_class(inputs[[1L]], "ModelDescriptor")) { - super$.train(inputs) - } else if (test_class(inputs[[1L]], "Task")) { - private$.transform_task(inputs) - } else { - stopf("Unsupported input type '%s'.", class(inputs)[[1L]]) - } - }, - .predict = function(inputs) { - if (test_class(inputs[[1L]], "ModelDescriptor")) { - super$.predict(inputs) - } else if (test_class(inputs[[1L]], "Task")) { - private$.transform_task(inputs) - } - }, - .transform_task = function(inputs) { - intask = inputs[[1L]]$clone(deep = TRUE) - - lazy_cols = intask$feature_types[get("type") == "lazy_tensor", "id"][[1L]] - if (length(lazy_cols) != 1L) { - stopf("Can only use PipeOpTorchLazyTransform on tasks with exactly one lazy tensor column.") - } - lt = intask$data(cols = lazy_cols)[[1L]] - - self$state = list(lazy_cols) - - shapes_in = attr(lt[[1L]], "data_descriptor")$.pointer_shape - - fn = private$.make_module(shapes_in = shapes_in, param_vals = self$param_set$values, task = intask) - - po_fn = PipeOpModule$new( - id = self$id, - module = fn, - inname = self$input$name, - outname = self$output$name, - packages = self$packages - ) - - shapes_out = self$shapes_out(shapes_in, intask) - lt_processed = transform_lazy_tensor(lt, po_fn, shapes_out[[1L]]) - new_col = set_names(data.table(lt_processed), lazy_cols) - - list(intask$select(setdiff(intask$feature_names, lazy_cols))$cbind(new_col)) - }, - .additional_phash_input = function() { - list(self$param_set$ids(), private$.fn, self$packages) - } - ) -) - -#' @include zzz.R -register_po("lazy_transform", PipeOpTorchLazyTransform) - - -#' @title Resize an Object -#' @description -#' See [`torchvision::transform_resize()`] for more information. -#' Creates a new instance of this [R6][R6::R6Class] class. -#' @template param_id -#' @template param_param_vals -#' @export -PipeOpTorchTransformResize = R6Class("PipeOpTOrchTransformResize", - inherit = PipeOpTorchLazyTransform, - public = list( - initialize = function(id = "transform_resize", param_vals = list()) { - param_set = ps( - size = p_uty(tags = c("train", "required")), - interpolation = p_fct(levels = magick::filter_types(), special_vals = list(0L, 2L, 3L), - tags = "train", default = 2L - ) - ) - super$initialize( - id = id, - packages = "torchvision", - param_set = param_set, - param_vals = param_vals, - fn = torchvision::transform_resize - ) - } - ), - private = list( - .shapes_out = function(shapes_in, param_vals, task) { - size = param_vals$size - shape = shapes_in[[1L]] - assert_true(length(shape) > 2) - height = shape[[length(shape) - 1L]] - width = shape[[length(shape)]] - s = torchvision::transform_resize(torch_ones(c(1, height, width), device = "meta"), size = size)$shape[2:3] - list(c(shape[seq_len(length(shape) - 2L)], s)) - } - ) -) - -#' @include zzz.R -register_po("transform_resize", PipeOpTorchTransformResize) diff --git a/R/register_lazy.R b/R/register_lazy.R new file mode 100644 index 00000000..2b8a9c17 --- /dev/null +++ b/R/register_lazy.R @@ -0,0 +1,100 @@ +register_trafo = function(name, fn, param_set, shapes_out = NULL, packages, envir) { + classname = paste0("PipeOpTorchTrafo", capitalize(name)) + idname = paste0("trafo_", name) + + init_fun = crate(function(id = idname, param_vals = list()) { + super$initialize( + id = id, + packages = packages, + param_set = param_set, + param_vals = param_vals, + fn = fn + ) + }, param_set, fn, idname, packages, .parent = topenv()) + + Class = R6Class(classname, + inherit = PipeOpTorchLazyTrafo, + public = list( + initialize = init_fun + ), + private = list( + .shapes_out = shapes_out + ) + ) + + assign(classname, Class, envir = envir) + register_po(idname, Class) + + return(NULL) +} + +register_preproc = function(name, fn, param_set, shapes_out, packages, envir) { + classname = paste0("PipeOpTaskPreprocLazy", capitalize(name)) + idname = paste0("preproc_", name) + + init_fun = crate(function(id = idname, param_vals = list()) { + super$initialize( + id = id, + packages = packages, + param_set = param_set, + param_vals = param_vals, + fn = fn + ) + }, param_set, fn, idname, packages, .parent = topenv()) + + Class = R6Class(classname, + inherit = PipeOpTaskPreprocLazy, + public = list( + initialize = init_fun + ), + private = list( + .shapes_out = shapes_out + ) + ) + + assign(classname, Class, envir = envir) + register_po(idname, Class) + + return(NULL) + +} + +#' @include PipeOpTorchLazyTrafo.R PipeOpTorchLazyPreproc.R +register_lazy = function(name, fn, param_set, shapes_out, packages, envir = parent.frame()) { + register_trafo(name, fn, param_set, shapes_out, packages, envir = envir) + register_preproc(name, fn, param_set, shapes_out, packages, envir = envir) + + return(NULL) +} + +#' @title Lazy Preprocessing and Transformations +#' @name preproc_and_lazy +#' @section Available PipeOps: +#' The following +NULL + + +#' @name PipeOpTaskPreprocLazyResize +#' @alias PipeOpTorchLazyTrafoResize +#' @rdname preproc_and_lazy +register_lazy("resize", torchvision::transform_resize, + packages = "torchvision", + param_set = ps( + size = p_uty(tags = c("train", "required")), + interpolation = p_fct(levels = magick::filter_types(), special_vals = list(0L, 2L, 3L), + tags = "train", default = 2L + ) + ), + shapes_out = function(shapes_in, param_vals, task) { + size = param_vals$size + shape = shapes_in[[1L]] + assert_true(length(shape) > 2) + height = shape[[length(shape) - 1L]] + width = shape[[length(shape)]] + s = torchvision::transform_resize(torch_ones(c(1, height, width), device = "meta"), size = size)$shape[2:3] + list(c(shape[seq_len(length(shape) - 2L)], s)) + } +) + +#' @rawNamespace exportPattern("^PipeOpTaskPreprocLazy") +#' @rawNamespace exportPattern("^PipeOpTorchLazyTrafo") diff --git a/R/task_dataset.R b/R/task_dataset.R index 5aadee7a..0bd05d5e 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -51,6 +51,9 @@ task_dataset = dataset( # Here, we could have multiple `lazy_tensor` columns that share parts of the graph # We try to merge those graphs if possible + + # FIXME: I am not sure whether this belongs here ... + if (length(lazy_tensor_features) > 1L) { first_row = self$task$data(self$task$row_ids[1L], cols = lazy_tensor_features) graphs = map(first_row, function(x) attr(x, "data_descriptor")$graph) diff --git a/man/PipeOpTorchTransformResize.Rd b/man/PipeOpTorchTransformResize.Rd deleted file mode 100644 index 56097db3..00000000 --- a/man/PipeOpTorchTransformResize.Rd +++ /dev/null @@ -1,68 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchLazyTransform.R -\name{PipeOpTorchTransformResize} -\alias{PipeOpTorchTransformResize} -\title{Resize an Object} -\description{ -See \code{\link[torchvision:transform_resize]{torchvision::transform_resize()}} for more information. -Creates a new instance of this \link[R6:R6Class]{R6} class. -} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{\link[mlr3torch:PipeOpTorchLazyTransform]{mlr3torch::PipeOpTorchLazyTransform}} -> \code{PipeOpTOrchTransformResize} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTOrchTransformResize-new}{\code{PipeOpTorchTransformResize$new()}} -\item \href{#method-PipeOpTOrchTransformResize-clone}{\code{PipeOpTorchTransformResize$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTOrchTransformResize-new}{}}} -\subsection{Method \code{new()}}{ -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchTransformResize$new(id = "transform_resize", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -The id for of the new object.} - -\item{\code{param_vals}}{(named \code{list()})\cr -Parameter values to be set after construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTOrchTransformResize-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchTransformResize$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_module.Rd b/man/mlr_pipeops_module.Rd index 52e3a8d9..4a16df29 100644 --- a/man/mlr_pipeops_module.Rd +++ b/man/mlr_pipeops_module.Rd @@ -157,8 +157,8 @@ Creates a new instance of this \link[R6:R6Class]{R6} class. \item{\code{id}}{(\code{character(1)})\cr The id for of the new object.} -\item{\code{module}}{(\code{\link{nn_module}})\cr -The torch module that is being wrapped.} +\item{\code{module}}{(\code{\link{nn_module}} or \verb{function()})\cr +The torch module or function that is being wrapped.} \item{\code{inname}}{(\code{character()})\cr The names of the input channels.} diff --git a/man/mlr_pipeops_torch.Rd b/man/mlr_pipeops_torch.Rd index 26386db0..a56184d5 100644 --- a/man/mlr_pipeops_torch.Rd +++ b/man/mlr_pipeops_torch.Rd @@ -292,8 +292,7 @@ Creates a new instance of this \link[R6:R6Class]{R6} class. inname = "input", outname = "output", packages = "torch", - tags = NULL, - variant_types = FALSE + tags = NULL )}\if{html}{\out{}} } diff --git a/man/mlr_pipeops_torch_lazy_trafo.Rd b/man/mlr_pipeops_torch_lazy_trafo.Rd new file mode 100644 index 00000000..f5c71177 --- /dev/null +++ b/man/mlr_pipeops_torch_lazy_trafo.Rd @@ -0,0 +1,151 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchLazyTrafo.R +\name{mlr_pipeops_torch_lazy_trafo} +\alias{mlr_pipeops_torch_lazy_trafo} +\alias{PipeOpTorchLazyTrafo} +\title{Base Class for Lazy Transformations} +\description{ +This \code{PipeOp} represents simple preprocessing transformations of torch tensors. +These can be used in two situations: +\enumerate{ +\item To preprocess a task, which works analogous to standard preprocessing PipeOps like \code{\link{PipeOpPCA}}. +Because the \code{\link[=lazy_tensor]{lazy_tensor()}} does not make any assumptions on how the data is stored, the transformation is +applied lazily, i.e. when \code{\link[=materialize]{materialize()}} is called. +During trainig of a learner, this transformation will be a applied during data-loading on the CPU. +\item To add a preprocessing step in an \code{\link[=nn_graph]{nn_graph()}} that is being built up in a \code{\link{ModelDescriptor}}. +In this case, the transformation is applied during the forward pass of the model, i.e. the tensor is then +also on the specified device. +} + +Currently the \code{PipeOp} must have exactly one inut and one output. +} +\section{Inheriting}{ + +You need to: +\itemize{ +\item Initialize the \code{fn} argument. This function should take one torch tensor as input and return a torch tensor. +Additional parameters that are passed to the function can be specified via the parameter set. +This function needs to be a simple, stateless function, see section \emph{Internals} for more information. +\item In case the transformation changes the tensor shape you must provide a private \code{.shapes_out()} method like +for \code{\link{PipeOpTorch}}. +} +} + +\section{Input and Output Channels}{ + +During \emph{training}, all inputs and outputs are of class \code{\link{Task}} or \code{\link{ModelDescriptor}}. +During \emph{prediction}, all inputs and outputs are of class \code{\link{Task}} or \code{\link{ModelDescriptor}}. +} + +\section{State}{ + +The state is the value calculated by the public method \code{shapes_out()}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{augment} :: \code{logical(1)}\cr +This parameter is only present when the \code{PipeOp} does not modify the input shape. +Whether the transformation is applied only during training (\code{TRUE}) or also during prediction (also includes +validation; \code{FALSE}). +This parameter is initalized to \code{FALSE}. +} + +Additional parameters can be specified by the class. +} + +\section{Internals}{ + + +Applied to a \strong{Task}: + +When this PipeOp is used for preprocessing, it creates a \code{\link{PipeOpModule}} from the function \code{fn} (additionally +passing the \code{param_vals} if there are any) and then adds it to the preprocessing graph that is part of the +\code{\link{DataDescriptor}} contained in the \code{\link{lazy_tensor}} column that is being preprocessed. +When the outpuf of this pipeop is then preprocessed by a different \code{PipeOpTorchLazyTrafo} a deep clone of the +preprocessing graph is done. However, this deep clone does not clone the environment of the +function or its attributes in case they have a state (as e.g. in \code{\link[=nn_module]{nn_module()}}s). +When setting the parameter \code{augment} this meanst that the preprcessing + +Applied to a \strong{ModelDescriptor} +} + +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchLazyTrafo} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchLazyTrafo-new}{\code{PipeOpTorchLazyTrafo$new()}} +\item \href{#method-PipeOpTorchLazyTrafo-clone}{\code{PipeOpTorchLazyTrafo$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchLazyTrafo-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchLazyTrafo$new( + fn, + id = "lazy_trafo", + param_vals = list(), + param_set = ps(), + packages = character(0) +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{fn}}{(\verb{function()})\cr +A function that will be applied to a (lazy) tensor. +Additional arguments can be passed as parameters. +During actual preprocessing the (lazy) tensor will be passed by position. +The transformation is always applied to a whole batch of tensors, i.e. the first dimension is the batch dimension.} + +\item{\code{id}}{(\code{character(1)})\cr +The id for of the new object.} + +\item{\code{param_vals}}{(named \code{list()})\cr +Parameter values to be set after construction.} + +\item{\code{param_set}}{(\code{paradox::ParamSet})\cr +The parameter set.} + +\item{\code{packages}}{(\code{character()})\cr +The packages the function depends on.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchLazyTrafo-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchLazyTrafo$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_torch_lazy_transform.Rd b/man/mlr_pipeops_torch_lazy_transform.Rd deleted file mode 100644 index 66da478c..00000000 --- a/man/mlr_pipeops_torch_lazy_transform.Rd +++ /dev/null @@ -1,120 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchLazyTransform.R -\name{mlr_pipeops_torch_lazy_transform} -\alias{mlr_pipeops_torch_lazy_transform} -\alias{PipeOpTorchLazyTransform} -\title{Base Class for Lazy Transformations} -\description{ -This is the base class for lazy tensor transformations. -These can either be used as preprocessing for \code{\link{lazy_tensor}} objects or as part of the -graph contained in the \code{\link{ModelDescriptor}}. -Currently the \code{PipeOp} must have exactly one inut and one output. -} -\section{Inheriting}{ - -You need to: -\itemize{ -\item Either provide a function as argument \code{fn} or overwrite the private \code{.make_module()} method. -See \code{\link{PipeOpTorch}} for how to do this. -\item In case the transformation changes the tensor shapes you must provide a private \code{.shapes_out()} method like -for \code{\link{PipeOpTorch}}. It can be assumed that the first dimension is \code{NA}, i.e. the batch dimension. -} - -Depending on the data-loader, this function is either applied individually to each tensor from a batch and then -concatenated, or to the whole batch at once and should return the same result in both cases. -} - -\section{Input and Output Channels}{ - -During \emph{training}, all inputs and outputs are of class \code{\link{Task}} or \code{\link{ModelDescriptor}}. -During \emph{prediction}, all inputs and outputs are of class \code{\link{Task}} or \code{\link{ModelDescriptor}}. -} - -\section{State}{ - -The state is the value calculated by the public method \code{shapes_out()}. -} - -\section{Parameters}{ - -The \code{\link[paradox:ParamSet]{ParamSet}} is specified by the child class inheriting from \code{\link{PipeOpTorchLazyTransform}}. -} - -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchLazyTransform} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchLazyTransform-new}{\code{PipeOpTorchLazyTransform$new()}} -\item \href{#method-PipeOpTorchLazyTransform-clone}{\code{PipeOpTorchLazyTransform$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchLazyTransform-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchLazyTransform$new( - fn, - id = "lazy_transform", - param_vals = list(), - param_set = ps(), - packages = character(0) -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{fn}}{(\verb{function()})\cr -A function that will be applied to a (lazy) tensor. -Additional arguments can be passed as parameters. -During actual preprocessing the (lazy) tensor will be passed by position.} - -\item{\code{id}}{(\code{character(1)})\cr -The id for of the new object.} - -\item{\code{param_vals}}{(named \code{list()})\cr -Parameter values to be set after construction.} - -\item{\code{param_set}}{(\code{paradox::ParamSet})\cr -The parameter set.} - -\item{\code{packages}}{(\code{character()})\cr -The packages the function depends on. -If \code{fn} is from a namespace and no value is provided the namespace is automatically set.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchLazyTransform-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchLazyTransform$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/preproc_and_lazy.Rd b/man/preproc_and_lazy.Rd new file mode 100644 index 00000000..8fbaad59 --- /dev/null +++ b/man/preproc_and_lazy.Rd @@ -0,0 +1,9 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/register_lazy.R +\name{preproc_and_lazy} +\alias{preproc_and_lazy} +\alias{PipeOpTaskPreprocLazyResize} +\title{Lazy Preprocessing and Transformations} +\description{ +Lazy Preprocessing and Transformations +} diff --git a/tests/testthat/helper_autotest.R b/tests/testthat/helper_autotest.R index e5c65832..55736bd2 100644 --- a/tests/testthat/helper_autotest.R +++ b/tests/testthat/helper_autotest.R @@ -303,3 +303,8 @@ autotest_torch_callback = function(torch_callback, check_man = TRUE) { cb_trained$ctx = "placeholder" expect_error(cb_trained$clone(deep = TRUE), "must never be cloned unless") } + +autotest_pipeop_torch_preprocess = function() { + # TODO: + # a) Check that all parameters but augment have tags train and predict (this should hold in basically all cases) +} diff --git a/tests/testthat/test_PipeOpTorchLazyTransform.R b/tests/testthat/test_PipeOpTorchLazyTransform.R index 0260eba1..ec49e557 100644 --- a/tests/testthat/test_PipeOpTorchLazyTransform.R +++ b/tests/testthat/test_PipeOpTorchLazyTransform.R @@ -1,3 +1,27 @@ +test_that("PipeOpTorchLazyTransform basic checks", { + trafo = function(x) torchvision::transform_resize(x, c(10, 10)) + po_lt = po("lazy_transform", trafo, packages = "R6") + expect_pipeop(po_lt) + expect_true("R6" %in% po_lt$packages) + + expect_error( + po("lazy_transform", function(x) torchvision::transform_resize(x, c(10, 10)), param_set = ps(augment = p_lgl())) + ) + + taskin = nano_mnist() + + taskout = po_lt$train(list(taskin))[[1L]] + + expect_permutation(taskin$feature_names, taskout$feature_names) + + # transformation is applied as we expect it + expect_true(torch_equal( + trafo(materialize(taskin$data(cols = "image")[[1L]])), + materialize(taskout$data(cols = "image")[[1L]]) + )) + +}) + test_that("PipeOpTorchLazyTransform works for preprocessing", { task = nano_mnist() po_resize = po("transform_resize", size = c(10, 10)) @@ -22,3 +46,5 @@ test_that("PipeOpTorchLazyTransform works in Graph", { graph$train(task)[[1L]] }) + +test_that("PipeOpTorchLazyTransform works with") diff --git a/tests/testthat/test_PipeOpTorchPreprocess.R b/tests/testthat/test_PipeOpTorchPreprocess.R new file mode 100644 index 00000000..d8e61cdb --- /dev/null +++ b/tests/testthat/test_PipeOpTorchPreprocess.R @@ -0,0 +1,4 @@ +test_that("PipeOpTorchPreprocess works", { + po + +}) diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index 19e83e91..7b88df6a 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -302,6 +302,9 @@ test_that("task_dataset works with multiple lazy_tensor columns", { po("transform_resize_2", size = c(15, 15)) ) - graph$train(task) + # What to do next: + # Test that PipeOpTorchLazyTensor works as we want, i.e. all the 8 cases (train-predict, preproc-graph, augment) + + graph$train(task) }) From ce54f2737311bc34f5301a98d917af4d138ea75e Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 13 Oct 2023 13:47:08 +0200 Subject: [PATCH 05/90] add test --- tests/testthat/test_lazy_tensor.R | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index c2a66794..f29fe569 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -17,6 +17,8 @@ test_that("lazy_tensor works", { expect_class(lt1_empty, "lazy_tensor") lt1_empty[1] = lt1[1] + + expect_class(materialize(lazy_tensor()), "torch_tensor") }) test_that("transform_lazy_tensor works", { From e29f6b62f5ee4035faf06385d3119a4c74879ccd Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 17 Oct 2023 17:02:28 +0200 Subject: [PATCH 06/90] WIP ... --- DESCRIPTION | 7 +- NAMESPACE | 9 +- R/PipeOpTaskPreprocTorch.R | 273 ++++++++++++++++++ R/PipeOpTorch.R | 10 +- R/PipeOpTorchLazyPreproc.R | 87 ------ ...eOpTorchLazyTrafo.R => PipeOpTorchTrafo.R} | 15 +- R/lazy_tensor.R | 63 +++- R/preproc_and_trafo.R | 41 +++ R/register_lazy.R | 55 +--- man/mlr_pipeops_torch.Rd | 2 +- ...zy_trafo.Rd => mlr_pipeops_torch_trafo.Rd} | 30 +- man/preproc_and_lazy.Rd | 9 +- man/transform_lazy_tensor.Rd | 50 ++++ tests/testthat/helper_autotest.R | 17 ++ tests/testthat/test_PipeOpTaskPreprocTorch.R | 39 +++ .../testthat/test_PipeOpTorchLazyTransform.R | 14 +- tests/testthat/test_PipeOpTorchPreprocess.R | 4 - tests/testthat/test_preproc_and_trafo.R | 1 + tests/testthat/test_task_dataset.R | 6 +- 19 files changed, 543 insertions(+), 189 deletions(-) create mode 100644 R/PipeOpTaskPreprocTorch.R delete mode 100644 R/PipeOpTorchLazyPreproc.R rename R/{PipeOpTorchLazyTrafo.R => PipeOpTorchTrafo.R} (93%) create mode 100644 R/preproc_and_trafo.R rename man/{mlr_pipeops_torch_lazy_trafo.Rd => mlr_pipeops_torch_trafo.Rd} (87%) create mode 100644 man/transform_lazy_tensor.Rd create mode 100644 tests/testthat/test_PipeOpTaskPreprocTorch.R delete mode 100644 tests/testthat/test_PipeOpTorchPreprocess.R create mode 100644 tests/testthat/test_preproc_and_trafo.R diff --git a/DESCRIPTION b/DESCRIPTION index e5482f58..7815829a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -93,6 +93,7 @@ Collate: 'ModelDescriptor.R' 'PipeOpModule.R' 'PipeOpTorch.R' + 'PipeOpTaskPreprocTorch.R' 'PipeOpTorchActivation.R' 'PipeOpTorchAvgPool.R' 'PipeOpTorchBatchNorm.R' @@ -103,8 +104,6 @@ Collate: 'PipeOpTorchHead.R' 'PipeOpTorchIngress.R' 'PipeOpTorchLayerNorm.R' - 'PipeOpTorchLazyPreproc.R' - 'PipeOpTorchLazyTrafo.R' 'PipeOpTorchLinear.R' 'TorchLoss.R' 'PipeOpTorchLoss.R' @@ -114,6 +113,7 @@ Collate: 'PipeOpTorchOptimizer.R' 'PipeOpTorchReshape.R' 'PipeOpTorchSoftmax.R' + 'PipeOpTorchTrafo.R' 'ResamplingRowRoles.R' 'TaskClassif_mnist.R' 'TaskClassif_tiny_imagenet.R' @@ -128,8 +128,9 @@ Collate: 'merge_graphs.R' 'nn_graph.R' 'paramset_torchlearner.R' - 'rd_info.R' 'register_lazy.R' + 'preproc_and_trafo.R' + 'rd_info.R' 'reset_last_layer.R' 'task_dataset.R' 'utils.R' diff --git a/NAMESPACE b/NAMESPACE index 7c9443b9..ef9bb3b0 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,6 @@ # Generated by roxygen2: do not edit by hand +S3method("$",lazy_tensor) S3method("[",imageuri) S3method("[",lazy_tensor) S3method("[<-",imageuri) @@ -12,6 +13,7 @@ S3method(as_imageuri,character) S3method(as_imageuri,imageuri) S3method(as_lazy_tensor,DataDescriptor) S3method(as_lazy_tensor,dataset) +S3method(as_lazy_tensor,numeric) S3method(as_lazy_tensor,torch_tensor) S3method(as_torch_callback,R6ClassGenerator) S3method(as_torch_callback,TorchCallback) @@ -64,7 +66,7 @@ export(LearnerTorchMLP) export(LearnerTorchModel) export(ModelDescriptor) export(PipeOpModule) -export(PipeOpTaskPreprocLazy) +export(PipeOpTaskPreprocTorch) export(PipeOpTorch) export(PipeOpTorchAvgPool1D) export(PipeOpTorchAvgPool2D) @@ -95,7 +97,6 @@ export(PipeOpTorchIngressImage) export(PipeOpTorchIngressLazyTensor) export(PipeOpTorchIngressNumeric) export(PipeOpTorchLayerNorm) -export(PipeOpTorchLazyTrafo) export(PipeOpTorchLeakyReLU) export(PipeOpTorchLinear) export(PipeOpTorchLogSigmoid) @@ -126,6 +127,7 @@ export(PipeOpTorchSqueeze) export(PipeOpTorchTanh) export(PipeOpTorchTanhShrink) export(PipeOpTorchThreshold) +export(PipeOpTorchTrafo) export(PipeOpTorchUnsqueeze) export(ResamplingRowRoles) export(TorchCallback) @@ -167,6 +169,9 @@ export(t_opt) export(t_opts) export(task_dataset) export(torch_callback) +export(transform_lazy_tensor) +exportPattern("^PipeOpTaskPreprocTorch") +exportPattern("^PipeOpTorchTrafo") import(checkmate) import(data.table) import(mlr3) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R new file mode 100644 index 00000000..b5f0fafb --- /dev/null +++ b/R/PipeOpTaskPreprocTorch.R @@ -0,0 +1,273 @@ +#' @Base Class for Torch Preprocessing +#' @name mlr_pipeops_task_preproc_torch +#' +#' @description +#' This `PipeOp` can be used to preprocess (one or more) [`lazy_tensor`] columns contained in an [`mlr3::Task`] +#' using the same preprocessing function. +#' The function that is applied is specified as construction argument `fn` and additional arguments to this +#' function can be defined through the `PipeOp`'s parameter set. +#' +#' @section Inheriting: +#' In addition to specifying the parameters `fn`, `packages` and `param_set` during construction you must also overwrite +#' the private `$.shapes_out()` method in case the preprocessing function changes the shape of the tensor. +#' See the description of [`PipeOpTorch`] how to implement this method. +#' +#' @param fn (`function`)\cr +#' The preprocessing function. +#' @param packages (`character()`)\cr +#' The packages the preprocessing function depends on. +#' @param param_set ([`ParamSet`])\cr +#' In case the function `fn` takes additional parameter besides a [`torch_tensor()`] they can be +#' specfied as parameters. Pay attention to set the correct `tags` for the parameters: if tag `"train"` is present, +#' the preprocessing is applied during training and if tag `"predict"` is present, the preprocessing is applied +#' during prediction (if `augment` is set to `FALSE`). +#' +#' @section Input and Output Channels: +#' See [`PipeOpTaskPreproc`]. +#' Note that the `PipeOp` currently expects exactly one [`lazy_tensor`] column. +#' @section State +#' See [`PipeOpTaskPreproc`]. +#' @section Parameters: +#' In addition to the parameters inherited from [`PipeOpTaskPreproc`] as well as those specified during construction +#' as the argument `param_set` there is: +#' +#' * `augment` :: `logical(1)`\cr +#' Whether the to apply the preprocessing only during training (`TRUE`) or also during prediction (`FALSE`). +#' This parameter is initialized to `FALSE`. +#' +#' @section Internals: +#' +#' A [`PipeOpModule`] with one input and one output channel is created. +#' The pipeop simply applies the function `fn` to the input tensor while additionally +#' passing the paramter values (minus `augment` and `affect_columns`) to `fn`. +#' Then [`transform_lazy_tensor`] is called with the created [`PipeOpModule`] and the shapes obtained from the +#' `$shapes_out()` method of this `PipeOp`. +#' +#' @include PipeOpTorch.R +#' @export +#' @examples +if (FALSE) { + PipeOpPreprocTorchPoly = R6::R6Class("PipeOpPreprocTorchPoly", + inherit = PipeOpTaskPreprocTorch, + public = list( + initialize = function(id = "preproc_poly", param_vals = list()) { + param_set = paradox::ps( + n_degree = paradox::p_int(lower = 1L, tags = c("train", "predict", "required")) + ) + param_set$set_values( + n_degree = 1L + ) + fn = mlr3misc::crate(function(x, n_degree) { + torch::torch_cat( + lapply(seq_len(n_degree), function(d) torch_pow(x, d)), + dim = 2L + ) + }) + + super$initialize( + fn = fn, + id = id, + packages = character(0), + param_vals = param_vals, + param_set = param_set + ) + } + ), + private = list( + .shapes_out = function(shapes_in, param_vals, task) { + # shapes_in is a list of length 1 containing the shapes + checkmate::assert_true(length(shapes_in[[1L]]) == 2L) + if (shapes_in[[1L]][2L] != 1L) { + stop("Input shape must be (NA, 1)") + } + list(c(NA, param_vals$n_degree)) + } + ) + ) + + po_poly = PipeOpPreprocTorchPoly$new( + param_vals = list(n_degree = 2L) + ) + + po_poly$shapes_out(c(NA, 1L)) + + d = data.table( + x1 = as_lazy_tensor(rnorm(10)), + x2 = as_lazy_tensor(rnorm(10)), + y = rnorm(10) + ) + + task = as_task_regr(d, target = "y") + + po_pol + + po_preproc = po("preproc_torch", + # use mlr3misc::crate to get rid of unnecessary environment baggage + fn = mlr3misc::crate(function(x, a) x + a), + param_set = ps(a = p_int(tags = c("train", "predict", "required"))) + ) + + po_preproc$param_set$set_values( + a = 100 + ) + + taskout_train = po_preproc$train(list(task))[[1L]] + + materialize(taskout_train$data(cols = c("x1", "x2"))) + +} +PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", + inherit = PipeOpTaskPreproc, + public = list( + initialize = function(fn, id = "preproc_torch", param_vals = list(), param_set = ps(), packages = character(0)) { + private$.fn = assert_function(fn, null.ok = FALSE) + + if ("augment" %in% param_set$ids()) { + stopf("Parameter name 'augment' is reserved and cannot be used.") + } + if (is.null(private$.shapes_out)) { + param_set$add(ps( + augment = p_lgl(tags = c("predict", "required")) + )) + param_set$set_values(augment = FALSE) + } + + super$initialize( + id = id, + param_vals = param_vals, + param_set = param_set, + feature_types = "lazy_tensor" + ) + }, + #' @description + #' Calculates the output shape after applying the preprocessing step to a lazy tensor vector. + #' @param shapes_in (`list()` of `integer()` or `integer()`)\cr + #' The input input shape of the lazy tensor, which must either be a `list()` of length 1 containing the + #' shape of the lazy tensor (first dimension must be `NA` for the batch) or the shape itself. + #' @param task ([`Task`] or `NULL`)\cr + #' The task, which is very rarely used. + #' @return + #' A named `list()` containing the output shape. The name is the name of the output channel. + shapes_out = function(shapes_in, task = NULL) { + assert_r6(task, "Task", null.ok = TRUE) + if (is.numeric(shapes_in)) shapes_in = list(shapes_in) + if (identical(self$input$name, "...")) { + assert_list(shapes_in, min.len = 1, types = "numeric") + } else { + assert_list(shapes_in, len = nrow(self$input), types = "numeric") + } + + s = if (is.null(private$.shapes_out)) { + shapes_in + } else { + pv = self$param_set$get_values() + private$.shapes_out(shapes_in, pv, task = task) + } + + set_names(s, self$output$name) + } + ), + private = list( + .train_task = function(task) { + dt_columns = private$.select_cols(task) + cols = dt_columns + if (!length(cols)) { + self$state = list(dt_columns = dt_columns) + return(task) + } + dt = task$data(cols = cols) + + param_vals = self$param_set$get_values(tags = "train") + param_vals$affect_columns = NULL + + trafo = private$.fn + + fn = if (length(param_vals)) { + crate(function(x) { + invoke(.f = trafo, x, .args = param_vals) + }, param_vals, trafo, .parent = environment(trafo)) + } else { + trafo + } + + dt = private$.transform(dt, fn, task) + + self$state$dt_columns = dt_columns + task$select(setdiff(task$feature_names, cols))$cbind(dt) + }, + .predict_task = function(task) { + cols = self$state$dt_columns + if (!length(cols)) { + return(task) + } + dt = task$data(cols = cols) + param_vals = self$param_set$get_values(tags = "predict") + augment = param_vals$augment + param_vals$augment = NULL + + # augment can be NULL (in case the pipeopf changes the output shape and hence augmentation is not supported) + # or a logical(1) + fn = if (isTRUE(augment)) { + # We cannot simple add no module to the graph as we need to maintain the same graph-structure + # as during training + identity + } else { + trafo = private$.fn + crate(function(x) { + invoke(.f = trafo, x, .args = param_vals) + }, param_vals, trafo, .parent = environment(trafo)) + } + + dt = private$.transform(dt, fn, task) + task$select(setdiff(task$feature_names, cols))$cbind(dt) + }, + .transform = function(dt, fn, task) { + dt = map_dtc(dt, function(lt) { + # the ID of the `PipeOp` does not matter. + # By randomizing it we avoid ID clashes + + po_fn = PipeOpModule$new( + id = paste0(self$id, sample.int(.Machine$integer.max, 1)), + module = fn, + inname = self$input$name, + outname = self$output$name, + packages = self$packages + ) + shapes_out = self$shapes_out(lt$.pointer_shape, task) + transform_lazy_tensor(lt, po_fn, shapes_out[[1L]]) + }) + return(dt) + }, + .fn = NULL, + .additional_phash_input = function() { + list(self$param_set$ids(), private$.fn, self$packages) + } + ) +) + +pipeop_preproc_torch = function(fn, id, param_set = NULL) { + # TODO + + +# Where I was: +# PipeOpTaskPreprocTorch and PipeOpTorchTrafo: +# their shapes_out method should be slightly different, i.e. +# --> How to implement this? +# 1. In register_lazy I want to specify the shapes_out method only once. +# 2. PipeOpTorch expects list()s but ...TaskPreproc should probably input and output shape +# vectors +# +# Other thigns: + # I want to provide helper functions to create these pipeops for: + # * preproc + # * trafo + # * pipeop torch +# Other things: + # * autotest for trafo and preproc + # * implement some common trafos and preprocs + # + # + + +register_po("preproc_torch", PipeOpTaskPreprocTorch) + diff --git a/R/PipeOpTorch.R b/R/PipeOpTorch.R index ac431b9e..7d6dd703 100644 --- a/R/PipeOpTorch.R +++ b/R/PipeOpTorch.R @@ -279,7 +279,7 @@ PipeOpTorch = R6Class("PipeOpTorch", }, #' @description #' Calculates the output shapes for the given input shapes, parameters and task. - #' @param shapes_in (`list()` of `integer()` or `integer()`, task)\cr + #' @param shapes_in (`list()` of `integer()` or `integer()`)\cr #' The input input shapes, which must be in the same order as the input channel names of the `PipeOp`. #' If there is only one input channel, `shapes_in` can also contain the shapes for this input channel. #' @param task ([`Task`] or `NULL`)\cr @@ -300,7 +300,7 @@ PipeOpTorch = R6Class("PipeOpTorch", shapes_in } else { pv = self$param_set$get_values() - private$.shapes_out(shapes_in, pv, task = task, self$output$name) + private$.shapes_out(shapes_in, pv, task = task) } set_names(s, self$output$name) @@ -381,3 +381,9 @@ PipeOpTorch = R6Class("PipeOpTorch", } ) ) + +pipeop_torch = function(...) { + # TODO +} + + diff --git a/R/PipeOpTorchLazyPreproc.R b/R/PipeOpTorchLazyPreproc.R deleted file mode 100644 index 1bf7e583..00000000 --- a/R/PipeOpTorchLazyPreproc.R +++ /dev/null @@ -1,87 +0,0 @@ -#' @export -PipeOpTaskPreprocLazy = R6Class("PipeOpTaskPreprocLazy", - inherit = PipeOpTaskPreproc, - public = list( - initialize = function(fn, id = "lazy_preproc", param_vals = list(), param_set = ps(), packages = character(0)) { - private$.fn = assert_function(fn, null.ok = FALSE) - - if ("augment" %in% param_set$ids()) { - stopf("Parameter name 'augment' is reserved and cannot be used.") - } - if (is.null(private$.shapes_out)) { - param_set$add(ps( - augment = p_lgl(tags = c("predict", "required")) - )) - param_set$set_values(augment = FALSE) - } - - super$initialize( - id = id, - param_vals = param_vals, - feature_types = "lazy_tensor" - ) - } - ), - private = list( - .train_dt = function(dt, levels, target) { - if (ncol(dt) != 1L) { - # Check only during train as this will ensure it also holds during predict - stop("Can only use PipeOpTorchLazyTrafo on tasks with exactly one lazy tensor column.") - } - param_vals = self$param_set$get_values(tags = "train") - - trafo = private$.fn - - fn = if (length(param_vals)) { - crate(function(x) { - invoke(.f = trafo, x, .args = param_vals) - }, param_vals, trafo, .parent = topenv()) - } else { - trafo - } - - self$state = list() - - private$.transform_dt(dt, fn) - }, - .predict_dt = function(dt, levels) { - param_vals = self$param_set$get_values(tags = "predict") - augment = param_vals$augment - param_vals$augment = NULL - - # augment can be NULL (in case the pipeopf changes the output shape and hence augmentation is not supported) - # or a logical(1) - fn = if (isTRUE(augment)) { - identity - } else { - trafo = private$.fn - crate(function(x) { - invoke(.f = trafo, x, .args = param_vals) - }, param_vals, trafo, .parent = topenv()) - } - - private$.transform_dt(dt, fn) - }, - .transform_dt = function(dt, fn) { - po_fn = PipeOpModule$new( - id = self$id, - module = fn, - inname = self$input$name, - outname = self$output$name, - packages = self$packages - ) - - lt = dt[[1L]] - - shapes_in = attr(lt[[1L]], "data_descriptor")$.pointer_shape - - shapes_out = self$shapes_out(shapes_in, intask) - dt[[1L]] = transform_lazy_tensor(lt, po_fn, shapes_out[[1L]]) - return(dt) - }, - .fn = NULL, - .additional_phash_input = function() { - list(self$param_set$ids(), private$.fn, self$packages) - } - ) -) diff --git a/R/PipeOpTorchLazyTrafo.R b/R/PipeOpTorchTrafo.R similarity index 93% rename from R/PipeOpTorchLazyTrafo.R rename to R/PipeOpTorchTrafo.R index 5b6b7d57..35965d56 100644 --- a/R/PipeOpTorchLazyTrafo.R +++ b/R/PipeOpTorchTrafo.R @@ -1,5 +1,5 @@ #' @title Base Class for Lazy Transformations -#' @name mlr_pipeops_torch_lazy_trafo +#' @name mlr_pipeops_torch_trafo #' #' @description #' This `PipeOp` represents simple preprocessing transformations of torch tensors. @@ -45,7 +45,7 @@ #' When this PipeOp is used for preprocessing, it creates a [`PipeOpModule`] from the function `fn` (additionally #' passing the `param_vals` if there are any) and then adds it to the preprocessing graph that is part of the #' [`DataDescriptor`] contained in the [`lazy_tensor`] column that is being preprocessed. -#' When the outpuf of this pipeop is then preprocessed by a different `PipeOpTorchLazyTrafo` a deep clone of the +#' When the outpuf of this pipeop is then preprocessed by a different `PipeOpTorchTrafo` a deep clone of the #' preprocessing graph is done. However, this deep clone does not clone the environment of the #' function or its attributes in case they have a state (as e.g. in [`nn_module()`]s). #' When setting the parameter `augment` this meanst that the preprcessing @@ -67,11 +67,11 @@ #' The transformation is always applied to a whole batch of tensors, i.e. the first dimension is the batch dimension. #' #' @export -PipeOpTorchLazyTrafo = R6Class("PipeOpTorchLazyTrafo", +PipeOpTorchTrafo = R6Class("PipeOpTorchTrafo", inherit = PipeOpTorch, public = list( #' @description Creates a new instance of this [R6][R6::R6Class] class. - initialize = function(fn, id = "lazy_trafo", param_vals = list(), param_set = ps(), packages = character(0)) { + initialize = function(fn, id = "torch_trafo", param_vals = list(), param_set = ps(), packages = character(0)) { private$.fn = assert_function(fn, null.ok = FALSE) if ("augment" %in% param_set$ids()) { @@ -136,7 +136,10 @@ PipeOpTorchLazyTrafo = R6Class("PipeOpTorchLazyTrafo", ) ) -#' @include zzz.R -register_po("lazy_trafo", PipeOpTorchLazyTrafo) +pipeop_torch_trafo = function(fn, id, param_set = NULL) { + +} +#' @include zzz.R +register_po("torch_trafo", PipeOpTorchTrafo) diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index d733237a..0888418d 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -59,8 +59,16 @@ as_lazy_tensor.dataset = function(x, dataset_shapes, ids = NULL, ...) { # nolint lazy_tensor(dd, ids) } +#' @export +as_lazy_tensor.numeric = function(x) { # nolint + as_lazy_tensor(torch_tensor(x)) +} + #' @export as_lazy_tensor.torch_tensor = function(x) { # nolint + if (length(dim(x)) == 1L) { + x = x$unsqueeze(2) + } ds = dataset( initialize = function(x) { self$x = x @@ -72,7 +80,7 @@ as_lazy_tensor.torch_tensor = function(x) { # nolint dim(self$x)[1L] } )(x) - as_lazy_tensor(ds, dataset_shapes = list(x = c(NA, dim(x)))) + as_lazy_tensor(ds, dataset_shapes = list(x = c(NA, dim(x)[-1]))) } @@ -102,8 +110,8 @@ is_lazy_tensor = function(x) { #' @title Transform Lazy Tensor #' @description -#' Input must be PipeOpModule with exactly one input and one output -#' shape must be shape with NA in first dimension +#' transform a [`lazy_tensor`] vector by appending a preprocessing step. +#' #' @param lt ([`lazy_tensor`])\cr #' A lazy tensor vector. #' @param pipeop ([`PipeOpModule`])\cr @@ -111,22 +119,42 @@ is_lazy_tensor = function(x) { #' Must have one input and one output. #' @param shape (`integer()`)\cr #' The shape of the lazy tensor (without the batch dimension). -#' @param clone_graph (`logical(1)`)\cr -#' Whether to clone the graph from the data descriptor. -#' @noRd -transform_lazy_tensor = function(lt, pipeop, shape, clone_graph = TRUE) { +#' +#' @details +#' The following is done: +#' 1. A shallow copy of the [`lazy_tensor`]'s preprocessing `graph` is created. +#' 1. The provided `pipeop` is added to the (shallowly cloned) `graph` and connected to the current `.pointer` of the +#' [`DataDescriptor`]. +#' 1. The `.pointer` of the [`DataDescriptor`] is updated to point to the new output channel of the `pipeop`. +#' 1. The `.pointer_shape` of the [`DataDescriptor`] set to the provided `shape`. +#' 1. The `.hash` of the [`DataDescriptor`] is updated. +#' Input must be PipeOpModule with exactly one input and one output +#' shape must be shape with NA in first dimension +#' +#' @return [`lazy_tensor`] +#' @examples +#' lt = as_lazy_tensor(1:10) +#' add_five = po("module", module = function(x) x + 5) +#' lt_plus_five = transform_lazy_tensor(lt, add_five, c(NA, 1)) +#' torch_cat(list(materialize(lt), materialize(lt_plus_five)), dim = 2) +#' # graph is cloned +#' identical(lt$graph, lt_plus_five$graph) +#' lt$graph$edges +#' lt_plus_five$graph_edges +#' # pipeops are not cloned +#' identical(lt$graph$pipeops[[1]], lt_plus_five$graph[[1]]) +#' @export +transform_lazy_tensor = function(lt, pipeop, shape) { assert_lazy_tensor(lt) assert_class(pipeop, "PipeOpModule") assert_true(nrow(pipeop$input) == 1L) assert_true(nrow(pipeop$output) == 1L) assert_shape(shape) - assert_flag(clone_graph) data_descriptor = attr(lt, "data_descriptor") - if (clone_graph) { - data_descriptor$graph = data_descriptor$graph$clone(deep = TRUE) - } + data_descriptor$graph = data_descriptor$graph$clone(deep = FALSE) + data_descriptor$graph$edges = copy(data_descriptor$graph$edges) data_descriptor$graph$add_pipeop(pipeop$clone(deep = TRUE)) data_descriptor$graph$add_edge( @@ -142,3 +170,16 @@ transform_lazy_tensor = function(lt, pipeop, shape, clone_graph = TRUE) { new_lazy_tensor(data_descriptor, vec_data(lt)) } + +#' @export +`$.lazy_tensor` = function(x, name) { + if (name == "data_descriptor") { + return(attr(x, "data_descriptor")) + } + + x = attr(x, "data_descriptor")[[name]] + if (is.null(x)) { + stopf("Unknown field '%s'.", name) + } + return(x) +} diff --git a/R/preproc_and_trafo.R b/R/preproc_and_trafo.R new file mode 100644 index 00000000..add22bb4 --- /dev/null +++ b/R/preproc_and_trafo.R @@ -0,0 +1,41 @@ +#' @include register_lazy.R +NULL + +# Where I have left off: +# I split the class for the lazy tensor preprocessing / transformation into two clases +# I also decided to create the corresponding classes programmatically, otherwise we just have to write so much code +# there will be one or two (either one for both preproc and trafo or seperately) manual pages that document how to +# use the pipeops + a pointer to the parent class + a list with available pipeops +# This refactoring now needs to be done + the resulting pipeops than tested + +#' @rawNamespace exportPattern("^PipeOpTaskPreprocTorch") +#' @rawNamespace exportPattern("^PipeOpTorchTrafo") +NULL + +#' @title Lazy Preprocessing and Transformations +#' @name preproc_and_lazy +#' @section Available PipeOps: +#' The following +NULL + +#' @name PipeOpTaskPreprocTorchResize +#' @alias PipeOpTorchTrafoResize +#' @rdname preproc_and_lazy +register_lazy("resize", torchvision::transform_resize, + packages = "torchvision", + param_set = ps( + size = p_uty(tags = c("train", "required")), + interpolation = p_fct(levels = magick::filter_types(), special_vals = list(0L, 2L, 3L), + tags = "train", default = 2L + ) + ), + shapes_out = function(shapes_in, param_vals, task) { + size = param_vals$size + shape = shapes_in[[1L]] + assert_true(length(shape) > 2) + height = shape[[length(shape) - 1L]] + width = shape[[length(shape)]] + s = torchvision::transform_resize(torch_ones(c(1, height, width), device = "meta"), size = size)$shape[2:3] + list(c(shape[seq_len(length(shape) - 2L)], s)) + } +) diff --git a/R/register_lazy.R b/R/register_lazy.R index 2b8a9c17..5e04cc34 100644 --- a/R/register_lazy.R +++ b/R/register_lazy.R @@ -11,9 +11,11 @@ register_trafo = function(name, fn, param_set, shapes_out = NULL, packages, envi fn = fn ) }, param_set, fn, idname, packages, .parent = topenv()) + body(init_fun)[[2]][[4]] = param_set + attributes(init_fun) = NULL Class = R6Class(classname, - inherit = PipeOpTorchLazyTrafo, + inherit = PipeOpTorchTrafo, public = list( initialize = init_fun ), @@ -29,26 +31,29 @@ register_trafo = function(name, fn, param_set, shapes_out = NULL, packages, envi } register_preproc = function(name, fn, param_set, shapes_out, packages, envir) { - classname = paste0("PipeOpTaskPreprocLazy", capitalize(name)) + classname = paste0("PipeOpPreprocTorch", capitalize(name)) idname = paste0("preproc_", name) init_fun = crate(function(id = idname, param_vals = list()) { super$initialize( id = id, packages = packages, - param_set = param_set, + param_set = ps, param_vals = param_vals, fn = fn ) - }, param_set, fn, idname, packages, .parent = topenv()) + }, fn, packages, .parent = topenv()) + # param_set is already an expression + body(init_fun)[[2]][[4]] = param_set + attributes(init_fun) = NULL Class = R6Class(classname, - inherit = PipeOpTaskPreprocLazy, + inherit = PipeOpTaskPreprocTorch, public = list( initialize = init_fun ), private = list( - .shapes_out = shapes_out + .shapes_out = crate(function(...)) ) ) @@ -59,42 +64,10 @@ register_preproc = function(name, fn, param_set, shapes_out, packages, envir) { } -#' @include PipeOpTorchLazyTrafo.R PipeOpTorchLazyPreproc.R +#' @include PipeOpTaskPreprocTorch.R PipeOpTorchTrafo.R register_lazy = function(name, fn, param_set, shapes_out, packages, envir = parent.frame()) { - register_trafo(name, fn, param_set, shapes_out, packages, envir = envir) - register_preproc(name, fn, param_set, shapes_out, packages, envir = envir) + register_trafo(name, fn, substitute(param_set), shapes_out, packages, envir = envir) + register_preproc(name, fn, substitute(param_set), shapes_out, packages, envir = envir) return(NULL) } - -#' @title Lazy Preprocessing and Transformations -#' @name preproc_and_lazy -#' @section Available PipeOps: -#' The following -NULL - - -#' @name PipeOpTaskPreprocLazyResize -#' @alias PipeOpTorchLazyTrafoResize -#' @rdname preproc_and_lazy -register_lazy("resize", torchvision::transform_resize, - packages = "torchvision", - param_set = ps( - size = p_uty(tags = c("train", "required")), - interpolation = p_fct(levels = magick::filter_types(), special_vals = list(0L, 2L, 3L), - tags = "train", default = 2L - ) - ), - shapes_out = function(shapes_in, param_vals, task) { - size = param_vals$size - shape = shapes_in[[1L]] - assert_true(length(shape) > 2) - height = shape[[length(shape) - 1L]] - width = shape[[length(shape)]] - s = torchvision::transform_resize(torch_ones(c(1, height, width), device = "meta"), size = size)$shape[2:3] - list(c(shape[seq_len(length(shape) - 2L)], s)) - } -) - -#' @rawNamespace exportPattern("^PipeOpTaskPreprocLazy") -#' @rawNamespace exportPattern("^PipeOpTorchLazyTrafo") diff --git a/man/mlr_pipeops_torch.Rd b/man/mlr_pipeops_torch.Rd index a56184d5..a735c0e7 100644 --- a/man/mlr_pipeops_torch.Rd +++ b/man/mlr_pipeops_torch.Rd @@ -349,7 +349,7 @@ Calculates the output shapes for the given input shapes, parameters and task. \subsection{Arguments}{ \if{html}{\out{
}} \describe{ -\item{\code{shapes_in}}{(\code{list()} of \code{integer()} or \code{integer()}, task)\cr +\item{\code{shapes_in}}{(\code{list()} of \code{integer()} or \code{integer()})\cr The input input shapes, which must be in the same order as the input channel names of the \code{PipeOp}. If there is only one input channel, \code{shapes_in} can also contain the shapes for this input channel.} diff --git a/man/mlr_pipeops_torch_lazy_trafo.Rd b/man/mlr_pipeops_torch_trafo.Rd similarity index 87% rename from man/mlr_pipeops_torch_lazy_trafo.Rd rename to man/mlr_pipeops_torch_trafo.Rd index f5c71177..a2c12bdf 100644 --- a/man/mlr_pipeops_torch_lazy_trafo.Rd +++ b/man/mlr_pipeops_torch_trafo.Rd @@ -1,8 +1,8 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchLazyTrafo.R -\name{mlr_pipeops_torch_lazy_trafo} -\alias{mlr_pipeops_torch_lazy_trafo} -\alias{PipeOpTorchLazyTrafo} +% Please edit documentation in R/PipeOpTorchTrafo.R +\name{mlr_pipeops_torch_trafo} +\alias{mlr_pipeops_torch_trafo} +\alias{PipeOpTorchTrafo} \title{Base Class for Lazy Transformations} \description{ This \code{PipeOp} represents simple preprocessing transformations of torch tensors. @@ -63,7 +63,7 @@ Applied to a \strong{Task}: When this PipeOp is used for preprocessing, it creates a \code{\link{PipeOpModule}} from the function \code{fn} (additionally passing the \code{param_vals} if there are any) and then adds it to the preprocessing graph that is part of the \code{\link{DataDescriptor}} contained in the \code{\link{lazy_tensor}} column that is being preprocessed. -When the outpuf of this pipeop is then preprocessed by a different \code{PipeOpTorchLazyTrafo} a deep clone of the +When the outpuf of this pipeop is then preprocessed by a different \code{PipeOpTorchTrafo} a deep clone of the preprocessing graph is done. However, this deep clone does not clone the environment of the function or its attributes in case they have a state (as e.g. in \code{\link[=nn_module]{nn_module()}}s). When setting the parameter \code{augment} this meanst that the preprcessing @@ -72,13 +72,13 @@ Applied to a \strong{ModelDescriptor} } \section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchLazyTrafo} +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchTrafo} } \section{Methods}{ \subsection{Public methods}{ \itemize{ -\item \href{#method-PipeOpTorchLazyTrafo-new}{\code{PipeOpTorchLazyTrafo$new()}} -\item \href{#method-PipeOpTorchLazyTrafo-clone}{\code{PipeOpTorchLazyTrafo$clone()}} +\item \href{#method-PipeOpTorchTrafo-new}{\code{PipeOpTorchTrafo$new()}} +\item \href{#method-PipeOpTorchTrafo-clone}{\code{PipeOpTorchTrafo$clone()}} } } \if{html}{\out{ @@ -93,14 +93,14 @@ Applied to a \strong{ModelDescriptor} }} \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchLazyTrafo-new}{}}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchTrafo-new}{}}} \subsection{Method \code{new()}}{ Creates a new instance of this \link[R6:R6Class]{R6} class. \subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchLazyTrafo$new( +\if{html}{\out{
}}\preformatted{PipeOpTorchTrafo$new( fn, - id = "lazy_trafo", + id = "torch_trafo", param_vals = list(), param_set = ps(), packages = character(0) @@ -132,12 +132,12 @@ The packages the function depends on.} } } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchLazyTrafo-clone}{}}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchTrafo-clone}{}}} \subsection{Method \code{clone()}}{ The objects of this class are cloneable with this method. \subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchLazyTrafo$clone(deep = FALSE)}\if{html}{\out{
}} +\if{html}{\out{
}}\preformatted{PipeOpTorchTrafo$clone(deep = FALSE)}\if{html}{\out{
}} } \subsection{Arguments}{ diff --git a/man/preproc_and_lazy.Rd b/man/preproc_and_lazy.Rd index 8fbaad59..5822940b 100644 --- a/man/preproc_and_lazy.Rd +++ b/man/preproc_and_lazy.Rd @@ -1,9 +1,14 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/register_lazy.R +% Please edit documentation in R/preproc_and_trafo.R \name{preproc_and_lazy} \alias{preproc_and_lazy} -\alias{PipeOpTaskPreprocLazyResize} +\alias{PipeOpTaskPreprocTorchResize} \title{Lazy Preprocessing and Transformations} \description{ Lazy Preprocessing and Transformations } +\section{Available PipeOps}{ + +The following +} + diff --git a/man/transform_lazy_tensor.Rd b/man/transform_lazy_tensor.Rd new file mode 100644 index 00000000..5e6567fe --- /dev/null +++ b/man/transform_lazy_tensor.Rd @@ -0,0 +1,50 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lazy_tensor.R +\name{transform_lazy_tensor} +\alias{transform_lazy_tensor} +\title{Transform Lazy Tensor} +\usage{ +transform_lazy_tensor(lt, pipeop, shape) +} +\arguments{ +\item{lt}{(\code{\link{lazy_tensor}})\cr +A lazy tensor vector.} + +\item{pipeop}{(\code{\link{PipeOpModule}})\cr +The pipeop to be added to the preprocessing graph(s) of the lazy tensor. +Must have one input and one output.} + +\item{shape}{(\code{integer()})\cr +The shape of the lazy tensor (without the batch dimension).} +} +\value{ +\code{\link{lazy_tensor}} +} +\description{ +transform a \code{\link{lazy_tensor}} vector by appending a preprocessing step. +} +\details{ +The following is done: +\enumerate{ +\item A shallow copy of the \code{\link{lazy_tensor}}'s preprocessing \code{graph} is created. +\item The provided \code{pipeop} is added to the (shallowly cloned) \code{graph} and connected to the current \code{.pointer} of the +\code{\link{DataDescriptor}}. +\item The \code{.pointer} of the \code{\link{DataDescriptor}} is updated to point to the new output channel of the \code{pipeop}. +\item The \code{.pointer_shape} of the \code{\link{DataDescriptor}} set to the provided \code{shape}. +\item The \code{.hash} of the \code{\link{DataDescriptor}} is updated. +Input must be PipeOpModule with exactly one input and one output +shape must be shape with NA in first dimension +} +} +\examples{ +lt = as_lazy_tensor(1:10) +add_five = po("module", module = function(x) x + 5) +lt_plus_five = transform_lazy_tensor(lt, add_five, c(NA, 1)) +torch_cat(list(materialize(lt), materialize(lt_plus_five)), dim = 2) +# graph is cloned +identical(lt$graph, lt_plus_five$graph) +lt$graph$edges +lt_plus_five$graph_edges +# pipeops are not cloned +identical(lt$graph$pipeops[[1]], lt_plus_five$graph[[1]]) +} diff --git a/tests/testthat/helper_autotest.R b/tests/testthat/helper_autotest.R index 55736bd2..7f37f06f 100644 --- a/tests/testthat/helper_autotest.R +++ b/tests/testthat/helper_autotest.R @@ -308,3 +308,20 @@ autotest_pipeop_torch_preprocess = function() { # TODO: # a) Check that all parameters but augment have tags train and predict (this should hold in basically all cases) } + +autotest_preproc_and_trafo = function(obj) { + autotest_trafo(obj) + autotest_preproc(obj) +} + +autotest_trafo = function(obj) { + +} + +autotest_preproc = function(obj) { + expect_class(obj, "PipeOpTaskPreprocTorch") + + # TODO: Unless the test is disabled, check that all parameters have train and predict tag + + +} diff --git a/tests/testthat/test_PipeOpTaskPreprocTorch.R b/tests/testthat/test_PipeOpTaskPreprocTorch.R new file mode 100644 index 00000000..ac7aa5c7 --- /dev/null +++ b/tests/testthat/test_PipeOpTaskPreprocTorch.R @@ -0,0 +1,39 @@ +test_that("Correct errors", { + + +}) + +test_that("PipeOpTaskPreprocTorch works with one lazy tensor column", { + d = data.table( + y = 1:10, + x = as_lazy_tensor(rnorm(10)) + ) + + taskin = as_task_regr(d, target = "y") + + po_test = po("preproc_torch", fn = crate(function(x, a) x + a), param_set = ps(a = p_int(tags = c("train", ""))), a = -10) + + taskout_train = po_test$train(list(taskin))[[1L]] + taskout_pred = po_test$predict(list(taskin))[[1L]] + + po_test$param_set$set_values(augment = TRUE) + taskout_pred_aug = po_test$predict(list(taskin))[[1L]] + + expect_true(length(taskin$data(cols = "x")[[1]]$graph$pipeops) == 1L) + + expect_true(length(taskout_pred$data(cols = "x")[[1]]$graph$pipeops) == 2L) + expect_true(length(taskout_pred_aug$data(cols = "x")[[1]]$graph$pipeops) == 2L) + + expect_true(identical(taskout_pred_aug$data(cols = "x")[[1]]$graph$pipeops[[2]]$module, identity)) + expect_false(identical(taskout_pred$data(cols = "x")[[1]]$graph$pipeops[[2]]$module, identity)) + + taskout_pred$data(cols = "x")[[1]]$graph + + expect_equal( + as_array(materialize(taskin$data(cols = "x")[[1L]])), + as_array(materialize(taskout_train$data(cols = "x")[[1L]]) + 10), + tolerance = 1e-5 + ) +}) + +test_that("PipeOpTaskPreprocTorch works with multiple lazy tensor columns") diff --git a/tests/testthat/test_PipeOpTorchLazyTransform.R b/tests/testthat/test_PipeOpTorchLazyTransform.R index ec49e557..5f4e3cc5 100644 --- a/tests/testthat/test_PipeOpTorchLazyTransform.R +++ b/tests/testthat/test_PipeOpTorchLazyTransform.R @@ -1,11 +1,11 @@ test_that("PipeOpTorchLazyTransform basic checks", { trafo = function(x) torchvision::transform_resize(x, c(10, 10)) - po_lt = po("lazy_transform", trafo, packages = "R6") + po_lt = po("trafo_lazy", trafo, packages = "R6") expect_pipeop(po_lt) expect_true("R6" %in% po_lt$packages) expect_error( - po("lazy_transform", function(x) torchvision::transform_resize(x, c(10, 10)), param_set = ps(augment = p_lgl())) + po("trafo_lazy", function(x) torchvision::transform_resize(x, c(10, 10)), param_set = ps(augment = p_lgl())) ) taskin = nano_mnist() @@ -22,16 +22,6 @@ test_that("PipeOpTorchLazyTransform basic checks", { }) -test_that("PipeOpTorchLazyTransform works for preprocessing", { - task = nano_mnist() - po_resize = po("transform_resize", size = c(10, 10)) - - task1 = po_resize$train(list(task))[[1L]] - - lt = task1$data(cols = "image") - -}) - test_that("PipeOpTorchLazyTransform works in Graph", { task = nano_mnist() diff --git a/tests/testthat/test_PipeOpTorchPreprocess.R b/tests/testthat/test_PipeOpTorchPreprocess.R deleted file mode 100644 index d8e61cdb..00000000 --- a/tests/testthat/test_PipeOpTorchPreprocess.R +++ /dev/null @@ -1,4 +0,0 @@ -test_that("PipeOpTorchPreprocess works", { - po - -}) diff --git a/tests/testthat/test_preproc_and_trafo.R b/tests/testthat/test_preproc_and_trafo.R new file mode 100644 index 00000000..300d797e --- /dev/null +++ b/tests/testthat/test_preproc_and_trafo.R @@ -0,0 +1 @@ +test_that("resize works") diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index 7b88df6a..5be4b5a9 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -296,10 +296,10 @@ test_that("dataset_img works", { test_that("task_dataset works with multiple lazy_tensor columns", { task = nano_mnist() graph = po("torch_ingress_ltnsr") %>>% - po("transform_resize", size = c(40, 40)) %>>% + po("trafo_resize", size = c(40, 40)) %>>% list( - po("transform_resize_1", size = c(30, 30)), - po("transform_resize_2", size = c(15, 15)) + po("trafo_resize_1", size = c(30, 30)), + po("trafo_resize_2", size = c(15, 15)) ) From d7df8628337a4c38856550ea8dff305e853aaae5 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 18 Oct 2023 17:16:05 +0200 Subject: [PATCH 07/90] task preprocessing is working --- DESCRIPTION | 4 +- NAMESPACE | 5 +- R/PipeOpTaskPreprocTorch.R | 332 +++++++++++-------- R/PipeOpTorch.R | 11 +- R/materialize.R | 5 +- R/preproc_and_trafo.R | 41 --- R/preprocess.R | 34 ++ R/register_lazy.R | 73 ---- R/task_dataset.R | 3 +- R/utils.R | 8 +- R/zzz.R | 2 +- R/PipeOpTorchTrafo.R => attic/Trafo.R | 36 +- man/materialize_internal.Rd | 51 +++ man/mlr_pipeops_task_preproc_torch.Rd | 284 ++++++++++++++++ man/mlr_pipeops_torch.Rd | 7 +- man/mlr_pipeops_torch_trafo.Rd | 151 --------- man/pipeop_preproc_torch.Rd | 50 +++ man/preproc_and_lazy.Rd | 14 - man/preprocessing_pipeops.Rd | 19 ++ tests/testthat/helper_expectations.R | 5 + tests/testthat/test_PipeOpTaskPreprocTorch.R | 126 ++++++- 21 files changed, 815 insertions(+), 446 deletions(-) delete mode 100644 R/preproc_and_trafo.R create mode 100644 R/preprocess.R delete mode 100644 R/register_lazy.R rename R/PipeOpTorchTrafo.R => attic/Trafo.R (86%) create mode 100644 man/materialize_internal.Rd create mode 100644 man/mlr_pipeops_task_preproc_torch.Rd delete mode 100644 man/mlr_pipeops_torch_trafo.Rd create mode 100644 man/pipeop_preproc_torch.Rd delete mode 100644 man/preproc_and_lazy.Rd create mode 100644 man/preprocessing_pipeops.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 7815829a..8e7ddf68 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -113,7 +113,6 @@ Collate: 'PipeOpTorchOptimizer.R' 'PipeOpTorchReshape.R' 'PipeOpTorchSoftmax.R' - 'PipeOpTorchTrafo.R' 'ResamplingRowRoles.R' 'TaskClassif_mnist.R' 'TaskClassif_tiny_imagenet.R' @@ -128,8 +127,7 @@ Collate: 'merge_graphs.R' 'nn_graph.R' 'paramset_torchlearner.R' - 'register_lazy.R' - 'preproc_and_trafo.R' + 'preprocess.R' 'rd_info.R' 'reset_last_layer.R' 'task_dataset.R' diff --git a/NAMESPACE b/NAMESPACE index ef9bb3b0..81f5c6bb 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -127,7 +127,6 @@ export(PipeOpTorchSqueeze) export(PipeOpTorchTanh) export(PipeOpTorchTanhShrink) export(PipeOpTorchThreshold) -export(PipeOpTorchTrafo) export(PipeOpTorchUnsqueeze) export(ResamplingRowRoles) export(TorchCallback) @@ -160,6 +159,7 @@ export(nn_merge_sum) export(nn_reshape) export(nn_squeeze) export(nn_unsqueeze) +export(pipeop_preproc_torch) export(reset_last_layer) export(t_clbk) export(t_clbks) @@ -170,8 +170,7 @@ export(t_opts) export(task_dataset) export(torch_callback) export(transform_lazy_tensor) -exportPattern("^PipeOpTaskPreprocTorch") -exportPattern("^PipeOpTorchTrafo") +exportPattern("^PipeOpPreproc") import(checkmate) import(data.table) import(mlr3) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index b5f0fafb..5dd6c769 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -2,15 +2,37 @@ #' @name mlr_pipeops_task_preproc_torch #' #' @description -#' This `PipeOp` can be used to preprocess (one or more) [`lazy_tensor`] columns contained in an [`mlr3::Task`] -#' using the same preprocessing function. +#' This `PipeOp` can be used to preprocess (one or more) [`lazy_tensor`] columns contained in an [`mlr3::Task`]. #' The function that is applied is specified as construction argument `fn` and additional arguments to this #' function can be defined through the `PipeOp`'s parameter set. +#' The preprocessing is either done per-column in which case the number lazy tensor output columns is equivalent +#' to the number of lazy tensor input columns. +#' It is also possible to implement preprocessing that is applied to all lazy tensor columns at once and returns +#' one or more (not necessarily the same number) of lazy tensor columns. #' #' @section Inheriting: -#' In addition to specifying the parameters `fn`, `packages` and `param_set` during construction you must also overwrite -#' the private `$.shapes_out()` method in case the preprocessing function changes the shape of the tensor. -#' See the description of [`PipeOpTorch`] how to implement this method. +#' In addition to specifying the parameters `fn`, `packages` and `param_set` during construction you can also overwrite +#' the private `.shapes_out()` or `.tranform()` methods: +#' * `.shapes_out(shapes_in, param_vals, task)`\cr +#' (`list()`, `list(), `Task` or `NULL`) -> `list()`\cr +#' This private method calculates the output shapes of the lazy tensor columns that are created from applying +#' the preprocessing. +#' +#' Also see the documentation of [`PipeOpTorch`] how to implement this method. +#' +#' In case the construction argument `per_column` is `TRUE`, this private method only has the responsibility +#' to caclculate the output shapes for one input column, i.e. the input `shapes_in` can be assumed to have +#' exactly one shape vector for which it must calculate the output shapes. +#' +#' * `.transform(dt, task, param_vals, stage)`\cr +#' (`data.table()`, `Task`, `list()`, `character(1)`) -> `data.table()`\cr +#' This method must only be overwritten when the the `per_column` construction argument is `FALSE`. +#' It receives as inputs all selected lazy tensor columns, the input `Task` (already cloned), +#' the paramer values, and whether the preprocessing is applied during training (stage is `"train"`) +#' or prediction (stage is `"predict"`). It needs to return a `data.table` with lazy tensor columns. +#' Note that the lazy tensor inputs should not be modified in-place. +#' Note that overwriting this method (currently) requires a solid understanding of the [`lazy_tensor`] internals. This might be made easier in the future. +#' Note also that you need to pay attention to avoid name conflicts with existing columns in the task. #' #' @param fn (`function`)\cr #' The preprocessing function. @@ -21,21 +43,26 @@ #' specfied as parameters. Pay attention to set the correct `tags` for the parameters: if tag `"train"` is present, #' the preprocessing is applied during training and if tag `"predict"` is present, the preprocessing is applied #' during prediction (if `augment` is set to `FALSE`). +#' @param per_column (`logical(1)`)\cr +#' Whether the transformation is applied per column. +#' If this is `FALSE`, is applied to all lazy tensor columns at once and might produce +#' one or more new lazy tensor columns. #' #' @section Input and Output Channels: #' See [`PipeOpTaskPreproc`]. -#' Note that the `PipeOp` currently expects exactly one [`lazy_tensor`] column. -#' @section State +#' @section State: #' See [`PipeOpTaskPreproc`]. #' @section Parameters: #' In addition to the parameters inherited from [`PipeOpTaskPreproc`] as well as those specified during construction -#' as the argument `param_set` there is: +#' as the argument `param_set` there are the following parameters: #' #' * `augment` :: `logical(1)`\cr +#' (This parameter only exists of the `PipeOp`) does not modify its input shapes. #' Whether the to apply the preprocessing only during training (`TRUE`) or also during prediction (`FALSE`). #' This parameter is initialized to `FALSE`. #' #' @section Internals: +#' If `per_column` is `TRUE`: #' #' A [`PipeOpModule`] with one input and one output channel is created. #' The pipeop simply applies the function `fn` to the input tensor while additionally @@ -43,88 +70,110 @@ #' Then [`transform_lazy_tensor`] is called with the created [`PipeOpModule`] and the shapes obtained from the #' `$shapes_out()` method of this `PipeOp`. #' +#' +#' If `per_column` is `FALSE`: +#' It is the obligation of the user to overwrite the `.transform()` method appropriately. +#' Note that on +#' #' @include PipeOpTorch.R #' @export #' @examples -if (FALSE) { - PipeOpPreprocTorchPoly = R6::R6Class("PipeOpPreprocTorchPoly", - inherit = PipeOpTaskPreprocTorch, - public = list( - initialize = function(id = "preproc_poly", param_vals = list()) { - param_set = paradox::ps( - n_degree = paradox::p_int(lower = 1L, tags = c("train", "predict", "required")) - ) - param_set$set_values( - n_degree = 1L - ) - fn = mlr3misc::crate(function(x, n_degree) { - torch::torch_cat( - lapply(seq_len(n_degree), function(d) torch_pow(x, d)), - dim = 2L - ) - }) - - super$initialize( - fn = fn, - id = id, - packages = character(0), - param_vals = param_vals, - param_set = param_set - ) - } - ), - private = list( - .shapes_out = function(shapes_in, param_vals, task) { - # shapes_in is a list of length 1 containing the shapes - checkmate::assert_true(length(shapes_in[[1L]]) == 2L) - if (shapes_in[[1L]][2L] != 1L) { - stop("Input shape must be (NA, 1)") - } - list(c(NA, param_vals$n_degree)) - } - ) - ) - - po_poly = PipeOpPreprocTorchPoly$new( - param_vals = list(n_degree = 2L) - ) - - po_poly$shapes_out(c(NA, 1L)) - - d = data.table( - x1 = as_lazy_tensor(rnorm(10)), - x2 = as_lazy_tensor(rnorm(10)), - y = rnorm(10) - ) - - task = as_task_regr(d, target = "y") - - po_pol - - po_preproc = po("preproc_torch", - # use mlr3misc::crate to get rid of unnecessary environment baggage - fn = mlr3misc::crate(function(x, a) x + a), - param_set = ps(a = p_int(tags = c("train", "predict", "required"))) - ) - - po_preproc$param_set$set_values( - a = 100 - ) - - taskout_train = po_preproc$train(list(task))[[1L]] - - materialize(taskout_train$data(cols = c("x1", "x2"))) - -} +#' # Creating a simple task +#' d = data.table( +#' x1 = as_lazy_tensor(rnorm(10)), +#' x2 = as_lazy_tensor(rnorm(10)), +#' x3 = as_lazy_tensor(as.double(1:10)), +#' y = rnorm(10) +#' ) +#' +#' taskin = as_task_regr(d, target = "y") +#' +#' # Creating a simple preprocessing pipeop +#' po_simple = po("preproc_torch", +#' # use mlr3misc::crate to get rid of unnecessary environment baggage +#' fn = mlr3misc::crate(function(x, a) x + a), +#' param_set = ps(a = p_int(tags = c("train", "predict", "required"))) +#' ) +#' +#' po_simple$param_set$set_values( +#' a = 100, +#' affect_columns = selector_name(c("x1", "x2")), +#' augment = FALSE +#' ) +#' +#' taskout_train = po_simple$train(list(taskin))[[1L]] +#' materialize(taskout_train$data(cols = c("x1", "x2"))) +#' +#' taskout_predict_noaug = po_simple$predict(list(taskin))[[1L]] +#' materialize(taskout_predict_noaug$data(cols = c("x1", "x2"))) +#' +#' po_simple$param_set$set_values( +#' augment = TRUE +#' ) +#' +#' # transformation is not applied +#' taskout_predict_aug = po_simple$predict(list(taskin))[[1L]] +#' materialize(taskout_predict_aug$data(cols = c("x1", "x2"))) +#' +#' # Creating a more complex preprocessing PipeOp +#' +#' PipeOpPreprocTorchPoly = R6::R6Class("PipeOpPreprocTorchPoly", +#' inherit = PipeOpTaskPreprocTorch, +#' public = list( +#' initialize = function(id = "preproc_poly", param_vals = list()) { +#' param_set = paradox::ps( +#' n_degree = paradox::p_int(lower = 1L, tags = c("train", "predict", "required")) +#' ) +#' param_set$set_values( +#' n_degree = 1L +#' ) +#' fn = mlr3misc::crate(function(x, n_degree) { +#' torch::torch_cat( +#' lapply(seq_len(n_degree), function(d) torch_pow(x, d)), +#' dim = 2L +#' ) +#' }) +#' +#' super$initialize( +#' fn = fn, +#' id = id, +#' packages = character(0), +#' param_vals = param_vals, +#' param_set = param_set +#' ) +#' } +#' ), +#' private = list( +#' .shapes_out = function(shapes_in, param_vals, task) { +#' # shapes_in is a list of length 1 containing the shapes +#' checkmate::assert_true(length(shapes_in[[1L]]) == 2L) +#' if (shapes_in[[1L]][2L] != 1L) { +#' stop("Input shape must be (NA, 1)") +#' } +#' list(c(NA, param_vals$n_degree)) +#' } +#' ) +#' ) +#' +#' po_poly = PipeOpPreprocTorchPoly$new( +#' param_vals = list(n_degree = 3L, affect_columns = selector_name("x3")) +#' ) +#' +#' # Note that the 'augment' parameter is not present as the PipeOp +#' # modifies the input shape and must hence be applied during training **and** prediction +#' po_poly$param_set +#' +#' po_poly$shapes_out(list(c(NA, 1L))) +#' +#' taskout = po_poly$train(list(taskin))[[1L]] +#' materialize(taskout$data(cols = "x3")) PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", inherit = PipeOpTaskPreproc, public = list( - initialize = function(fn, id = "preproc_torch", param_vals = list(), param_set = ps(), packages = character(0)) { - private$.fn = assert_function(fn, null.ok = FALSE) + initialize = function(fn, id = "preproc_torch", param_vals = list(), param_set = ps(), packages = character(0), per_column = TRUE) { + private$.per_column = assert_flag(per_column) + private$.fn = assert_function(fn, null.ok = per_column) - if ("augment" %in% param_set$ids()) { - stopf("Parameter name 'augment' is reserved and cannot be used.") - } if (is.null(private$.shapes_out)) { param_set$add(ps( augment = p_lgl(tags = c("predict", "required")) @@ -136,35 +185,40 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", id = id, param_vals = param_vals, param_set = param_set, - feature_types = "lazy_tensor" + feature_types = "lazy_tensor", + packages = packages ) }, #' @description - #' Calculates the output shape after applying the preprocessing step to a lazy tensor vector. - #' @param shapes_in (`list()` of `integer()` or `integer()`)\cr - #' The input input shape of the lazy tensor, which must either be a `list()` of length 1 containing the - #' shape of the lazy tensor (first dimension must be `NA` for the batch) or the shape itself. + #' Calculates the output shapes that would result in applying the preprocessing to one or more + #' lazy tensor columns with the provided shape. + #' Names are ignored and only order matters. + #' @param shapes_in (`list()` of `integer()`)\cr + #' The input input shapes of the lazy tensors. #' @param task ([`Task`] or `NULL`)\cr - #' The task, which is very rarely used. - #' @return - #' A named `list()` containing the output shape. The name is the name of the output channel. + #' The task, which is very rarely needed. + #' @return `list()` of `integer()` shapes_out = function(shapes_in, task = NULL) { assert_r6(task, "Task", null.ok = TRUE) - if (is.numeric(shapes_in)) shapes_in = list(shapes_in) - if (identical(self$input$name, "...")) { - assert_list(shapes_in, min.len = 1, types = "numeric") - } else { - assert_list(shapes_in, len = nrow(self$input), types = "numeric") + assert_shapes(shapes_in, named = FALSE) + names(shapes_in) = NULL + + if (is.null(private$.shapes_out)) { + # shapes_out can only be NULL if per_column is TRUE + return(shapes_in) } - s = if (is.null(private$.shapes_out)) { - shapes_in + pv = self$param_set$get_values() + + torch_tensor(0) + + s = if (private$.per_column) { + map(shapes_in, function(s) private$.shapes_out(list(s), param_vals = pv, task = task)[[1L]]) } else { - pv = self$param_set$get_values() - private$.shapes_out(shapes_in, pv, task = task) + private$.shapes_out(shapes_in, param_vals = pv, task = task) } - set_names(s, self$output$name) + return(s) } ), private = list( @@ -179,18 +233,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", param_vals = self$param_set$get_values(tags = "train") param_vals$affect_columns = NULL - - trafo = private$.fn - - fn = if (length(param_vals)) { - crate(function(x) { - invoke(.f = trafo, x, .args = param_vals) - }, param_vals, trafo, .parent = environment(trafo)) - } else { - trafo - } - - dt = private$.transform(dt, fn, task) + dt = private$.transform(dt, task, param_vals, "train") self$state$dt_columns = dt_columns task$select(setdiff(task$feature_names, cols))$cbind(dt) @@ -201,27 +244,43 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", return(task) } dt = task$data(cols = cols) + param_vals = self$param_set$get_values(tags = "predict") - augment = param_vals$augment - param_vals$augment = NULL + dt = private$.transform(dt, task, param_vals, "predict") + res = task$select(setdiff(task$feature_names, cols))$cbind(dt) - # augment can be NULL (in case the pipeopf changes the output shape and hence augmentation is not supported) - # or a logical(1) - fn = if (isTRUE(augment)) { - # We cannot simple add no module to the graph as we need to maintain the same graph-structure - # as during training - identity + res + }, + .transform = function(dt, task, param_vals, stage) { + # stage is "train" or "predict" + trafo = private$.fn + + if (stage == "train") { + fn = if (length(param_vals)) { + crate(function(x) { + invoke(.f = trafo, x, .args = param_vals) + }, param_vals, trafo, .parent = environment(trafo)) + } else { + trafo + } } else { - trafo = private$.fn - crate(function(x) { - invoke(.f = trafo, x, .args = param_vals) - }, param_vals, trafo, .parent = environment(trafo)) + augment = param_vals$augment + param_vals$augment = NULL + # augment can be NULL (in case the pipeop changes the output shape and hence augmentation is not supported) + # or a logical(1) + fn = if (isTRUE(augment)) { + # We cannot simple add no module to the graph as we need to maintain the same graph-structure + # as during training + identity + } else if (length(param_vals)) { + crate(function(x) { + invoke(.f = trafo, x, .args = param_vals) + }, param_vals, trafo, .parent = environment(trafo)) + } else { + trafo + } } - dt = private$.transform(dt, fn, task) - task$select(setdiff(task$feature_names, cols))$cbind(dt) - }, - .transform = function(dt, fn, task) { dt = map_dtc(dt, function(lt) { # the ID of the `PipeOp` does not matter. # By randomizing it we avoid ID clashes @@ -233,20 +292,25 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", outname = self$output$name, packages = self$packages ) - shapes_out = self$shapes_out(lt$.pointer_shape, task) - transform_lazy_tensor(lt, po_fn, shapes_out[[1L]]) + shape_out = self$shapes_out(list(lt$.pointer_shape), task)[[1L]] + transform_lazy_tensor(lt, po_fn, shape_out) }) + # we don't want name conflicts with other columns + names(dt) = uniqueify(names(dt), setdiff(task$col_info$id, names(dt))) + # FIXME: names return(dt) }, - .fn = NULL, .additional_phash_input = function() { - list(self$param_set$ids(), private$.fn, self$packages) - } + list(self$param_set$ids(), private$.fn, self$packages, private$.per_column) + }, + .fn = NULL, + .per_column = NULL ) ) pipeop_preproc_torch = function(fn, id, param_set = NULL) { # TODO +} # Where I was: diff --git a/R/PipeOpTorch.R b/R/PipeOpTorch.R index 7d6dd703..b4bc838e 100644 --- a/R/PipeOpTorch.R +++ b/R/PipeOpTorch.R @@ -32,7 +32,7 @@ #' If left as is, it calls the provided `module_generator` with the arguments obtained by #' the private method `.shape_dependent_params()`. #' * `.shapes_out(shapes_in, param_vals, task)`\cr -#' (`list()`, `list()`) -> named `list()`\cr +#' (`list()`, `list()`, `Task` or `NULL`) -> named `list()`\cr #' This private method gets a list of `numeric` vectors (`shapes_in`), the parameter values (`param_vals`), #' as well as an (optional) [`Task`]. # The `shapes_in` list indicates the shape of input tensors that will be fed to the module's `$forward()` function. @@ -279,9 +279,8 @@ PipeOpTorch = R6Class("PipeOpTorch", }, #' @description #' Calculates the output shapes for the given input shapes, parameters and task. - #' @param shapes_in (`list()` of `integer()` or `integer()`)\cr + #' @param shapes_in (`list()` of `integer()`)\cr #' The input input shapes, which must be in the same order as the input channel names of the `PipeOp`. - #' If there is only one input channel, `shapes_in` can also contain the shapes for this input channel. #' @param task ([`Task`] or `NULL`)\cr #' The task, which is very rarely used (default is `NULL`). An exception is [`PipeOpTorchHead`]. #' @return @@ -381,9 +380,3 @@ PipeOpTorch = R6Class("PipeOpTorch", } ) ) - -pipeop_torch = function(...) { - # TODO -} - - diff --git a/R/materialize.R b/R/materialize.R index 72cdb0f3..bbe1e18a 100644 --- a/R/materialize.R +++ b/R/materialize.R @@ -32,7 +32,6 @@ materialize = function(x, device = "cpu", ...) { } #' @export -#' @return (`list()`) materialize.list = function(x, device = "cpu") { # nolint cache = if (sum(map_lgl(x, is_lazy_tensor)) > 1L) { new.env() @@ -73,7 +72,6 @@ materialize.list = function(x, device = "cpu") { # nolint #' @export -#' @return ([`torch_tensor()`]) materialize.lazy_tensor = function(x, device = "cpu") { # nolint materialize_internal(x = x, device = device, cache = NULL, set_keep_results = TRUE) } @@ -107,7 +105,7 @@ materialize.lazy_tensor = function(x, device = "cpu") { # nolint #' When caching is done, this should be set to `FALSE` as otherwise data will be discarded that might be relevant #' for materializing other lazy tensor columns. #' @return [`lazy_tensor()`] -#' @noRd +#' @keywords internal materialize_internal = function(x, device = "cpu", cache = NULL, set_keep_results = is.null(cache)) { do_caching = !is.null(cache) ids = vec_data(x) @@ -176,5 +174,4 @@ materialize_internal = function(x, device = "cpu", cache = NULL, set_keep_result #' @method materialize data.frame #' @export -#' @return ([`list()`]) materialize.data.frame = materialize.list # nolint diff --git a/R/preproc_and_trafo.R b/R/preproc_and_trafo.R deleted file mode 100644 index add22bb4..00000000 --- a/R/preproc_and_trafo.R +++ /dev/null @@ -1,41 +0,0 @@ -#' @include register_lazy.R -NULL - -# Where I have left off: -# I split the class for the lazy tensor preprocessing / transformation into two clases -# I also decided to create the corresponding classes programmatically, otherwise we just have to write so much code -# there will be one or two (either one for both preproc and trafo or seperately) manual pages that document how to -# use the pipeops + a pointer to the parent class + a list with available pipeops -# This refactoring now needs to be done + the resulting pipeops than tested - -#' @rawNamespace exportPattern("^PipeOpTaskPreprocTorch") -#' @rawNamespace exportPattern("^PipeOpTorchTrafo") -NULL - -#' @title Lazy Preprocessing and Transformations -#' @name preproc_and_lazy -#' @section Available PipeOps: -#' The following -NULL - -#' @name PipeOpTaskPreprocTorchResize -#' @alias PipeOpTorchTrafoResize -#' @rdname preproc_and_lazy -register_lazy("resize", torchvision::transform_resize, - packages = "torchvision", - param_set = ps( - size = p_uty(tags = c("train", "required")), - interpolation = p_fct(levels = magick::filter_types(), special_vals = list(0L, 2L, 3L), - tags = "train", default = 2L - ) - ), - shapes_out = function(shapes_in, param_vals, task) { - size = param_vals$size - shape = shapes_in[[1L]] - assert_true(length(shape) > 2) - height = shape[[length(shape) - 1L]] - width = shape[[length(shape)]] - s = torchvision::transform_resize(torch_ones(c(1, height, width), device = "meta"), size = size)$shape[2:3] - list(c(shape[seq_len(length(shape) - 2L)], s)) - } -) diff --git a/R/preprocess.R b/R/preprocess.R new file mode 100644 index 00000000..7b4de7a3 --- /dev/null +++ b/R/preprocess.R @@ -0,0 +1,34 @@ +#' @title Lazy Preprocessing and Transformations +#' @description +#' Overview over all implemented preprocessing methods. +#' See [`PipeOpTaskPreprocTorch`] for more details. +#' @name preprocessing_pipeops +#' @rawNamespace exportPattern("^PipeOpPreproc") +#' @include PipeOpTaskPreprocTorch.R +#' @section Available PipeOps: +#' The following +NULL + +#' @name PipeOpPreprocResize +#' @describeIn preprocessing_pipeops See [`torchvision::transform_resize`] +#' @rdname preprocessing_pipeops +#' @section preproc_resize: +#' Resize a tensor to a given size +register_preproc("resize", torchvision::transform_resize, + packages = "torchvision", + param_set = ps( + size = p_uty(tags = c("train", "required")), + interpolation = p_fct(levels = magick::filter_types(), special_vals = list(0L, 2L, 3L), + tags = "train", default = 2L + ) + ), + shapes_out = function(shapes_in, param_vals, task) { + size = param_vals$size + shape = shapes_in[[1L]] + assert_true(length(shape) > 2) + height = shape[[length(shape) - 1L]] + width = shape[[length(shape)]] + s = torchvision::transform_resize(torch_ones(c(1, height, width), device = "meta"), size = size)$shape[2:3] + list(c(shape[seq_len(length(shape) - 2L)], s)) + } +) diff --git a/R/register_lazy.R b/R/register_lazy.R deleted file mode 100644 index 5e04cc34..00000000 --- a/R/register_lazy.R +++ /dev/null @@ -1,73 +0,0 @@ -register_trafo = function(name, fn, param_set, shapes_out = NULL, packages, envir) { - classname = paste0("PipeOpTorchTrafo", capitalize(name)) - idname = paste0("trafo_", name) - - init_fun = crate(function(id = idname, param_vals = list()) { - super$initialize( - id = id, - packages = packages, - param_set = param_set, - param_vals = param_vals, - fn = fn - ) - }, param_set, fn, idname, packages, .parent = topenv()) - body(init_fun)[[2]][[4]] = param_set - attributes(init_fun) = NULL - - Class = R6Class(classname, - inherit = PipeOpTorchTrafo, - public = list( - initialize = init_fun - ), - private = list( - .shapes_out = shapes_out - ) - ) - - assign(classname, Class, envir = envir) - register_po(idname, Class) - - return(NULL) -} - -register_preproc = function(name, fn, param_set, shapes_out, packages, envir) { - classname = paste0("PipeOpPreprocTorch", capitalize(name)) - idname = paste0("preproc_", name) - - init_fun = crate(function(id = idname, param_vals = list()) { - super$initialize( - id = id, - packages = packages, - param_set = ps, - param_vals = param_vals, - fn = fn - ) - }, fn, packages, .parent = topenv()) - # param_set is already an expression - body(init_fun)[[2]][[4]] = param_set - attributes(init_fun) = NULL - - Class = R6Class(classname, - inherit = PipeOpTaskPreprocTorch, - public = list( - initialize = init_fun - ), - private = list( - .shapes_out = crate(function(...)) - ) - ) - - assign(classname, Class, envir = envir) - register_po(idname, Class) - - return(NULL) - -} - -#' @include PipeOpTaskPreprocTorch.R PipeOpTorchTrafo.R -register_lazy = function(name, fn, param_set, shapes_out, packages, envir = parent.frame()) { - register_trafo(name, fn, substitute(param_set), shapes_out, packages, envir = envir) - register_preproc(name, fn, substitute(param_set), shapes_out, packages, envir = envir) - - return(NULL) -} diff --git a/R/task_dataset.R b/R/task_dataset.R index 0bd05d5e..0d009f9a 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -52,9 +52,8 @@ task_dataset = dataset( # Here, we could have multiple `lazy_tensor` columns that share parts of the graph # We try to merge those graphs if possible - # FIXME: I am not sure whether this belongs here ... - if (length(lazy_tensor_features) > 1L) { + # TODO: Inspect hashes of data descriptors to check whether caching is possible first_row = self$task$data(self$task$row_ids[1L], cols = lazy_tensor_features) graphs = map(first_row, function(x) attr(x, "data_descriptor")$graph) graphs = graphs[!duplicated(graphs)] diff --git a/R/utils.R b/R/utils.R index e82ee2de..773e3e86 100644 --- a/R/utils.R +++ b/R/utils.R @@ -188,11 +188,15 @@ assert_shape = function(shape, null.ok = FALSE) { # nolint TRUE } -assert_shapes = function(shapes) { - assert_list(shapes, names = "unique", min.len = 1L) +assert_shapes = function(shapes, named = TRUE) { + assert_list(shapes, names = if (named) "unique", min.len = 1L) walk(shapes, assert_shape) } assert_lazy_tensor = function(x) { assert_class(x, "lazy_tensor") } + +uniqueify = function(new, existing) { + make.unique(c(existing, new), sep = "_")[length(existing) + seq_along(new)] +} diff --git a/R/zzz.R b/R/zzz.R index 253fff83..6d38751c 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -26,7 +26,7 @@ mlr3torch_learners = new.env() mlr3torch_tasks = new.env() mlr3torch_resamplings = new.env() mlr3torch_pipeop_tags = c("torch", "activation") -mlr3torch_feature_types = c(img = "imageuri", ltnsr = "lazy_tensor") +mlr3torch_feature_types = c(img = "imageuri", lt = "lazy_tensor") # metainf must be manually added in the register_mlr3pipelines function # Because the value is substituted, we cannot pass it through this function diff --git a/R/PipeOpTorchTrafo.R b/attic/Trafo.R similarity index 86% rename from R/PipeOpTorchTrafo.R rename to attic/Trafo.R index 35965d56..8b232476 100644 --- a/R/PipeOpTorchTrafo.R +++ b/attic/Trafo.R @@ -1,3 +1,36 @@ + +register_trafo = function(name, fn, param_set, shapes_out = NULL, packages, envir) { + classname = paste0("PipeOpTorchTrafo", capitalize(name)) + idname = paste0("trafo_", name) + + init_fun = crate(function(id = idname, param_vals = list()) { + super$initialize( + id = id, + packages = packages, + param_set = param_set, + param_vals = param_vals, + fn = fn + ) + }, param_set, fn, idname, packages, .parent = topenv()) + body(init_fun)[[2]][[4]] = param_set + attributes(init_fun) = NULL + + Class = R6Class(classname, + inherit = PipeOpTorchTrafo, + public = list( + initialize = init_fun + ), + private = list( + .shapes_out = shapes_out + ) + ) + + assign(classname, Class, envir = envir) + register_po(idname, Class) + + return(NULL) +} + #' @title Base Class for Lazy Transformations #' @name mlr_pipeops_torch_trafo #' @@ -136,10 +169,9 @@ PipeOpTorchTrafo = R6Class("PipeOpTorchTrafo", ) ) -pipeop_torch_trafo = function(fn, id, param_set = NULL) { +pipeop_torch_trafo.function = function(fn, id, param_set = NULL) { # nolint } #' @include zzz.R register_po("torch_trafo", PipeOpTorchTrafo) - diff --git a/man/materialize_internal.Rd b/man/materialize_internal.Rd new file mode 100644 index 00000000..1075c64e --- /dev/null +++ b/man/materialize_internal.Rd @@ -0,0 +1,51 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/materialize.R +\name{materialize_internal} +\alias{materialize_internal} +\title{Materialize a Lazy Tensor} +\usage{ +materialize_internal( + x, + device = "cpu", + cache = NULL, + set_keep_results = is.null(cache) +) +} +\arguments{ +\item{x}{(\code{\link[=lazy_tensor]{lazy_tensor()}})\cr +The lazy tensor to materialize.} + +\item{device}{(\code{character(1L)})\cr +The device to put the materialized tensor on (after running the preprocessing graph).} + +\item{cache}{(\code{NULL} or \code{environment()})\cr +Whether to cache the (intermediate) results of the materialization. +This can make data loading faster when multiple \code{lazy_tensor}s reference the same dataset or graph.} + +\item{set_keep_results}{(\code{logical(1)})\cr +In some cases, the \code{.pointer} of a \code{\link{DataDescriptor}} might point to a non-terminal node in which case the +this result is not part of the output of the \code{\link{Graph}}. +Therefore we have to include this as part of the \code{keep_results} field of the \code{\link{Graph}}. +When caching is done, this should be set to \code{FALSE} as otherwise data will be discarded that might be relevant +for materializing other lazy tensor columns.} +} +\value{ +\code{\link[=lazy_tensor]{lazy_tensor()}} +} +\description{ +Materializing a lazy tensor consists of: +\enumerate{ +\item Loading the data from the internal dataset of the \code{\link{DataDescriptor}}. +\item Processing these batches in the preprocessing \code{\link{Graph}}s. +\item Returning the result of the \code{\link{PipeOp}} pointed to by the \code{\link{DataDescriptor}} (\code{.pointer}). +} + +With multiple \code{\link{lazy_tensor}} columns we can benefit from caching because: +a) Output(s) from the dataset might be input to multiple graphs. +b) Different lazy tensors might be outputs from the same graph. + +For this reason it is possible to provide a cache environment. +The hash key for a) is the hash of the indices and the dataset. +The hash key for b) is the hash of the indices dataset and preprocessing graph. +} +\keyword{internal} diff --git a/man/mlr_pipeops_task_preproc_torch.Rd b/man/mlr_pipeops_task_preproc_torch.Rd new file mode 100644 index 00000000..8ed6fc83 --- /dev/null +++ b/man/mlr_pipeops_task_preproc_torch.Rd @@ -0,0 +1,284 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTaskPreprocTorch.R +\name{mlr_pipeops_task_preproc_torch} +\alias{mlr_pipeops_task_preproc_torch} +\alias{PipeOpTaskPreprocTorch} +\title{Base Class for Torch Preprocessing} +\description{ +This \code{PipeOp} can be used to preprocess (one or more) \code{\link{lazy_tensor}} columns contained in an \code{\link[mlr3:Task]{mlr3::Task}}. +The function that is applied is specified as construction argument \code{fn} and additional arguments to this +function can be defined through the \code{PipeOp}'s parameter set. +The preprocessing is either done per-column in which case the number lazy tensor output columns is equivalent +to the number of lazy tensor input columns. +It is also possible to implement preprocessing that is applied to all lazy tensor columns at once and returns +one or more lazy tensor columns. +Note also that the preprocessing is always applied batch-wise. + +The convenience function \code{\link[=pipeop_preproc_torch]{pipeop_preproc_torch()}} can also be used to implement preprocessing pipeops +inheriting from this class. +} +\section{Inheriting}{ + +In addition to specifying the parameters \code{fn}, \code{packages} and \code{param_set} during construction you can also overwrite +the private \code{.shapes_out()} or \code{.tranform()} methods: +\itemize{ +\item \code{.shapes_out(shapes_in, param_vals, task)}\cr +(\code{list()}, \verb{list(), }Task\code{or}NULL\verb{) -> }list()`\cr +This private method calculates the output shapes of the lazy tensor columns that are created from applying +the preprocessing. + +Also see the documentation of \code{\link{PipeOpTorch}} how to implement this method. + +In case the construction argument \code{per_column} is \code{TRUE}, this private method only has the responsibility +to caclculate the output shapes for one input column, i.e. the input \code{shapes_in} can be assumed to have +exactly one shape vector for which it must calculate the output shapes. +\item \code{.transform(dt, task, param_vals, stage)}\cr +(\code{data.table()}, \code{Task}, \code{list()}, \code{character(1)}) -> \code{data.table()}\cr +This method must only be overwritten when the the \code{per_column} construction argument is \code{FALSE}. +It receives as inputs all selected lazy tensor columns, the input \code{Task} (already cloned), +the paramer values, and whether the preprocessing is applied during training (stage is \code{"train"}) +or prediction (stage is \code{"predict"}). It needs to return a \code{data.table} with lazy tensor columns. +Note that the lazy tensor inputs should not be modified in-place. +Note that overwriting this method (currently) requires a solid understanding of the \code{\link{lazy_tensor}} internals. This might be made easier in the future. +Note also that you need to pay attention to avoid name conflicts with existing columns in the task. +} +} + +\section{Input and Output Channels}{ + +See \code{\link{PipeOpTaskPreproc}}. +} + +\section{State}{ + +See \code{\link{PipeOpTaskPreproc}}. +} + +\section{Parameters}{ + +In addition to the parameters inherited from \code{\link{PipeOpTaskPreproc}} as well as those specified during construction +as the argument \code{param_set} there are the following parameters: +\itemize{ +\item \code{augment} :: \code{logical(1)}\cr +(This parameter only exists of the \code{PipeOp}) does not modify its input shapes. +Whether the to apply the preprocessing only during training (\code{TRUE}) or also during prediction (\code{FALSE}). +This parameter is initialized to \code{FALSE}. +} +} + +\section{Internals}{ + +If \code{per_column} is \code{TRUE}: + +A \code{\link{PipeOpModule}} with one input and one output channel is created. +The pipeop simply applies the function \code{fn} to the input tensor while additionally +passing the paramter values (minus \code{augment} and \code{affect_columns}) to \code{fn}. +Then \code{\link{transform_lazy_tensor}} is called with the created \code{\link{PipeOpModule}} and the shapes obtained from the +\verb{$shapes_out()} method of this \code{PipeOp}. + +If \code{per_column} is \code{FALSE}: +It is the obligation of the user to overwrite the \code{.transform()} method appropriately. +Note that on +} + +\examples{ +# Creating a simple task +d = data.table( + x1 = as_lazy_tensor(rnorm(10)), + x2 = as_lazy_tensor(rnorm(10)), + x3 = as_lazy_tensor(as.double(1:10)), + y = rnorm(10) +) + +taskin = as_task_regr(d, target = "y") + +# Creating a simple preprocessing pipeop +po_simple = po("preproc_torch", + # use mlr3misc::crate to get rid of unnecessary environment baggage + fn = mlr3misc::crate(function(x, a) x + a), + param_set = ps(a = p_int(tags = c("train", "predict", "required"))) +) + +po_simple$param_set$set_values( + a = 100, + affect_columns = selector_name(c("x1", "x2")), + augment = FALSE +) + +taskout_train = po_simple$train(list(taskin))[[1L]] +materialize(taskout_train$data(cols = c("x1", "x2"))) + +taskout_predict_noaug = po_simple$predict(list(taskin))[[1L]] +materialize(taskout_predict_noaug$data(cols = c("x1", "x2"))) + +po_simple$param_set$set_values( + augment = TRUE +) + +# transformation is not applied +taskout_predict_aug = po_simple$predict(list(taskin))[[1L]] +materialize(taskout_predict_aug$data(cols = c("x1", "x2"))) + +# Creating a more complex preprocessing PipeOp + +PipeOpPreprocTorchPoly = R6::R6Class("PipeOpPreprocTorchPoly", + inherit = PipeOpTaskPreprocTorch, + public = list( + initialize = function(id = "preproc_poly", param_vals = list()) { + param_set = paradox::ps( + n_degree = paradox::p_int(lower = 1L, tags = c("train", "predict", "required")) + ) + param_set$set_values( + n_degree = 1L + ) + fn = mlr3misc::crate(function(x, n_degree) { + torch::torch_cat( + lapply(seq_len(n_degree), function(d) torch_pow(x, d)), + dim = 2L + ) + }) + + super$initialize( + fn = fn, + id = id, + packages = character(0), + param_vals = param_vals, + param_set = param_set + ) + } + ), + private = list( + .shapes_out = function(shapes_in, param_vals, task) { + # shapes_in is a list of length 1 containing the shapes + checkmate::assert_true(length(shapes_in[[1L]]) == 2L) + if (shapes_in[[1L]][2L] != 1L) { + stop("Input shape must be (NA, 1)") + } + list(c(NA, param_vals$n_degree)) + } + ) +) + +po_poly = PipeOpPreprocTorchPoly$new( + param_vals = list(n_degree = 3L, affect_columns = selector_name("x3")) +) + +# Note that the 'augment' parameter is not present as the PipeOp +# modifies the input shape and must hence be applied during training **and** prediction +po_poly$param_set + +po_poly$shapes_out(list(c(NA, 1L))) + +taskout = po_poly$train(list(taskin))[[1L]] +materialize(taskout$data(cols = "x3")) +} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3pipelines:PipeOpTaskPreproc]{mlr3pipelines::PipeOpTaskPreproc}} -> \code{PipeOpTaskPreprocTorch} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTaskPreprocTorch-new}{\code{PipeOpTaskPreprocTorch$new()}} +\item \href{#method-PipeOpTaskPreprocTorch-shapes_out}{\code{PipeOpTaskPreprocTorch$shapes_out()}} +\item \href{#method-PipeOpTaskPreprocTorch-clone}{\code{PipeOpTaskPreprocTorch$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTaskPreprocTorch-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTaskPreprocTorch$new( + fn, + id = "preproc_torch", + param_vals = list(), + param_set = ps(), + packages = character(0), + per_column = TRUE +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{fn}}{(\code{function})\cr +The preprocessing function.} + +\item{\code{id}}{(\code{character(1)})\cr +The id for of the new object.} + +\item{\code{param_vals}}{(named \code{list()})\cr +Parameter values to be set after construction.} + +\item{\code{param_set}}{(\code{\link{ParamSet}})\cr +In case the function \code{fn} takes additional parameter besides a \code{\link[=torch_tensor]{torch_tensor()}} they can be +specfied as parameters. Pay attention to set the correct \code{tags} for the parameters: if tag \code{"train"} is present, +the preprocessing is applied during training and if tag \code{"predict"} is present, the preprocessing is applied +during prediction (if \code{augment} is set to \code{FALSE}).} + +\item{\code{packages}}{(\code{character()})\cr +The packages the preprocessing function depends on.} + +\item{\code{per_column}}{(\code{logical(1)})\cr +Whether the transformation is applied per column. +If this is \code{FALSE}, is applied to all lazy tensor columns at once and might produce +one or more new lazy tensor columns.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTaskPreprocTorch-shapes_out}{}}} +\subsection{Method \code{shapes_out()}}{ +Calculates the output shapes that would result in applying the preprocessing to one or more +lazy tensor columns with the provided shape. +Names are ignored and only order matters. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTaskPreprocTorch$shapes_out(shapes_in, task = NULL)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{shapes_in}}{(\code{list()} of \code{integer()})\cr +The input input shapes of the lazy tensors.} + +\item{\code{task}}{(\code{\link{Task}} or \code{NULL})\cr +The task, which is very rarely needed.} +} +\if{html}{\out{
}} +} +\subsection{Returns}{ +\code{list()} of \code{integer()} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTaskPreprocTorch-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTaskPreprocTorch$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_torch.Rd b/man/mlr_pipeops_torch.Rd index a735c0e7..e90db5c3 100644 --- a/man/mlr_pipeops_torch.Rd +++ b/man/mlr_pipeops_torch.Rd @@ -35,7 +35,7 @@ This private method is called to generated the \code{nn_module} that is passed a If left as is, it calls the provided \code{module_generator} with the arguments obtained by the private method \code{.shape_dependent_params()}. \item \code{.shapes_out(shapes_in, param_vals, task)}\cr -(\code{list()}, \code{list()}) -> named \code{list()}\cr +(\code{list()}, \code{list()}, \code{Task} or \code{NULL}) -> named \code{list()}\cr This private method gets a list of \code{numeric} vectors (\code{shapes_in}), the parameter values (\code{param_vals}), as well as an (optional) \code{\link{Task}}. The \code{shapes_in} can be assumed to be in the same order as the input names of the \code{PipeOp}. @@ -349,9 +349,8 @@ Calculates the output shapes for the given input shapes, parameters and task. \subsection{Arguments}{ \if{html}{\out{
}} \describe{ -\item{\code{shapes_in}}{(\code{list()} of \code{integer()} or \code{integer()})\cr -The input input shapes, which must be in the same order as the input channel names of the \code{PipeOp}. -If there is only one input channel, \code{shapes_in} can also contain the shapes for this input channel.} +\item{\code{shapes_in}}{(\code{list()} of \code{integer()})\cr +The input input shapes, which must be in the same order as the input channel names of the \code{PipeOp}.} \item{\code{task}}{(\code{\link{Task}} or \code{NULL})\cr The task, which is very rarely used (default is \code{NULL}). An exception is \code{\link{PipeOpTorchHead}}.} diff --git a/man/mlr_pipeops_torch_trafo.Rd b/man/mlr_pipeops_torch_trafo.Rd deleted file mode 100644 index a2c12bdf..00000000 --- a/man/mlr_pipeops_torch_trafo.Rd +++ /dev/null @@ -1,151 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchTrafo.R -\name{mlr_pipeops_torch_trafo} -\alias{mlr_pipeops_torch_trafo} -\alias{PipeOpTorchTrafo} -\title{Base Class for Lazy Transformations} -\description{ -This \code{PipeOp} represents simple preprocessing transformations of torch tensors. -These can be used in two situations: -\enumerate{ -\item To preprocess a task, which works analogous to standard preprocessing PipeOps like \code{\link{PipeOpPCA}}. -Because the \code{\link[=lazy_tensor]{lazy_tensor()}} does not make any assumptions on how the data is stored, the transformation is -applied lazily, i.e. when \code{\link[=materialize]{materialize()}} is called. -During trainig of a learner, this transformation will be a applied during data-loading on the CPU. -\item To add a preprocessing step in an \code{\link[=nn_graph]{nn_graph()}} that is being built up in a \code{\link{ModelDescriptor}}. -In this case, the transformation is applied during the forward pass of the model, i.e. the tensor is then -also on the specified device. -} - -Currently the \code{PipeOp} must have exactly one inut and one output. -} -\section{Inheriting}{ - -You need to: -\itemize{ -\item Initialize the \code{fn} argument. This function should take one torch tensor as input and return a torch tensor. -Additional parameters that are passed to the function can be specified via the parameter set. -This function needs to be a simple, stateless function, see section \emph{Internals} for more information. -\item In case the transformation changes the tensor shape you must provide a private \code{.shapes_out()} method like -for \code{\link{PipeOpTorch}}. -} -} - -\section{Input and Output Channels}{ - -During \emph{training}, all inputs and outputs are of class \code{\link{Task}} or \code{\link{ModelDescriptor}}. -During \emph{prediction}, all inputs and outputs are of class \code{\link{Task}} or \code{\link{ModelDescriptor}}. -} - -\section{State}{ - -The state is the value calculated by the public method \code{shapes_out()}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{augment} :: \code{logical(1)}\cr -This parameter is only present when the \code{PipeOp} does not modify the input shape. -Whether the transformation is applied only during training (\code{TRUE}) or also during prediction (also includes -validation; \code{FALSE}). -This parameter is initalized to \code{FALSE}. -} - -Additional parameters can be specified by the class. -} - -\section{Internals}{ - - -Applied to a \strong{Task}: - -When this PipeOp is used for preprocessing, it creates a \code{\link{PipeOpModule}} from the function \code{fn} (additionally -passing the \code{param_vals} if there are any) and then adds it to the preprocessing graph that is part of the -\code{\link{DataDescriptor}} contained in the \code{\link{lazy_tensor}} column that is being preprocessed. -When the outpuf of this pipeop is then preprocessed by a different \code{PipeOpTorchTrafo} a deep clone of the -preprocessing graph is done. However, this deep clone does not clone the environment of the -function or its attributes in case they have a state (as e.g. in \code{\link[=nn_module]{nn_module()}}s). -When setting the parameter \code{augment} this meanst that the preprcessing - -Applied to a \strong{ModelDescriptor} -} - -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchTrafo} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchTrafo-new}{\code{PipeOpTorchTrafo$new()}} -\item \href{#method-PipeOpTorchTrafo-clone}{\code{PipeOpTorchTrafo$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchTrafo-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchTrafo$new( - fn, - id = "torch_trafo", - param_vals = list(), - param_set = ps(), - packages = character(0) -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{fn}}{(\verb{function()})\cr -A function that will be applied to a (lazy) tensor. -Additional arguments can be passed as parameters. -During actual preprocessing the (lazy) tensor will be passed by position. -The transformation is always applied to a whole batch of tensors, i.e. the first dimension is the batch dimension.} - -\item{\code{id}}{(\code{character(1)})\cr -The id for of the new object.} - -\item{\code{param_vals}}{(named \code{list()})\cr -Parameter values to be set after construction.} - -\item{\code{param_set}}{(\code{paradox::ParamSet})\cr -The parameter set.} - -\item{\code{packages}}{(\code{character()})\cr -The packages the function depends on.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchTrafo-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchTrafo$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/pipeop_preproc_torch.Rd b/man/pipeop_preproc_torch.Rd new file mode 100644 index 00000000..a48b6123 --- /dev/null +++ b/man/pipeop_preproc_torch.Rd @@ -0,0 +1,50 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTaskPreprocTorch.R +\name{pipeop_preproc_torch} +\alias{pipeop_preproc_torch} +\title{Create a Torch Preprocessing PipeOp} +\usage{ +pipeop_preproc_torch( + id, + fn, + shapes_out = NULL, + param_set = NULL, + packages = character(), + per_column = TRUE +) +} +\arguments{ +\item{id}{(\code{character(1)})\cr +The ID of the \code{PipeOp}.} + +\item{fn}{(\code{function})\cr +The preprocessing function.} + +\item{shapes_out}{(\verb{function()} or \code{NULL}) +Will be set as private \verb{$.shapes_out()} method. +Can be left as \code{NULL} if the operation does not modify the shapes.} + +\item{param_set}{(\code{ParamSet} or \code{NULL})\cr +The parameter set of the \code{PipeOp}. +If left as \code{NULL}, parameters of type \code{\link{ParamUty}} will be created for all but the first argument +of function \code{fn}. They will have both tags \code{"train"} and \code{"predict"}.} + +\item{packages}{(\code{character()})\cr +The packages the \code{PipeOp} depends on.} + +\item{per_column}{(\code{logical(1)})\cr +Whether the preprecessing is applied column-wise.} +} +\value{ +\code{\link{R6Class}} instance inheriting ess_torchfrom \code{\link{PipeOpTaskPreprocTorch}} +} +\description{ +Utility function that makes implementing preprocessing pipeops easier. +You should read the documentation of \code{\link{PipeOpTaskPreprocTorch}} first. +} +\examples{ +po_device = pipeop_preproc_torch("to_device", + function(x, device) x$to(device = device) +) +po_device$param_set +} diff --git a/man/preproc_and_lazy.Rd b/man/preproc_and_lazy.Rd deleted file mode 100644 index 5822940b..00000000 --- a/man/preproc_and_lazy.Rd +++ /dev/null @@ -1,14 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preproc_and_trafo.R -\name{preproc_and_lazy} -\alias{preproc_and_lazy} -\alias{PipeOpTaskPreprocTorchResize} -\title{Lazy Preprocessing and Transformations} -\description{ -Lazy Preprocessing and Transformations -} -\section{Available PipeOps}{ - -The following -} - diff --git a/man/preprocessing_pipeops.Rd b/man/preprocessing_pipeops.Rd new file mode 100644 index 00000000..e7470f58 --- /dev/null +++ b/man/preprocessing_pipeops.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{preprocessing_pipeops} +\alias{preprocessing_pipeops} +\alias{PipeOpPreprocResize} +\title{Lazy Preprocessing and Transformations} +\description{ +Overview over all implemented preprocessing methods +} +\section{Available PipeOps}{ + +The following +} + +\section{preproc_resize}{ + +Resize a tensor to a given size +} + diff --git a/tests/testthat/helper_expectations.R b/tests/testthat/helper_expectations.R index c4087f74..1988be18 100644 --- a/tests/testthat/helper_expectations.R +++ b/tests/testthat/helper_expectations.R @@ -9,3 +9,8 @@ expect_learner_torch = function(learner, check_man = TRUE, check_id = TRUE) { expect_subset(c("loss", "optimizer", "callbacks"), formalArgs(learner$initialize)) expect_subset(c("mlr3", "mlr3torch", "torch"), learner$packages) } + +expect_torch_equal = function(...) { + expect_true(torch_equal(...)) +} + diff --git a/tests/testthat/test_PipeOpTaskPreprocTorch.R b/tests/testthat/test_PipeOpTaskPreprocTorch.R index ac7aa5c7..95d15a7f 100644 --- a/tests/testthat/test_PipeOpTaskPreprocTorch.R +++ b/tests/testthat/test_PipeOpTaskPreprocTorch.R @@ -1,9 +1,96 @@ -test_that("Correct errors", { +test_that("PipeOpTaskPreprocTorch: basic checks", { + po_test = po("preproc_torch", identity, packages = "R6") + expect_pipeop(po_test) + expect_equal(po_test$feature_types, "lazy_tensor") + expect_true(po_test$innum == 1L) + expect_true(po_test$outnum == 1L) + expect_class(po_test, "PipeOpTaskPreproc") + expect_true("R6" %in% po_test$packages) + expect_set_equal(po_test$param_set$ids(), c("augment", "affect_columns")) + expect_error(po("preproc_torch"), "is missing") + PipeOpTaskPreprocTorchTest = R6Class("PipeOpTaskPreprocTorchTest", + inherit = PipeOpTaskPreprocTorch, + public = list( + initialize = function(id = "test1", param_vals = list()) { + super$initialize( + id = id, + param_vals = param_vals, + fn = function(x) -x + ) + } + ), + private = list( + # check that shapes_out calls `$.shapes_out()` on each lazy tensor column + .shapes_out = function(shapes_in, param_vals, task) list(shapes_in[[1L]]) + ) + ) + + po_test1 = PipeOpTaskPreprocTorchTest$new(id = "test1") + expect_false("augment" %in% po_test1$param_set$ids()) + + shapes_in = list(c(NA, 1), c(NA, 1)) + expect_identical(shapes_in, po_test1$shapes_out(shapes_in)) + shapes_in1 = list(a = c(NA, 1), b = c(NA, 1)) + + expect_true(is.null(names(po_test1$shapes_out(shapes_in1)))) + + task = as_task_regr(data.table( + y = 1:10, + x1 = as_lazy_tensor(as.double(1:10)), + x2 = as_lazy_tensor(as.double(1:10)) + ), target = "y") + + po_test1$param_set$set_values( + affect_columns = selector_name("x1") + ) + + taskout1 = po_test1$train(list(task))[[1L]] + expect_torch_equal( + -materialize(taskout1$data(cols = "x1")[[1L]]), + materialize(taskout1$data(cols = "x2")[[1L]]) + ) + + # "train" and "predict" tags are respected + PipeOpTaskPreprocTorchTest2 = R6Class("PipeOpTaskPreprocTorchTest2", + inherit = PipeOpTaskPreprocTorch, + public = list( + initialize = function(id = "test2", param_vals = list()) { + param_set = ps( + a = p_int(tags = "train") + ) + super$initialize( + param_set = param_set, + id = id, + param_vals = param_vals, + fn = function(x, a = 2) x * a + ) + + } + ) + ) + + po_test2 = PipeOpTaskPreprocTorchTest2$new(param_vals = list(affect_columns = selector_name("x1"), a = 0)) + + expect_true( + torch_sum(materialize(po_test2$train(list(task))[[1L]]$data(cols = "x1")[[1L]]))$item() == 0 + ) + expect_true( + torch_sum(materialize(po_test2$predict(list(task))[[1L]]$data(cols = "x1")[[1L]]))$item() == 2 * sum(1:10) + ) + + # augment parameter works as intended (above augment was FALSE) + + po_test2$param_set$set_values( + augment = TRUE + ) + expect_true( + torch_sum(materialize(po_test2$predict(list(task))[[1L]]$data(cols = "x1")[[1L]]))$item() == sum(1:10) + ) }) -test_that("PipeOpTaskPreprocTorch works with one lazy tensor column", { +test_that("PipeOpTaskPreprocTorch modifies the underlying lazy tensor columns correctly", { d = data.table( y = 1:10, x = as_lazy_tensor(rnorm(10)) @@ -36,4 +123,37 @@ test_that("PipeOpTaskPreprocTorch works with one lazy tensor column", { ) }) -test_that("PipeOpTaskPreprocTorch works with multiple lazy tensor columns") +test_that("pipeop_preproc_torch works", { + expect_error( + pipeop_preproc_torch("abc", function(x) NULL, shapes_out = function(shapes) NULL), + "Must have formal" + ) + + po_test = pipeop_preproc_torch("abc", function(x, a) torch_cat(list(x, torch_pow(x, a)), dim = 2), + shapes_out = function(shapes_in, param_vals, task) { + s = shapes_in[[1L]] + s[2] = 2L + s + list(s) + } + ) + + expect_class(po_test, "PipeOpPreprocTorchAbc") + # parameter a was added + expect_set_equal(c("a", "affect_columns"), po_test$param_set$ids()) + + task = as_task_regr(data.table( + y = 2, + x = as_lazy_tensor(3) + ), target = "y") + + po_test$param_set$set_values( + a = 0 + ) + + taskout = po_test$train(list(task))[[1L]] + + x = materialize(taskout$data(cols = "x")[[1L]]) + expect_torch_equal(x[1, 1]$item(), 3) + expect_torch_equal(x[1, 2]$item(), 1) +}) From 9d4404fb5037acd31bf5c537211699d90f7ee3b9 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 20 Oct 2023 13:46:39 +0200 Subject: [PATCH 08/90] ... --- NAMESPACE | 3 +- R/DataBackendLazy.R | 2 +- R/DataDescriptor.R | 11 +- R/PipeOpTaskPreprocTorch.R | 194 ++++++++++++++++-- R/PipeOpTorch.R | 6 +- R/PipeOpTorchIngress.R | 2 +- R/preprocess.R | 165 ++++++++++++--- R/task_dataset.R | 2 + R/utils.R | 2 + man/DataDescriptor.Rd | 8 +- ..._torch.Rd => mlr_pipeops_preproc_torch.Rd} | 25 ++- man/mlr_pipeops_preproc_torch_overview.Rd | 16 ++ man/mlr_pipeops_torch.Rd | 5 +- man/pipeop_preproc_torch.Rd | 50 +++-- man/pipeop_preproc_torch_class.Rd | 57 +++++ man/preprocessing_pipeops.Rd | 19 -- tests/testthat/test_PipeOpTaskPreprocTorch.R | 26 ++- 17 files changed, 475 insertions(+), 118 deletions(-) rename man/{mlr_pipeops_task_preproc_torch.Rd => mlr_pipeops_preproc_torch.Rd} (94%) create mode 100644 man/mlr_pipeops_preproc_torch_overview.Rd create mode 100644 man/pipeop_preproc_torch_class.Rd delete mode 100644 man/preprocessing_pipeops.Rd diff --git a/NAMESPACE b/NAMESPACE index 81f5c6bb..a3c6c682 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -160,6 +160,7 @@ export(nn_reshape) export(nn_squeeze) export(nn_unsqueeze) export(pipeop_preproc_torch) +export(pipeop_preproc_torch_class) export(reset_last_layer) export(t_clbk) export(t_clbks) @@ -170,7 +171,7 @@ export(t_opts) export(task_dataset) export(torch_callback) export(transform_lazy_tensor) -exportPattern("^PipeOpPreproc") +exportPattern("^PipeOpPreprocTorch") import(checkmate) import(data.table) import(mlr3) diff --git a/R/DataBackendLazy.R b/R/DataBackendLazy.R index 9a156b80..9612e564 100644 --- a/R/DataBackendLazy.R +++ b/R/DataBackendLazy.R @@ -220,7 +220,7 @@ DataBackendLazy = R6Class("DataBackendLazy", ), private = list( .calculate_hash = function() { - suppressWarnings(get_private(self$backend)$.calculate_hash()) + get_private(self$backend)$.calculate_hash() }, .constructor = NULL, .backend = NULL, diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index 2978cd32..5714fcf0 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -28,6 +28,10 @@ #' has no batch dimension. #' @param clone_graph (`logical(1)`)\cr #' Whether to clone the preprocessing graph. +#' @param .info (any)\cr +#' Any additional meta-information. +#' This is used by [`PipeOpTaskPreprocTorch`] to communicate the 'would-be' predict shapes to ensure +#' during the `$train()` phase that `$predict()` will be possible as well. #' #' @export #' @seealso ModelDescriptor, lazy_tensor @@ -59,7 +63,7 @@ #' # with no preprocessing #' dd1 = DataDescriptor(ds, list(x = c(NA, 3, 3))) DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NULL, .pointer = NULL, - .pointer_shape = NULL, clone_graph = TRUE) { + .pointer_shape = NULL, clone_graph = TRUE, .info = list()) { assert_class(dataset, "dataset") assert_shapes(dataset_shapes) @@ -94,7 +98,7 @@ DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NU } # We get a warning that package:mlr3torch may not be available when loading (?) - dataset_hash = suppressWarnings(calculate_hash(dataset, dataset_shapes)) + dataset_hash = calculate_hash(dataset, dataset_shapes) obj = structure( list( dataset = dataset, @@ -107,7 +111,8 @@ DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NU .hash = NULL, # is set below # Once a DataDescriptor is created the input PipeOps are fix, we save them # here because they can be costly to compute - .graph_input = graph$input$name + .graph_input = graph$input$name, + .info = .info ), class = "DataDescriptor" ) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 5dd6c769..9a6a86d4 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -1,5 +1,5 @@ -#' @Base Class for Torch Preprocessing -#' @name mlr_pipeops_task_preproc_torch +#' @title Base Class for Torch Preprocessing +#' @name mlr_pipeops_preproc_torch #' #' @description #' This `PipeOp` can be used to preprocess (one or more) [`lazy_tensor`] columns contained in an [`mlr3::Task`]. @@ -34,6 +34,8 @@ #' Note that overwriting this method (currently) requires a solid understanding of the [`lazy_tensor`] internals. This might be made easier in the future. #' Note also that you need to pay attention to avoid name conflicts with existing columns in the task. #' +#' @template param_id +#' @template param_param_vals #' @param fn (`function`)\cr #' The preprocessing function. #' @param packages (`character()`)\cr @@ -47,6 +49,8 @@ #' Whether the transformation is applied per column. #' If this is `FALSE`, is applied to all lazy tensor columns at once and might produce #' one or more new lazy tensor columns. +#' @param augment_init (`logical(1)`)\cr +#' Initial value for the `augment` parameter. #' #' @section Input and Output Channels: #' See [`PipeOpTaskPreproc`]. @@ -57,7 +61,7 @@ #' as the argument `param_set` there are the following parameters: #' #' * `augment` :: `logical(1)`\cr -#' (This parameter only exists of the `PipeOp`) does not modify its input shapes. +#' (This parameter only exists of the `PipeOp`) is applied per column. #' Whether the to apply the preprocessing only during training (`TRUE`) or also during prediction (`FALSE`). #' This parameter is initialized to `FALSE`. #' @@ -170,17 +174,22 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", inherit = PipeOpTaskPreproc, public = list( - initialize = function(fn, id = "preproc_torch", param_vals = list(), param_set = ps(), packages = character(0), per_column = TRUE) { + #' @description + #' Creates a new instance of this [`R6`][R6::R6Class] class. + initialize = function(fn, id = "preproc_torch", param_vals = list(), param_set = ps(), packages = character(0), + per_column = TRUE, augment_init = FALSE) { private$.per_column = assert_flag(per_column) private$.fn = assert_function(fn, null.ok = per_column) + assert_flag(augment_init) - if (is.null(private$.shapes_out)) { + if (per_column) { param_set$add(ps( augment = p_lgl(tags = c("predict", "required")) )) - param_set$set_values(augment = FALSE) + param_set$set_values(augment = augment_init) } + super$initialize( id = id, param_vals = param_vals, @@ -197,8 +206,10 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' The input input shapes of the lazy tensors. #' @param task ([`Task`] or `NULL`)\cr #' The task, which is very rarely needed. + #' @param stage (`character(1)`)\cr + #' The stage: either `"train"` or `"predict"`. #' @return `list()` of `integer()` - shapes_out = function(shapes_in, task = NULL) { + shapes_out = function(shapes_in, stage = NULL, task = NULL) { assert_r6(task, "Task", null.ok = TRUE) assert_shapes(shapes_in, named = FALSE) names(shapes_in) = NULL @@ -208,9 +219,9 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", return(shapes_in) } - pv = self$param_set$get_values() + assert_choice(stage, c("train", "predict")) - torch_tensor(0) + pv = self$param_set$get_values(tags = stage) s = if (private$.per_column) { map(shapes_in, function(s) private$.shapes_out(list(s), param_vals = pv, task = task)[[1L]]) @@ -282,22 +293,32 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", } dt = map_dtc(dt, function(lt) { - # the ID of the `PipeOp` does not matter. - # By randomizing it we avoid ID clashes - po_fn = PipeOpModule$new( + # By randomizing the id we avoid ID clashes id = paste0(self$id, sample.int(.Machine$integer.max, 1)), module = fn, inname = self$input$name, outname = self$output$name, packages = self$packages ) - shape_out = self$shapes_out(list(lt$.pointer_shape), task)[[1L]] - transform_lazy_tensor(lt, po_fn, shape_out) + + shape_before = lt$.pointer_shape + shape_out = self$shapes_out(list(shape_before), stage = stage, task = task)[[1L]] + x = transform_lazy_tensor(lt, po_fn, shape_out) + dd = x$data_descriptor + + # During "train" we will also calculate the shapes that would arise during prediction, making + # some assumption that the task and the parameter values are the same. + # This is then later used in PipeOpTorchModel **before** starting the training to verify that + # a `$predict()` call is possible later. + if (stage == "train") { + shape_out_predict = self$shapes_out(list(shape_before), stage = "predict", task = task)[[1L]] + dd$.info$.pointer_shape_predict = shape_out_predict + attr(x, "data_descriptor") = dd + } + x }) - # we don't want name conflicts with other columns names(dt) = uniqueify(names(dt), setdiff(task$col_info$id, names(dt))) - # FIXME: names return(dt) }, .additional_phash_input = function() { @@ -308,8 +329,144 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", ) ) -pipeop_preproc_torch = function(fn, id, param_set = NULL) { - # TODO +#' @title Create Torch Preprocessing PipeOps +#' @description +#' Calls [`pipeop_preproc_torch_class`] and instantiates the instance with the given parameter values. +#' @inheritParams pipeop_preproc_torch_class +#' @param param_vals (`list()`)\cr +#' The parameter values. +#' @export +pipeop_preproc_torch = function(name, fn, shapes_out = NULL, param_set = NULL, param_vals = list(), + packages = character(0), per_column = TRUE, prefix = "trafo") { + pipeop_preproc_torch_class( + name = name, + fn = fn, + shapes_out = shapes_out, + param_set = param_set, + packages = packages, + per_column = per_column, + prefix = prefix + )$new(param_vals = param_vals) +} + + +create_ps_call = function(v) { + # Create an empty named list to store the arguments + args = list() + + # Iterate through the elements of v and create expressions + for (element in v) { + arg_name = as.name(element) + arg_value = rlang::expr(p_uty(tags = c("train", "predict"))) + args[[arg_name]] = arg_value + } + + # Create the final language object + result = rlang::expr(ps(!!!args)) + + return(result) +} + +#' @title Create Torch Preprocessing PipeOps +#' @description +#' Convenience functions to create objects of class [`PipeOpTaskPreprocTorch`] in a slightly more convenient way. +#' Start by reading the documentation of [`PipeOpTaskPreprocTorch`]. +#' @template param_id +#' @param fn (`function`)\cr +#' The preprocessing function. +#' @param shapes_out (`function` or `NULL` or `TRUE`)\cr +#' The private `.shapes_out(shapes_in, param_vals, task)` method of [`PipeOpTaskPreprocTorch`]. +#' If `NULL`, the pipeop does not change the output shapes. +#' If `TRUE`, the output shape function is inferred and calculates the output shapes as follows: +#' For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is +#' applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. +#' @param param_set ([`ParamSet`] or `NULL`)\cr +#' The parameter set. +#' If this is left as `NULL` (default) the parameter set is inferred in the following way: +#' All arguments but the first and `...` of `fn` are set as untyped parameters with tags 'train' and 'predict'. +#' Default values are not annotated. +#' @template param_param_vals +#' @template param_packages +#' @param per_column (`logical(1)`)\cr +#' Whether the preprocessing is applied per-column. +#' @export +#' @returns An [`R6Class`][R6::R6Class] instance inheriting from [`PipeOpTaskPreprocTorch`] +#' @examples +#' po_example = pipeop_preproc_torch("preproc_example", function(x, a) x + a) +#' po_example +#' po_example$param_set +pipeop_preproc_torch_class = function(name, fn, shapes_out = NULL, param_set = NULL, + packages = character(0), per_column = TRUE, prefix = "trafo") { + assert_string(name) + assert_function(fn) + if (!isTRUE(shapes_out)) { + assert_function(shapes_out, args = c("shapes_in", "param_vals", "task"), null.ok = TRUE) + } + assert_character(packages) + assert_flag(per_column) + + if (!is.null(param_set)) { + assert_param_set(param_set) + param_set = substitute(param_set) + } else { + param_names = setdiff(formalArgs(fn)[-1], "...") + param_set = create_ps_call(param_names) + } + + classname = paste0("PipeOpPreprocTorch", paste0(capitalize(strsplit(name, split = "_")[[1L]]), collapse = "")) + # Note that we don't set default values + + + if (isTRUE(shapes_out)) { + shapes_out = crate(function(shapes_in, param_vals, task) { + sin = shapes_in[[1L]] + # set batch-dim to 1 + sin[1] = 1L + tensor_in = invoke(torch_empty, .args = sin, device = torch_device("meta")) + tensor_out = invoke(private$.fn, tensor_in, .args = param_vals) + + sout = dim(tensor_out) + sout[1] = NA + list(sout) + }) + } + + idname = paste0(prefix, "_", name) + + init_fun = crate(function(id = idname, param_vals = list()) { + super$initialize( + id = id, + packages = packages, + param_set = ps, + param_vals = param_vals, + fn = fn + ) + }) + formals(init_fun)$id = idname + # param_set is already an expression + body(init_fun)[[2]][[3]] = substitute(packages) + body(init_fun)[[2]][[4]] = param_set + body(init_fun)[[2]][[6]] = substitute(fn) + + Class = R6Class(classname, + inherit = PipeOpTaskPreprocTorch, + public = list( + initialize = init_fun + ), + private = list( + .shapes_out = shapes_out + ) + ) + + return(Class) +} + +register_preproc = function(name, fn, param_set = NULL, shapes_out = NULL, packages, prefix = "trafo") { + id = register_po(paste0(prefix, "_", name), Class) + class = pipeop_preproc_torch_class(id, fn, param_set = param_set, shapes_out = shapes_out, packages = packages) + + register_po(id, class) + } @@ -334,4 +491,3 @@ pipeop_preproc_torch = function(fn, id, param_set = NULL) { register_po("preproc_torch", PipeOpTaskPreprocTorch) - diff --git a/R/PipeOpTorch.R b/R/PipeOpTorch.R index b4bc838e..2dbaa77a 100644 --- a/R/PipeOpTorch.R +++ b/R/PipeOpTorch.R @@ -283,10 +283,12 @@ PipeOpTorch = R6Class("PipeOpTorch", #' The input input shapes, which must be in the same order as the input channel names of the `PipeOp`. #' @param task ([`Task`] or `NULL`)\cr #' The task, which is very rarely used (default is `NULL`). An exception is [`PipeOpTorchHead`]. + #' @param stage (`character(1)`)\cr + #' Either `"train"` or `"predict"`. #' @return #' A named `list()` containing the output shapes. The names are the names of the output channels of #' the `PipeOp`. - shapes_out = function(shapes_in, task = NULL) { + shapes_out = function(shapes_in, task = NULL, stage) { assert_r6(task, "Task", null.ok = TRUE) if (is.numeric(shapes_in)) shapes_in = list(shapes_in) if (identical(self$input$name, "...")) { @@ -299,7 +301,7 @@ PipeOpTorch = R6Class("PipeOpTorch", shapes_in } else { pv = self$param_set$get_values() - private$.shapes_out(shapes_in, pv, task = task) + private$.shapes_out(shapes_in, pv, task = task, stage = stage) } set_names(s, self$output$name) diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index 3444ff95..43c8c4ea 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -351,7 +351,7 @@ PipeOpTorchIngressLazyTensor = R6Class("PipeOpTorchIngressLazyTensor", stopf("PipeOpTorchIngressLazyTensor expects 1 lazy_tensor feature, but got %i.", length(lazy_cols)) } example = task$data(task$row_ids[1L], lazy_cols)[[1L]][[1L]] - attr(example, "data_descriptor")$.pointer_shape + example$.pointer_shape }, .get_batchgetter = function(task, param_vals) { batchgetter_lazy_tensor diff --git a/R/preprocess.R b/R/preprocess.R index 7b4de7a3..fc77910c 100644 --- a/R/preprocess.R +++ b/R/preprocess.R @@ -1,34 +1,143 @@ #' @title Lazy Preprocessing and Transformations #' @description #' Overview over all implemented preprocessing methods. -#' See [`PipeOpTaskPreprocTorch`] for more details. -#' @name preprocessing_pipeops -#' @rawNamespace exportPattern("^PipeOpPreproc") +#' See [`PipeOpTaskPreprocTorch`] for more details on the class itself. +#' @section Overview: +#' * trafo_resize: Calls [`torchvision::transform_resize`] +#' @usage NULL +#' @format NULL +#' @name mlr_pipeops_preproc_torch_overview +#' @rawNamespace exportPattern("^PipeOpPreprocTorch") #' @include PipeOpTaskPreprocTorch.R -#' @section Available PipeOps: -#' The following NULL -#' @name PipeOpPreprocResize -#' @describeIn preprocessing_pipeops See [`torchvision::transform_resize`] -#' @rdname preprocessing_pipeops -#' @section preproc_resize: -#' Resize a tensor to a given size -register_preproc("resize", torchvision::transform_resize, - packages = "torchvision", - param_set = ps( - size = p_uty(tags = c("train", "required")), - interpolation = p_fct(levels = magick::filter_types(), special_vals = list(0L, 2L, 3L), - tags = "train", default = 2L - ) - ), - shapes_out = function(shapes_in, param_vals, task) { - size = param_vals$size - shape = shapes_in[[1L]] - assert_true(length(shape) > 2) - height = shape[[length(shape) - 1L]] - width = shape[[length(shape)]] - s = torchvision::transform_resize(torch_ones(c(1, height, width), device = "meta"), size = size)$shape[2:3] - list(c(shape[seq_len(length(shape) - 2L)], s)) - } -) +table_preproc = function() { + keys = names(mlr3torch_pipeops) + keys = keys[grepl("^preproc_(?!torch).*", keys, perl = TRUE)] + paste0("* ", keys) +} + +#' @name PipeOpPreprocTorchResize +#' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("resize", torchvision::transform_resize, +# packages = "torchvision", +# param_set = ps( +# size = p_uty(tags = c("train", "required")), +# interpolation = p_fct(levels = magick::filter_types(), special_vals = list(0L, 2L, 3L), +# tags = "train", default = 2L +# ) +# ), +# shapes_out = function(shapes_in, param_vals, task) { +# size = param_vals$size +# shape = shapes_in[[1L]] +# assert_true(length(shape) > 2) +# height = shape[[length(shape) - 1L]] +# width = shape[[length(shape)]] +# s = torchvision::transform_resize(torch_ones(c(1, height, width), device = "meta"), size = size)$shape[2:3] +# list(c(shape[seq_len(length(shape) - 2L)], s)) +# } +#) +# +# +##' @name PipeOpPreprocTorchAdjustGamma +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("adjust_gamma", torchvision::transform_adjust_gamma, packages = "torchvision" +#) +##' @name PipeOpPreprocTorchRandomCrop +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("random_crop", torchvision::transform_random_crop, packages = "torchvision", +# shapes_out = TRUE +#) +##' @name PipeOpPreprocTorchResizedCrop +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("resized_crop", torchvision::transform_resized_crop, packages = "torchvision") +##' @name PipeOpPreprocTorchColorJitter +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("color_jitter", torchvision::transform_color_jitter, torchvision::transform_color_jitter, packages = "torchvision") +##' @name PipeOpPreprocTorchGrayscale +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("grayscale", torchvision::transform_grayscale, packages = "torchvision") +##' @name PipeOpPreprocTorchRgdToGrayscale +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("rgb_to_grayscale", torchvision::transform_rgb_to_grayscale, packages = "torchvision") +##' @name PipeOpPreprocTorchRandomResizedCrop +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("random_resized_crop", torchvision::transform_random_resized_crop, packages = "torchvision") +##' @name PipeOpPreprocTorchFiveCrop +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("five_crop", torchvision::transform_five_crop, packages = "torchvision") +##' @name PipeOpPreprocTorchRandomOrder +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("random_order", torchvision::transform_random_order, packages = "torchvision") +##' @name PipeOpPreprocTorchNormalize +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("normalize", torchvision::transform_normalize, packages = "torchvision") +##' @name PipeOpPreprocTorchHflip +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("hflip", torchvision::transform_hflip, packages = "torchvision") +##' @name PipeOpPreprocTorchRandomRotation +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("random_rotation", torchvision::transform_random_rotation, packages = "torchvision") +##' @name PipeOpPreprocTorchRandomHorizontalFlip +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("random_horizontal_flip", torchvision::transform_random_horizontal_flip, packages = "torchvision") +##' @name PipeOpPreprocTorchLinerTransformation +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("linear_transformation", torchvision::transform_linear_transformation, packages = "torchvision") +##' @name PipeOpPreprocTorchCrop +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("crop", torchvision::transform_crop, packages = "torchvision") +##' @name PipeOpPreprocTorchTenCrop +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("ten_crop", torchvision::transform_ten_crop, packages = "torchvision") +##' @name PipeOpPreprocTorchRandomVerticalFlip +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("random_vertical_flip", torchvision::transform_random_vertical_flip, packages = "torchvision") +##' @name PipeOpPreprocTorchRandomGrayscale +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("random_grayscale", torchvision::transform_random_grayscale, packages = "torchvision") +##' @name PipeOpPreprocTorchAdjustHue +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("adjust_hue", torchvision::transform_adjust_hue, packages = "torchvision") +##' @name PipeOpPreprocTorchRandomAffine +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("random_affine", torchvision::transform_random_affine, packages = "torchvision") +##' @name PipeOpPreprocTorchRandomPerspective +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("random_perspective", torchvision::transform_random_perspective, packages = "torchvision") +##' @name PipeOpPreprocTorchVflip +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("vflip", torchvision::transform_vflip, packages = "torchvision") +##' @name PipeOpPreprocTorchRandomErasing +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("random_erasing", torchvision::transform_random_erasing, packages = "torchvision") +##' @name PipeOpPreprocTorchPerspective +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("perspective", torchvision::transform_perspective, packages = "torchvision") +##' @name PipeOpPreprocTorchRandomApply +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("random_apply", torchvision::transform_random_apply, packages = "torchvision") +##' @name PipeOpPreprocTorchRotate +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("rotate", torchvision::transform_rotate, packages = "torchvision") +##' @name PipeOpPreprocTorchAdjustContrast +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("adjust_contrast", torchvision::transform_adjust_contrast, packages = "torchvision") +##' @name PipeOpPreprocTorchPad +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("pad", torchvision::transform_pad, packages = "torchvision") +##' @name PipeOpPreprocTorchAdjustSaturation +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("adjust_saturation", torchvision::transform_adjust_saturation, packages = "torchvision") +##' @name PipeOpPreprocTorchCenterCrop +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("center_crop", torchvision::transform_center_crop, packages = "torchvision") +##' @name PipeOpPreprocTorchRandomChoice +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("random_choice", torchvision::transform_random_choice, packages = "torchvision") +##' @name PipeOpPreprocTorchAffine +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("affine", torchvision::transform_affine, packages = "torchvision") +##' @name PipeOpPreprocTorchAdjustBrightness +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("adjust_brightness", torchvision::transform_adjust_brightness, packages = "torchvision") diff --git a/R/task_dataset.R b/R/task_dataset.R index 0d009f9a..45461a46 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -52,7 +52,9 @@ task_dataset = dataset( # Here, we could have multiple `lazy_tensor` columns that share parts of the graph # We try to merge those graphs if possible + # FIXME: This must be tested, I don't think it works yet if (length(lazy_tensor_features) > 1L) { + stopf("Not working yet I think") # TODO: Inspect hashes of data descriptors to check whether caching is possible first_row = self$task$data(self$task$row_ids[1L], cols = lazy_tensor_features) graphs = map(first_row, function(x) attr(x, "data_descriptor")$graph) diff --git a/R/utils.R b/R/utils.R index 773e3e86..ae9d22d3 100644 --- a/R/utils.R +++ b/R/utils.R @@ -200,3 +200,5 @@ assert_lazy_tensor = function(x) { uniqueify = function(new, existing) { make.unique(c(existing, new), sep = "_")[length(existing) + seq_along(new)] } + + diff --git a/man/DataDescriptor.Rd b/man/DataDescriptor.Rd index 063f43c3..32f8bfe8 100644 --- a/man/DataDescriptor.Rd +++ b/man/DataDescriptor.Rd @@ -11,7 +11,8 @@ DataDescriptor( .input_map = NULL, .pointer = NULL, .pointer_shape = NULL, - clone_graph = TRUE + clone_graph = TRUE, + .info = list() ) } \arguments{ @@ -43,6 +44,11 @@ has no batch dimension.} \item{clone_graph}{(\code{logical(1)})\cr Whether to clone the preprocessing graph.} + +\item{.info}{(any)\cr +Any additional meta-information. +This is used by \code{\link{PipeOpTaskPreprocTorch}} to communicate the 'would-be' predict shapes to ensure +during the \verb{$train()} phase that \verb{$predict()} will be possible as well.} } \description{ A data descriptor is a rather internal structure used in the \code{\link{lazy_tensor}} data type. diff --git a/man/mlr_pipeops_task_preproc_torch.Rd b/man/mlr_pipeops_preproc_torch.Rd similarity index 94% rename from man/mlr_pipeops_task_preproc_torch.Rd rename to man/mlr_pipeops_preproc_torch.Rd index 8ed6fc83..beae7519 100644 --- a/man/mlr_pipeops_task_preproc_torch.Rd +++ b/man/mlr_pipeops_preproc_torch.Rd @@ -1,7 +1,7 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/PipeOpTaskPreprocTorch.R -\name{mlr_pipeops_task_preproc_torch} -\alias{mlr_pipeops_task_preproc_torch} +\name{mlr_pipeops_preproc_torch} +\alias{mlr_pipeops_preproc_torch} \alias{PipeOpTaskPreprocTorch} \title{Base Class for Torch Preprocessing} \description{ @@ -11,11 +11,7 @@ function can be defined through the \code{PipeOp}'s parameter set. The preprocessing is either done per-column in which case the number lazy tensor output columns is equivalent to the number of lazy tensor input columns. It is also possible to implement preprocessing that is applied to all lazy tensor columns at once and returns -one or more lazy tensor columns. -Note also that the preprocessing is always applied batch-wise. - -The convenience function \code{\link[=pipeop_preproc_torch]{pipeop_preproc_torch()}} can also be used to implement preprocessing pipeops -inheriting from this class. +one or more (not necessarily the same number) of lazy tensor columns. } \section{Inheriting}{ @@ -60,7 +56,7 @@ In addition to the parameters inherited from \code{\link{PipeOpTaskPreproc}} as as the argument \code{param_set} there are the following parameters: \itemize{ \item \code{augment} :: \code{logical(1)}\cr -(This parameter only exists of the \code{PipeOp}) does not modify its input shapes. +(This parameter only exists of the \code{PipeOp}) is applied per column. Whether the to apply the preprocessing only during training (\code{TRUE}) or also during prediction (\code{FALSE}). This parameter is initialized to \code{FALSE}. } @@ -197,7 +193,7 @@ materialize(taskout$data(cols = "x3")) \if{html}{\out{}} \if{latex}{\out{\hypertarget{method-PipeOpTaskPreprocTorch-new}{}}} \subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. +Creates a new instance of this \code{\link[R6:R6Class]{R6}} class. \subsection{Usage}{ \if{html}{\out{
}}\preformatted{PipeOpTaskPreprocTorch$new( fn, @@ -205,7 +201,8 @@ Creates a new instance of this \link[R6:R6Class]{R6} class. param_vals = list(), param_set = ps(), packages = character(0), - per_column = TRUE + per_column = TRUE, + augment_init = FALSE )}\if{html}{\out{
}} } @@ -234,6 +231,9 @@ The packages the preprocessing function depends on.} Whether the transformation is applied per column. If this is \code{FALSE}, is applied to all lazy tensor columns at once and might produce one or more new lazy tensor columns.} + +\item{\code{augment_init}}{(\code{logical(1)})\cr +Initial value for the \code{augment} parameter.} } \if{html}{\out{
}} } @@ -246,7 +246,7 @@ Calculates the output shapes that would result in applying the preprocessing to lazy tensor columns with the provided shape. Names are ignored and only order matters. \subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTaskPreprocTorch$shapes_out(shapes_in, task = NULL)}\if{html}{\out{
}} +\if{html}{\out{
}}\preformatted{PipeOpTaskPreprocTorch$shapes_out(shapes_in, stage = NULL, task = NULL)}\if{html}{\out{
}} } \subsection{Arguments}{ @@ -255,6 +255,9 @@ Names are ignored and only order matters. \item{\code{shapes_in}}{(\code{list()} of \code{integer()})\cr The input input shapes of the lazy tensors.} +\item{\code{stage}}{(\code{character(1)})\cr +The stage: either \code{"train"} or \code{"predict"}.} + \item{\code{task}}{(\code{\link{Task}} or \code{NULL})\cr The task, which is very rarely needed.} } diff --git a/man/mlr_pipeops_preproc_torch_overview.Rd b/man/mlr_pipeops_preproc_torch_overview.Rd new file mode 100644 index 00000000..e88ee649 --- /dev/null +++ b/man/mlr_pipeops_preproc_torch_overview.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch_overview} +\alias{mlr_pipeops_preproc_torch_overview} +\title{Lazy Preprocessing and Transformations} +\description{ +Overview over all implemented preprocessing methods. +See \code{\link{PipeOpTaskPreprocTorch}} for more details on the class itself. +} +\section{Overview}{ + +\itemize{ +\item trafo_resize: Calls \code{\link[torchvision:transform_resize]{torchvision::transform_resize}} +} +} + diff --git a/man/mlr_pipeops_torch.Rd b/man/mlr_pipeops_torch.Rd index e90db5c3..fad5ab9a 100644 --- a/man/mlr_pipeops_torch.Rd +++ b/man/mlr_pipeops_torch.Rd @@ -343,7 +343,7 @@ The tags of the \code{\link{PipeOp}}. The tags \code{"torch"} is always added.} \subsection{Method \code{shapes_out()}}{ Calculates the output shapes for the given input shapes, parameters and task. \subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorch$shapes_out(shapes_in, task = NULL)}\if{html}{\out{
}} +\if{html}{\out{
}}\preformatted{PipeOpTorch$shapes_out(shapes_in, task = NULL, stage)}\if{html}{\out{
}} } \subsection{Arguments}{ @@ -354,6 +354,9 @@ The input input shapes, which must be in the same order as the input channel nam \item{\code{task}}{(\code{\link{Task}} or \code{NULL})\cr The task, which is very rarely used (default is \code{NULL}). An exception is \code{\link{PipeOpTorchHead}}.} + +\item{\code{stage}}{(\code{character(1)})\cr +Either \code{"train"} or \code{"predict"}.} } \if{html}{\out{
}} } diff --git a/man/pipeop_preproc_torch.Rd b/man/pipeop_preproc_torch.Rd index a48b6123..2556d0b1 100644 --- a/man/pipeop_preproc_torch.Rd +++ b/man/pipeop_preproc_torch.Rd @@ -2,49 +2,45 @@ % Please edit documentation in R/PipeOpTaskPreprocTorch.R \name{pipeop_preproc_torch} \alias{pipeop_preproc_torch} -\title{Create a Torch Preprocessing PipeOp} +\title{Create Torch Preprocessing PipeOps} \usage{ pipeop_preproc_torch( - id, + name, fn, shapes_out = NULL, param_set = NULL, - packages = character(), - per_column = TRUE + param_vals = list(), + packages = character(0), + per_column = TRUE, + prefix = "trafo" ) } \arguments{ -\item{id}{(\code{character(1)})\cr -The ID of the \code{PipeOp}.} - \item{fn}{(\code{function})\cr The preprocessing function.} -\item{shapes_out}{(\verb{function()} or \code{NULL}) -Will be set as private \verb{$.shapes_out()} method. -Can be left as \code{NULL} if the operation does not modify the shapes.} +\item{shapes_out}{(\code{function} or \code{NULL} or \code{TRUE})\cr +The private \code{.shapes_out(shapes_in, param_vals, task)} method of \code{\link{PipeOpTaskPreprocTorch}}. +If \code{NULL}, the pipeop does not change the output shapes. +If \code{TRUE}, the output shape function is inferred and calculates the output shapes as follows: +For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is +applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned.} + +\item{param_set}{(\code{\link{ParamSet}} or \code{NULL})\cr +The parameter set. +If this is left as \code{NULL} (default) the parameter set is inferred in the following way: +All arguments but the first and \code{...} of \code{fn} are set as untyped parameters with tags 'train' and 'predict'. +Default values are not annotated.} -\item{param_set}{(\code{ParamSet} or \code{NULL})\cr -The parameter set of the \code{PipeOp}. -If left as \code{NULL}, parameters of type \code{\link{ParamUty}} will be created for all but the first argument -of function \code{fn}. They will have both tags \code{"train"} and \code{"predict"}.} +\item{param_vals}{(\code{list()})\cr +The parameter values.} \item{packages}{(\code{character()})\cr -The packages the \code{PipeOp} depends on.} +The R packages this object depends on.} \item{per_column}{(\code{logical(1)})\cr -Whether the preprecessing is applied column-wise.} -} -\value{ -\code{\link{R6Class}} instance inheriting ess_torchfrom \code{\link{PipeOpTaskPreprocTorch}} +Whether the preprocessing is applied per-column.} } \description{ -Utility function that makes implementing preprocessing pipeops easier. -You should read the documentation of \code{\link{PipeOpTaskPreprocTorch}} first. -} -\examples{ -po_device = pipeop_preproc_torch("to_device", - function(x, device) x$to(device = device) -) -po_device$param_set +Calls \code{\link{pipeop_preproc_torch_class}} and instantiates the instance with the given parameter values. } diff --git a/man/pipeop_preproc_torch_class.Rd b/man/pipeop_preproc_torch_class.Rd new file mode 100644 index 00000000..4c40017f --- /dev/null +++ b/man/pipeop_preproc_torch_class.Rd @@ -0,0 +1,57 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTaskPreprocTorch.R +\name{pipeop_preproc_torch_class} +\alias{pipeop_preproc_torch_class} +\title{Create Torch Preprocessing PipeOps} +\usage{ +pipeop_preproc_torch_class( + name, + fn, + shapes_out = NULL, + param_set = NULL, + packages = character(0), + per_column = TRUE, + prefix = "trafo" +) +} +\arguments{ +\item{fn}{(\code{function})\cr +The preprocessing function.} + +\item{shapes_out}{(\code{function} or \code{NULL} or \code{TRUE})\cr +The private \code{.shapes_out(shapes_in, param_vals, task)} method of \code{\link{PipeOpTaskPreprocTorch}}. +If \code{NULL}, the pipeop does not change the output shapes. +If \code{TRUE}, the output shape function is inferred and calculates the output shapes as follows: +For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is +applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned.} + +\item{param_set}{(\code{\link{ParamSet}} or \code{NULL})\cr +The parameter set. +If this is left as \code{NULL} (default) the parameter set is inferred in the following way: +All arguments but the first and \code{...} of \code{fn} are set as untyped parameters with tags 'train' and 'predict'. +Default values are not annotated.} + +\item{packages}{(\code{character()})\cr +The R packages this object depends on.} + +\item{per_column}{(\code{logical(1)})\cr +Whether the preprocessing is applied per-column.} + +\item{id}{(\code{character(1)})\cr +The id for of the new object.} + +\item{param_vals}{(named \code{list()})\cr +Parameter values to be set after construction.} +} +\value{ +An \code{\link[R6:R6Class]{R6Class}} instance inheriting from \code{\link{PipeOpTaskPreprocTorch}} +} +\description{ +Convenience functions to create objects of class \code{\link{PipeOpTaskPreprocTorch}} in a slightly more convenient way. +Start by reading the documentation of \code{\link{PipeOpTaskPreprocTorch}}. +} +\examples{ +po_example = pipeop_preproc_torch("preproc_example", function(x, a) x + a) +po_example +po_example$param_set +} diff --git a/man/preprocessing_pipeops.Rd b/man/preprocessing_pipeops.Rd deleted file mode 100644 index e7470f58..00000000 --- a/man/preprocessing_pipeops.Rd +++ /dev/null @@ -1,19 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{preprocessing_pipeops} -\alias{preprocessing_pipeops} -\alias{PipeOpPreprocResize} -\title{Lazy Preprocessing and Transformations} -\description{ -Overview over all implemented preprocessing methods -} -\section{Available PipeOps}{ - -The following -} - -\section{preproc_resize}{ - -Resize a tensor to a given size -} - diff --git a/tests/testthat/test_PipeOpTaskPreprocTorch.R b/tests/testthat/test_PipeOpTaskPreprocTorch.R index 95d15a7f..7949f0f6 100644 --- a/tests/testthat/test_PipeOpTaskPreprocTorch.R +++ b/tests/testthat/test_PipeOpTaskPreprocTorch.R @@ -27,13 +27,14 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { ) po_test1 = PipeOpTaskPreprocTorchTest$new(id = "test1") - expect_false("augment" %in% po_test1$param_set$ids()) + expect_true("augment" %in% po_test1$param_set$ids()) shapes_in = list(c(NA, 1), c(NA, 1)) - expect_identical(shapes_in, po_test1$shapes_out(shapes_in)) + expect_identical(shapes_in, po_test1$shapes_out(shapes_in, stage = "train")) + expect_identical(shapes_in, po_test1$shapes_out(shapes_in, stage = "predict")) shapes_in1 = list(a = c(NA, 1), b = c(NA, 1)) - expect_true(is.null(names(po_test1$shapes_out(shapes_in1)))) + expect_true(is.null(names(po_test1$shapes_out(shapes_in1, "train")))) task = as_task_regr(data.table( y = 1:10, @@ -140,7 +141,7 @@ test_that("pipeop_preproc_torch works", { expect_class(po_test, "PipeOpPreprocTorchAbc") # parameter a was added - expect_set_equal(c("a", "affect_columns"), po_test$param_set$ids()) + expect_set_equal(c("a", "affect_columns", "augment"), po_test$param_set$ids()) task = as_task_regr(data.table( y = 2, @@ -156,4 +157,21 @@ test_that("pipeop_preproc_torch works", { x = materialize(taskout$data(cols = "x")[[1L]]) expect_torch_equal(x[1, 1]$item(), 3) expect_torch_equal(x[1, 2]$item(), 1) + + po_test1 = pipeop_preproc_torch("test1", torchvision::transform_resize, shapes_out = TRUE, + param_vals = list(size = c(10, 10)) + ) + + po_test$shapes_out(list(c(NA, 20, 20)), "train") +}) + +test_that("predict shapes are added during training", { + po_test = pipeop_preproc_torch("test", function(x) torch_cat(list(x, x * 2), dim = 2)) + task = as_task_regr(data.table( + y = 1, + x = as_lazy_tensor(1) + ), target = "y") + + taskout = po_test$train(list(task))[[1L]] + }) From 8636cd33326191a875f033da218eceb955b04c84 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Thu, 26 Oct 2023 18:02:03 +0200 Subject: [PATCH 09/90] tests passing --- DESCRIPTION | 1 - NAMESPACE | 2 +- R/DataDescriptor.R | 136 -------------- R/LearnerTorch.R | 59 ++++-- R/PipeOpTaskPreprocTorch.R | 173 +++++++++++------- R/PipeOpTorch.R | 12 +- R/PipeOpTorchIngress.R | 3 +- R/PipeOpTorchLoss.R | 4 +- R/TaskClassif_tiny_imagenet.R | 4 +- R/lazy_tensor.R | 159 +++++++++++++++- R/materialize.R | 83 +++++++-- R/preprocess.R | 99 +++++----- R/utils.R | 41 +++-- R/zzz.R | 31 +++- man/DataDescriptor.Rd | 4 +- man/assert_shape.Rd | 18 ++ man/lazy_tensor.Rd | 2 +- man/materialize.Rd | 16 +- man/materialize_internal.Rd | 11 +- man/mlr_learners.alexnet.Rd | 4 +- man/mlr_learners.mlp.Rd | 4 +- man/mlr_learners.torch_featureless.Rd | 4 +- man/mlr_learners_torch.Rd | 51 +++++- man/mlr_learners_torch_image.Rd | 4 +- man/mlr_learners_torch_model.Rd | 4 +- man/mlr_pipeops_preproc_torch.Rd | 52 +++--- man/mlr_pipeops_preproc_torch_overview.Rd | 1 + man/mlr_pipeops_torch.Rd | 2 +- man/pipeop_preproc_torch.Rd | 16 +- man/pipeop_preproc_torch_class.Rd | 19 +- man/transform_lazy_tensor.Rd | 50 ----- tests/testthat/helper_autotest.R | 4 +- tests/testthat/helper_functions.R | 4 +- tests/testthat/setup.R | 4 + tests/testthat/teardown.R | 1 + tests/testthat/test_DataDescriptor.R | 32 ---- tests/testthat/test_LearnerTorch.R | 5 + tests/testthat/test_PipeOpTaskPreprocTorch.R | 37 ++-- tests/testthat/test_PipeOpTorch.R | 4 +- .../testthat/test_PipeOpTorchLazyTransform.R | 40 ---- tests/testthat/test_lazy_tensor.R | 77 +++++++- tests/testthat/test_materialize.R | 41 ++++- tests/testthat/test_preproc_and_trafo.R | 1 - tests/testthat/test_task_dataset.R | 15 -- tests/testthat/test_utils.R | 28 +++ 45 files changed, 803 insertions(+), 559 deletions(-) delete mode 100644 R/DataDescriptor.R create mode 100644 man/assert_shape.Rd delete mode 100644 man/transform_lazy_tensor.Rd delete mode 100644 tests/testthat/test_DataDescriptor.R delete mode 100644 tests/testthat/test_PipeOpTorchLazyTransform.R delete mode 100644 tests/testthat/test_preproc_and_trafo.R diff --git a/DESCRIPTION b/DESCRIPTION index 8e7ddf68..afce1fc1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -83,7 +83,6 @@ Collate: 'CallbackSetProgress.R' 'ContextTorch.R' 'DataBackendLazy.R' - 'DataDescriptor.R' 'LearnerTorch.R' 'LearnerTorchImage.R' 'LearnerTorchAlexNet.R' diff --git a/NAMESPACE b/NAMESPACE index a3c6c682..41e6f200 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -170,7 +170,6 @@ export(t_opt) export(t_opts) export(task_dataset) export(torch_callback) -export(transform_lazy_tensor) exportPattern("^PipeOpPreprocTorch") import(checkmate) import(data.table) @@ -183,5 +182,6 @@ import(vctrs) importFrom(R6,R6Class) importFrom(R6,is.R6) importFrom(methods,formalArgs) +importFrom(rlang,"!!") importFrom(tools,R_user_dir) importFrom(utils,getFromNamespace) diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R deleted file mode 100644 index 5714fcf0..00000000 --- a/R/DataDescriptor.R +++ /dev/null @@ -1,136 +0,0 @@ -#' @title Data Descriptor -#' -#' @description -#' A data descriptor is a rather internal structure used in the [`lazy_tensor`] data type. -#' In essence it is an annotated [`torch::dataset`] and a preprocessing graph (consisting mosty of [`PipeOpModule`] -#' operators). The additional meta data (e.g. shapes) allows to preprocess [`lazy_tensors`] in an -#' [`mlr3pipelines::Graph`] just like any (non-lazy) data types. -#' -#' @param dataset ([`torch::dataset`])\cr -#' The torch dataset. -#' @param dataset_shapes (named `list()` of `integer()`s)\cr -#' The shapes of the output. -#' Names are the elements of the list returned by the dataset. -#' First dimension must be `NA`. -#' @param graph ([`Graph`])\cr -#' The preprocessing graph. -#' If left `NULL`, no preprocessing is applied to the data and `.input_map`, `.pointer` and `.pointer_shape` -#' are inferred in case the dataset returns only one element. -#' @param .input_map (`character()`)\cr -#' Character vector that must have the same length as the input of the graph. -#' Specifies how the data from the `dataset` is fed into the preprocessing graph. -#' @param .pointer (`character(2)` | `NULL`)\cr -#' Indicating an element on which a model is. Points to an output channel within `graph`: -#' Element 1 is the `PipeOp`'s id and element 2 is that `PipeOp`'s output channel. -#' @param .pointer_shape (`integer` | `NULL`)\cr -#' Shape of the output indicated by `.pointer`. Note that this is **without** the batch dimension as opposed -#' to the [`ModelDescriptor`]. The reason is that the .pointer_shape refers to exactly one element and hence -#' has no batch dimension. -#' @param clone_graph (`logical(1)`)\cr -#' Whether to clone the preprocessing graph. -#' @param .info (any)\cr -#' Any additional meta-information. -#' This is used by [`PipeOpTaskPreprocTorch`] to communicate the 'would-be' predict shapes to ensure -#' during the `$train()` phase that `$predict()` will be possible as well. -#' -#' @export -#' @seealso ModelDescriptor, lazy_tensor -#' @examples -#' # Create a dataset -#' dsg = dataset( -#' initialize = function() self$x = torch_randn(10, 3, 3), -#' .getitem = function(i) self$x[i, ], -#' .length = function() nrow(self$x) -#' ) -#' ds = dsg() -#' -#' # Create the preprocessing graph -#' po_module = po("module", module = function(x) torch_reshape(x, c(-1, 9))) -#' po_module$output -#' graph = as_graph(po_module) -#' -#' # Create the data descriptor -#' -#' dd = DataDescriptor( -#' dataset = ds, -#' dataset_shapes = list(x = c(NA, 3, 3)), -#' graph = graph, -#' .input_map = "x", -#' .pointer = c("module", "output"), -#' .pointer_shape = c(NA, 9) -#' ) -#' -#' # with no preprocessing -#' dd1 = DataDescriptor(ds, list(x = c(NA, 3, 3))) -DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NULL, .pointer = NULL, - .pointer_shape = NULL, clone_graph = TRUE, .info = list()) { - assert_class(dataset, "dataset") - assert_shapes(dataset_shapes) - - if (is.null(graph)) { - if ((length(dataset_shapes) == 1L) && is.null(.input_map)) { - .input_map = names(dataset_shapes) - } - assert_true(length(.input_map) == 1L) - assert_subset(.input_map, names(dataset_shapes)) - - graph = as_graph(po("nop", id = paste0(class(dataset)[[1L]], "_", .input_map))) - .pointer = c(graph$output$op.id, graph$output$channel.name) - .pointer_shape = dataset_shapes[[.input_map]] - } else { - graph = as_graph(graph) - if (clone_graph) { - graph = graph$clone(deep = TRUE) - } - assert_true(length(graph$pipeops) >= 1L) - - if (any(is.null(.input_map), is.null(.pointer), is.null(.pointer_shape))) { - stopf("When passing a graph you need to specify .input_map, .pointer and .pointer_shape.") - } - - assert_choice(.pointer[[1]], names(graph$pipeops)) - assert_choice(.pointer[[2]], graph$pipeops[[.pointer[[1]]]]$output$name) - assert_subset(paste0(.pointer, collapse = "."), graph$output$name) - assert_integerish(.pointer_shape, min.len = 1L) - - assert_subset(.input_map, names(dataset_shapes)) - assert_true(length(.input_map) == length(graph$input$name)) - } - - # We get a warning that package:mlr3torch may not be available when loading (?) - dataset_hash = calculate_hash(dataset, dataset_shapes) - obj = structure( - list( - dataset = dataset, - graph = graph, - dataset_shapes = dataset_shapes, - .input_map = .input_map, - .pointer = .pointer, - .pointer_shape = .pointer_shape, - .dataset_hash = dataset_hash, - .hash = NULL, # is set below - # Once a DataDescriptor is created the input PipeOps are fix, we save them - # here because they can be costly to compute - .graph_input = graph$input$name, - .info = .info - ), - class = "DataDescriptor" - ) - - obj = set_data_descriptor_hash(obj) - - return(obj) -} - -# TODO: printer - -set_data_descriptor_hash = function(data_descriptor) { - data_descriptor$.hash = calculate_hash( - data_descriptor$.dataset_hash, - data_descriptor$graph$hash, - data_descriptor$.input_map, - data_descriptor$.pointer, - data_descriptor$.pointer_shape - ) - return(data_descriptor) -} diff --git a/R/LearnerTorch.R b/R/LearnerTorch.R index c828465e..0d8747ff 100644 --- a/R/LearnerTorch.R +++ b/R/LearnerTorch.R @@ -199,6 +199,25 @@ LearnerTorch = R6Class("LearnerTorch", if (length(e)) { catn(str_indent("* Errors:", e)) } + }, + #' @description Train the learner. + #' @param task ([`Task`])\cr + #' The task. + #' @param row_ids (`integer()`)\cr + #' Which rows to use for trainin.g + train = function(task, row_ids = NULL) { + private$.verify_train_task(task, row_ids) + super$train(task, row_ids) + }, + #' @description Predict on a task. + #' @param task ([`Task`])\cr + #' The task. + #' @param row_ids (`integer()`)\cr + #' For which rows to predict. + #' @return ([`Prediction`]) + predict = function(task, row_ids = NULL) { + private$.verify_predict_task(task, row_ids) + super$predict(task, row_ids) } ), active = list( @@ -253,18 +272,6 @@ LearnerTorch = R6Class("LearnerTorch", # Should be handled outside of mlr3torch # Ideally we could rely on state$train_task, but there is this bug # https://github.com/mlr-org/mlr3/issues/947 - cols = c(task$feature_names, task$target_names) - ci_predict = task$col_info[get("id") %in% cols, c("id", "type", "levels")] - ci_train = self$model$task_col_info[get("id") %in% cols, c("id", "type", "levels")] - if (!test_equal_col_info(ci_train, ci_predict)) { # nolint - stopf(paste0( - "Predict task's `$col_info` does not match the train tasks' column info.\n", - "This will be handled more gracefully in the future.\n", - "Training column info:\n'%s'\n", - "Prediction column info:\n'%s'"), - paste0(capture.output(ci_train), collapse = "\n"), - paste0(capture.output(ci_predict), collapse = "\n")) - } param_vals = self$param_set$get_values(tags = "predict") param_vals$device = auto_device(param_vals$device) @@ -299,6 +306,34 @@ LearnerTorch = R6Class("LearnerTorch", .loss = NULL, .param_set_base = NULL, .callbacks = NULL, + .verify_train_task = function(task, row_ids) { + first_row = task$head(0) + iwalk(first_row, function(x, nm) { + if (!is_lazy_tensor(x)) return(NULL) + predict_shape = x$.info$.predict_shape + train_shape = x$.pointer_shape + # If no information on hypothetical predict shape is available we continue training + # This is e.g. the case when a completely un-preprocessed lazy tensor is used + # Otherwise we expect the predict_shape to be equal to the train shape + if (!is.null(predict_shape) && !identical(predict_shape, train_shape)) { + stopf("Lazy tensor column '%s' would have a different shape during training and prediction.", nm) + } + }) + }, + .verify_predict_task = function(task, row_ids) { + cols = c(task$feature_names, task$target_names) + ci_predict = task$col_info[get("id") %in% cols, c("id", "type", "levels")] + ci_train = self$model$task_col_info[get("id") %in% cols, c("id", "type", "levels")] + if (!test_equal_col_info(ci_train, ci_predict)) { # nolint + stopf(paste0( + "Predict task's `$col_info` does not match the train task's column info.\n", + "This will be handled more gracefully in the future.\n", + "Training column info:\n'%s'\n", + "Prediction column info:\n'%s'"), + paste0(capture.output(ci_train), collapse = "\n"), + paste0(capture.output(ci_predict), collapse = "\n")) + } + }, deep_clone = function(name, value) deep_clone(self, private, super, name, value) ) ) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 9a6a86d4..98d5ef38 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -3,36 +3,45 @@ #' #' @description #' This `PipeOp` can be used to preprocess (one or more) [`lazy_tensor`] columns contained in an [`mlr3::Task`]. -#' The function that is applied is specified as construction argument `fn` and additional arguments to this +#' The preprocessing function is specified as construction argument `fn` and additional arguments to this #' function can be defined through the `PipeOp`'s parameter set. -#' The preprocessing is either done per-column in which case the number lazy tensor output columns is equivalent +#' The preprocessing is usually done per-column in which case the number lazy tensor output columns is equivalent #' to the number of lazy tensor input columns. #' It is also possible to implement preprocessing that is applied to all lazy tensor columns at once and returns -#' one or more (not necessarily the same number) of lazy tensor columns. +#' one or more (not necessarily the same number of) lazy tensor columns. +#' The preprocessing that is applied during `$predict()` uses the parameters that were set during `$train()` +#' and not those that are set when performing the prediction. #' #' @section Inheriting: -#' In addition to specifying the parameters `fn`, `packages` and `param_set` during construction you can also overwrite -#' the private `.shapes_out()` or `.tranform()` methods: +#' In addition to specifying the construction arguments, you can overwrite the private `.shapes_out()` or +#' `.tranform()` methods: #' * `.shapes_out(shapes_in, param_vals, task)`\cr #' (`list()`, `list(), `Task` or `NULL`) -> `list()`\cr #' This private method calculates the output shapes of the lazy tensor columns that are created from applying #' the preprocessing. -#' -#' Also see the documentation of [`PipeOpTorch`] how to implement this method. +#' Note that the input shapes can be only contain NAs (e.g. (NA, NA, NA)), indicating that only the number of input +#' dimensions is known, but not the exact shape. +#' In this case the output shape should also only contain NAs. #' #' In case the construction argument `per_column` is `TRUE`, this private method only has the responsibility -#' to caclculate the output shapes for one input column, i.e. the input `shapes_in` can be assumed to have -#' exactly one shape vector for which it must calculate the output shapes. +#' to calculate the output shapes for one input column, i.e. the input `shapes_in` can be assumed to have +#' exactly one shape vector for which it must calculate the output shapes and return it as a `list()` of length 1. +#' +#' Also see the documentation of [`PipeOpTorch`] how to implement this method. #' #' * `.transform(dt, task, param_vals, stage)`\cr #' (`data.table()`, `Task`, `list()`, `character(1)`) -> `data.table()`\cr #' This method must only be overwritten when the the `per_column` construction argument is `FALSE`. #' It receives as inputs all selected lazy tensor columns, the input `Task` (already cloned), #' the paramer values, and whether the preprocessing is applied during training (stage is `"train"`) -#' or prediction (stage is `"predict"`). It needs to return a `data.table` with lazy tensor columns. -#' Note that the lazy tensor inputs should not be modified in-place. -#' Note that overwriting this method (currently) requires a solid understanding of the [`lazy_tensor`] internals. This might be made easier in the future. -#' Note also that you need to pay attention to avoid name conflicts with existing columns in the task. +#' or prediction (stage is `"predict"`). One should not work with the parameters currently set in the paramet set, +#' only use those passed as argument `param_vals`. These are the parameters that were specified during the `$train()` +#' call of the [`PipeOp`] (otherwise it cannot be ensured that the shapes encountered during `$predict()` can actually +#' be processed by the neural network). +#' The method must return a `data.table` with lazy tensor columns. +#' The lazy tensor input columns should **not** be modified in-place. +#' Overwriting this method (currently) requires a solid understanding of the [`lazy_tensor`] internals. +#' You also need to pay attention to avoid name conflicts with existing columns in the task. #' #' @template param_id #' @template param_param_vals @@ -42,7 +51,8 @@ #' The packages the preprocessing function depends on. #' @param param_set ([`ParamSet`])\cr #' In case the function `fn` takes additional parameter besides a [`torch_tensor()`] they can be -#' specfied as parameters. Pay attention to set the correct `tags` for the parameters: if tag `"train"` is present, +#' specfied as parameters. None of the parameters can have the [`"predict"`] tag. +#' Pay attention to set the correct `tags` for the parameters: if tag `"train"` is present, #' the preprocessing is applied during training and if tag `"predict"` is present, the preprocessing is applied #' during prediction (if `augment` is set to `FALSE`). #' @param per_column (`logical(1)`)\cr @@ -106,10 +116,10 @@ #' ) #' #' taskout_train = po_simple$train(list(taskin))[[1L]] -#' materialize(taskout_train$data(cols = c("x1", "x2"))) +#' materialize(taskout_train$data(cols = c("x1", "x2")), rbind = TRUE) #' #' taskout_predict_noaug = po_simple$predict(list(taskin))[[1L]] -#' materialize(taskout_predict_noaug$data(cols = c("x1", "x2"))) +#' materialize(taskout_predict_noaug$data(cols = c("x1", "x2")), rbind = TRUE) #' #' po_simple$param_set$set_values( #' augment = TRUE @@ -117,7 +127,7 @@ #' #' # transformation is not applied #' taskout_predict_aug = po_simple$predict(list(taskin))[[1L]] -#' materialize(taskout_predict_aug$data(cols = c("x1", "x2"))) +#' materialize(taskout_predict_aug$data(cols = c("x1", "x2")), rbind = TRUE) #' #' # Creating a more complex preprocessing PipeOp #' @@ -126,7 +136,7 @@ #' public = list( #' initialize = function(id = "preproc_poly", param_vals = list()) { #' param_set = paradox::ps( -#' n_degree = paradox::p_int(lower = 1L, tags = c("train", "predict", "required")) +#' n_degree = paradox::p_int(lower = 1L, tags = c("train", "required")) #' ) #' param_set$set_values( #' n_degree = 1L @@ -163,14 +173,10 @@ #' param_vals = list(n_degree = 3L, affect_columns = selector_name("x3")) #' ) #' -#' # Note that the 'augment' parameter is not present as the PipeOp -#' # modifies the input shape and must hence be applied during training **and** prediction -#' po_poly$param_set -#' #' po_poly$shapes_out(list(c(NA, 1L))) #' #' taskout = po_poly$train(list(taskin))[[1L]] -#' materialize(taskout$data(cols = "x3")) +#' materialize(taskout$data(cols = "x3"), rbind = TRUE) PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", inherit = PipeOpTaskPreproc, public = list( @@ -184,11 +190,13 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", if (per_column) { param_set$add(ps( - augment = p_lgl(tags = c("predict", "required")) + augment = p_lgl(tags = c("train", "required")) )) param_set$set_values(augment = augment_init) } - + if (some(param_set$tags, function(tags) "predict" %in% tags)) { + stopf("Parameter set cannot contain tags 'predict'.") + } super$initialize( id = id, @@ -211,6 +219,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' @return `list()` of `integer()` shapes_out = function(shapes_in, stage = NULL, task = NULL) { assert_r6(task, "Task", null.ok = TRUE) + assert_choice(stage, c("train", "predict")) assert_shapes(shapes_in, named = FALSE) names(shapes_in) = NULL @@ -219,9 +228,14 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", return(shapes_in) } - assert_choice(stage, c("train", "predict")) + pv = self$param_set$get_values(tags = "train") + augment = pv$augment + pv$augment = NULL + pv$affect_columns = NULL - pv = self$param_set$get_values(tags = stage) + if (stage == "predict") { + pv = if (augment) list() else pv + } s = if (private$.per_column) { map(shapes_in, function(s) private$.shapes_out(list(s), param_vals = pv, task = task)[[1L]]) @@ -236,17 +250,21 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", .train_task = function(task) { dt_columns = private$.select_cols(task) cols = dt_columns + param_vals = self$param_set$get_values(tags = "train") + param_vals$affect_columns = NULL + if (!length(cols)) { - self$state = list(dt_columns = dt_columns) + self$state = list(dt_columns = dt_columns, param_vals = param_vals) return(task) } dt = task$data(cols = cols) - param_vals = self$param_set$get_values(tags = "train") - param_vals$affect_columns = NULL - dt = private$.transform(dt, task, param_vals, "train") + self$state$param_vals = param_vals self$state$dt_columns = dt_columns + + dt = private$.transform(dt, task, param_vals, "train") + task$select(setdiff(task$feature_names, cols))$cbind(dt) }, .predict_task = function(task) { @@ -256,7 +274,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", } dt = task$data(cols = cols) - param_vals = self$param_set$get_values(tags = "predict") + param_vals = self$state$param_vals dt = private$.transform(dt, task, param_vals, "predict") res = task$select(setdiff(task$feature_names, cols))$cbind(dt) @@ -267,6 +285,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", trafo = private$.fn if (stage == "train") { + param_vals$augment = NULL fn = if (length(param_vals)) { crate(function(x) { invoke(.f = trafo, x, .args = param_vals) @@ -304,18 +323,20 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", shape_before = lt$.pointer_shape shape_out = self$shapes_out(list(shape_before), stage = stage, task = task)[[1L]] - x = transform_lazy_tensor(lt, po_fn, shape_out) - dd = x$data_descriptor + + shape_out_predict = if (stage == "train") { + shape_in_predict = if (is.null(lt$.info$.predict_shape)) shape_before + # during `$train()` we also keep track of the shapes that would arise during train + # This avoids that we first train a learner and then only notice during predict that the shapes + # during the predict phase are wrong + shape_out_predict = self$shapes_out(list(shape_before), stage = "predict", task = task)[[1L]] + } + x = transform_lazy_tensor(lt, po_fn, shape_out, shape_out_predict) # During "train" we will also calculate the shapes that would arise during prediction, making # some assumption that the task and the parameter values are the same. # This is then later used in PipeOpTorchModel **before** starting the training to verify that # a `$predict()` call is possible later. - if (stage == "train") { - shape_out_predict = self$shapes_out(list(shape_before), stage = "predict", task = task)[[1L]] - dd$.info$.pointer_shape_predict = shape_out_predict - attr(x, "data_descriptor") = dd - } x }) names(dt) = uniqueify(names(dt), setdiff(task$col_info$id, names(dt))) @@ -336,28 +357,36 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' @param param_vals (`list()`)\cr #' The parameter values. #' @export -pipeop_preproc_torch = function(name, fn, shapes_out = NULL, param_set = NULL, param_vals = list(), - packages = character(0), per_column = TRUE, prefix = "trafo") { +pipeop_preproc_torch = function(id, fn, shapes_out = NULL, param_set = NULL, param_vals = list(), + packages = character(0), per_column = TRUE) { pipeop_preproc_torch_class( - name = name, + id = id, fn = fn, shapes_out = shapes_out, param_set = param_set, packages = packages, - per_column = per_column, - prefix = prefix + per_column = per_column )$new(param_vals = param_vals) } -create_ps_call = function(v) { +create_ps_call = function(fn) { + fmls = rlang::fn_fmls(fn) + param_names = names(fmls) + param_names = setdiff(param_names[-1L], "...") + fmls = fmls[param_names] + is_required = map(fmls, function(x) x == rlang::missing_arg()) # Create an empty named list to store the arguments args = list() # Iterate through the elements of v and create expressions - for (element in v) { - arg_name = as.name(element) - arg_value = rlang::expr(p_uty(tags = c("train", "predict"))) + for (pname in param_names) { + arg_name = as.name(pname) + if (is_required[[pname]]) { + arg_value = rlang::expr(p_uty(tags = c("train", "required"))) + } else { + arg_value = rlang::expr(p_uty(tags = "train")) + } args[[arg_name]] = arg_value } @@ -378,12 +407,16 @@ create_ps_call = function(v) { #' The private `.shapes_out(shapes_in, param_vals, task)` method of [`PipeOpTaskPreprocTorch`]. #' If `NULL`, the pipeop does not change the output shapes. #' If `TRUE`, the output shape function is inferred and calculates the output shapes as follows: -#' For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is -#' applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. +#' a) The input shapes are known: +#' For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is +#' applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. +#' b) The input shapes are unknown (all NA): +#' The dimension is returned as is. #' @param param_set ([`ParamSet`] or `NULL`)\cr #' The parameter set. #' If this is left as `NULL` (default) the parameter set is inferred in the following way: -#' All arguments but the first and `...` of `fn` are set as untyped parameters with tags 'train' and 'predict'. +#' All parameters but the first and `...` of `fn` are set as untyped parameters with tags 'train' and those that +#' have nod default value are tagged as 'required' as well. #' Default values are not annotated. #' @template param_param_vals #' @template param_packages @@ -395,9 +428,9 @@ create_ps_call = function(v) { #' po_example = pipeop_preproc_torch("preproc_example", function(x, a) x + a) #' po_example #' po_example$param_set -pipeop_preproc_torch_class = function(name, fn, shapes_out = NULL, param_set = NULL, - packages = character(0), per_column = TRUE, prefix = "trafo") { - assert_string(name) +pipeop_preproc_torch_class = function(id, fn, shapes_out = NULL, param_set = NULL, + packages = character(0), per_column = TRUE) { + assert_string(id) assert_function(fn) if (!isTRUE(shapes_out)) { assert_function(shapes_out, args = c("shapes_in", "param_vals", "task"), null.ok = TRUE) @@ -406,33 +439,36 @@ pipeop_preproc_torch_class = function(name, fn, shapes_out = NULL, param_set = N assert_flag(per_column) if (!is.null(param_set)) { - assert_param_set(param_set) - param_set = substitute(param_set) + assert_param_set(eval(param_set)) } else { - param_names = setdiff(formalArgs(fn)[-1], "...") - param_set = create_ps_call(param_names) + # This should add required tags where it is applicable + param_set = create_ps_call(fn) } - classname = paste0("PipeOpPreprocTorch", paste0(capitalize(strsplit(name, split = "_")[[1L]]), collapse = "")) + classname = paste0("PipeOpPreprocTorch", paste0(capitalize(strsplit(id, split = "_")[[1L]]), collapse = "")) # Note that we don't set default values - if (isTRUE(shapes_out)) { shapes_out = crate(function(shapes_in, param_vals, task) { sin = shapes_in[[1L]] + if (all(is.na(sin))) { + # This is only TRUE if the preprocessing pipeop does not change the number of dimensions. + return(list(sin)) + } # set batch-dim to 1 sin[1] = 1L tensor_in = invoke(torch_empty, .args = sin, device = torch_device("meta")) tensor_out = invoke(private$.fn, tensor_in, .args = param_vals) sout = dim(tensor_out) + if (sout[1] != 1) { + stopf("The automatically inferred private .shapes_out() method for class '%s' is wrong.", classname) + } sout[1] = NA list(sout) }) } - idname = paste0(prefix, "_", name) - init_fun = crate(function(id = idname, param_vals = list()) { super$initialize( id = id, @@ -442,7 +478,7 @@ pipeop_preproc_torch_class = function(name, fn, shapes_out = NULL, param_set = N fn = fn ) }) - formals(init_fun)$id = idname + formals(init_fun)$id = id # param_set is already an expression body(init_fun)[[2]][[3]] = substitute(packages) body(init_fun)[[2]][[4]] = param_set @@ -461,12 +497,9 @@ pipeop_preproc_torch_class = function(name, fn, shapes_out = NULL, param_set = N return(Class) } -register_preproc = function(name, fn, param_set = NULL, shapes_out = NULL, packages, prefix = "trafo") { - id = register_po(paste0(prefix, "_", name), Class) - class = pipeop_preproc_torch_class(id, fn, param_set = param_set, shapes_out = shapes_out, packages = packages) - - register_po(id, class) - +register_preproc = function(id, fn, param_set = NULL, shapes_out = NULL, packages) { + Class = pipeop_preproc_torch_class(id, fn, param_set = substitute(param_set), shapes_out = shapes_out, packages = packages) + register_po(id, Class) } @@ -490,4 +523,4 @@ register_preproc = function(name, fn, param_set = NULL, shapes_out = NULL, packa # -register_po("preproc_torch", PipeOpTaskPreprocTorch) +register_po("preproc_torch", PipeOpTaskPreprocTorch, metainf = list(fn = identity)) diff --git a/R/PipeOpTorch.R b/R/PipeOpTorch.R index 2dbaa77a..6f9f4d76 100644 --- a/R/PipeOpTorch.R +++ b/R/PipeOpTorch.R @@ -257,8 +257,8 @@ PipeOpTorch = R6Class("PipeOpTorch", assert_character(packages, any.missing = FALSE) packages = union(packages, "torch") - input = data.table(name = inname, train = "ModelDescriptor", predict = "*") - output = data.table(name = outname, train = "ModelDescriptor", predict = "*") + input = data.table(name = inname, train = "ModelDescriptor", predict = "Task") + output = data.table(name = outname, train = "ModelDescriptor", predict = "Task") assert_r6(param_set, "ParamSet") #walk(param_set$params, function(p) { @@ -288,7 +288,7 @@ PipeOpTorch = R6Class("PipeOpTorch", #' @return #' A named `list()` containing the output shapes. The names are the names of the output channels of #' the `PipeOp`. - shapes_out = function(shapes_in, task = NULL, stage) { + shapes_out = function(shapes_in, task = NULL) { assert_r6(task, "Task", null.ok = TRUE) if (is.numeric(shapes_in)) shapes_in = list(shapes_in) if (identical(self$input$name, "...")) { @@ -301,7 +301,7 @@ PipeOpTorch = R6Class("PipeOpTorch", shapes_in } else { pv = self$param_set$get_values() - private$.shapes_out(shapes_in, pv, task = task, stage = stage) + private$.shapes_out(shapes_in, pv, task = task) } set_names(s, self$output$name) @@ -310,7 +310,7 @@ PipeOpTorch = R6Class("PipeOpTorch", # TODO: printer that calls the nn_module's printer ), private = list( - .shapes_out = function(shapes_in, param_vals, task) shapes_in, + .shapes_out = function(shapes_in, param_vals, task, stage) shapes_in, .shape_dependent_params = function(shapes_in, param_vals, task) param_vals, .make_module = function(shapes_in, param_vals, task) { do.call(self$module_generator, private$.shape_dependent_params(shapes_in, param_vals, task)) @@ -320,7 +320,7 @@ PipeOpTorch = R6Class("PipeOpTorch", input_pointers = map(inputs, ".pointer") input_shapes = map(inputs, ".pointer_shape") - assert_shapes(input_shapes) + assert_shapes(input_shapes, named = FALSE) # Now begin creating the result-object: it contains a merged version of all `inputs`' $graph slots etc. # The only thing missing afterwards is (1) integrating module_op to the merged $graph, and adding `.pointer`s. result_template = Reduce(model_descriptor_union, inputs) diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index 43c8c4ea..70b887b4 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -354,13 +354,14 @@ PipeOpTorchIngressLazyTensor = R6Class("PipeOpTorchIngressLazyTensor", example$.pointer_shape }, .get_batchgetter = function(task, param_vals) { + # FIXME: Various checks batchgetter_lazy_tensor } ) ) batchgetter_lazy_tensor = function(data, device, cache) { - materialize_internal(x = data[[1L]], device = device, cache = cache) + materialize_internal(x = data[[1L]], device = device, cache = cache, rbind = TRUE) } register_po("torch_ingress_ltnsr", PipeOpTorchIngressLazyTensor) diff --git a/R/PipeOpTorchLoss.R b/R/PipeOpTorchLoss.R index ae313f17..5ae51c50 100644 --- a/R/PipeOpTorchLoss.R +++ b/R/PipeOpTorchLoss.R @@ -64,5 +64,7 @@ PipeOpTorchLoss = R6Class("PipeOpTorchLoss", ) ) +# We set an arbitrary loss, so Dict -> DT conversion works + #' @include zzz.R TorchLoss.R -register_po("torch_loss", PipeOpTorchLoss) +register_po("torch_loss", PipeOpTorchLoss, metainf = list(loss = t_loss("mse"))) diff --git a/R/TaskClassif_tiny_imagenet.R b/R/TaskClassif_tiny_imagenet.R index 70ec51e8..3c85d282 100644 --- a/R/TaskClassif_tiny_imagenet.R +++ b/R/TaskClassif_tiny_imagenet.R @@ -75,7 +75,7 @@ constructor_tiny_imagenet = function(path) { } load_task_tiny_imagenet = function(id = "tiny_imagenet") { - cached_constructor = function() { + cached_constructor = crate(function() { # We need this as otherwise the factor level are differently ordered, # which causes the hard-coded col-info to be wrong for some locales # (whether a < A or A > a depends on the locale) @@ -85,7 +85,7 @@ load_task_tiny_imagenet = function(id = "tiny_imagenet") { dt$image = imageuri(dt$image) dt$..row_id = seq_len(nrow(dt)) DataBackendDataTable$new(data = dt, primary_key = "..row_id") - } + }) backend = DataBackendLazy$new( constructor = cached_constructor, diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index 0888418d..7afff374 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -1,4 +1,142 @@ -#' @title Create a lazy tensor +#' @title Data Descriptor +#' +#' @description +#' A data descriptor is a rather internal structure used in the [`lazy_tensor`] data type. +#' In essence it is an annotated [`torch::dataset`] and a preprocessing graph (consisting mosty of [`PipeOpModule`] +#' operators). The additional meta data (e.g. shapes) allows to preprocess [`lazy_tensors`] in an +#' [`mlr3pipelines::Graph`] just like any (non-lazy) data types. +#' +#' @param dataset ([`torch::dataset`])\cr +#' The torch dataset. +#' @param dataset_shapes (named `list()` of `integer()`s)\cr +#' The shapes of the output. +#' Names are the elements of the list returned by the dataset. +#' First dimension must be `NA`. +#' @param graph ([`Graph`])\cr +#' The preprocessing graph. +#' If left `NULL`, no preprocessing is applied to the data and `.input_map`, `.pointer` and `.pointer_shape` +#' are inferred in case the dataset returns only one element. +#' @param .input_map (`character()`)\cr +#' Character vector that must have the same length as the input of the graph. +#' Specifies how the data from the `dataset` is fed into the preprocessing graph. +#' @param .pointer (`character(2)` | `NULL`)\cr +#' Indicating an element on which a model is. Points to an output channel within `graph`: +#' Element 1 is the `PipeOp`'s id and element 2 is that `PipeOp`'s output channel. +#' @param .pointer_shape (`integer` | `NULL`)\cr +#' Shape of the output indicated by `.pointer`. Note that this is **without** the batch dimension as opposed +#' to the [`ModelDescriptor`]. The reason is that the .pointer_shape refers to exactly one element and hence +#' has no batch dimension. +#' @param clone_graph (`logical(1)`)\cr +#' Whether to clone the preprocessing graph. +#' @param .info (any)\cr +#' Any additional meta-information (internal). +#' This is used by [`PipeOpTaskPreprocTorch`] to communicate the 'would-be' predict shapes to ensure +#' during the `$train()` phase that `$predict()` will be possible as well. +#' +#' @export +#' @seealso ModelDescriptor, lazy_tensor +#' @examples +#' # Create a dataset +#' dsg = dataset( +#' initialize = function() self$x = torch_randn(10, 3, 3), +#' .getitem = function(i) self$x[i, ], +#' .length = function() nrow(self$x) +#' ) +#' ds = dsg() +#' +#' # Create the preprocessing graph +#' po_module = po("module", module = function(x) torch_reshape(x, c(-1, 9))) +#' po_module$output +#' graph = as_graph(po_module) +#' +#' # Create the data descriptor +#' +#' dd = DataDescriptor( +#' dataset = ds, +#' dataset_shapes = list(x = c(NA, 3, 3)), +#' graph = graph, +#' .input_map = "x", +#' .pointer = c("module", "output"), +#' .pointer_shape = c(NA, 9) +#' ) +#' +#' # with no preprocessing +#' dd1 = DataDescriptor(ds, list(x = c(NA, 3, 3))) +DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NULL, .pointer = NULL, + .pointer_shape = NULL, clone_graph = TRUE, .info = list()) { + assert_class(dataset, "dataset") + + # If the dataest implements a .getbatch() method the shaoe must be specified. + assert_shapes(dataset_shapes, unknown_ok = is.null(dataset$.getbatch)) + + if (is.null(graph)) { + if ((length(dataset_shapes) == 1L) && is.null(.input_map)) { + .input_map = names(dataset_shapes) + } + assert_true(length(.input_map) == 1L) + assert_subset(.input_map, names(dataset_shapes)) + + graph = as_graph(po("nop", id = paste0(class(dataset)[[1L]], "_", .input_map))) + .pointer = c(graph$output$op.id, graph$output$channel.name) + .pointer_shape = dataset_shapes[[.input_map]] + } else { + graph = as_graph(graph) + if (clone_graph) { + graph = graph$clone(deep = TRUE) + } + assert_true(length(graph$pipeops) >= 1L) + + if (any(is.null(.input_map), is.null(.pointer), is.null(.pointer_shape))) { + stopf("When passing a graph you need to specify .input_map, .pointer and .pointer_shape.") + } + + assert_choice(.pointer[[1]], names(graph$pipeops)) + assert_choice(.pointer[[2]], graph$pipeops[[.pointer[[1]]]]$output$name) + assert_subset(paste0(.pointer, collapse = "."), graph$output$name) + assert_shape(.pointer_shape, unknown_ok = TRUE) + + assert_subset(.input_map, names(dataset_shapes)) + assert_true(length(.input_map) == length(graph$input$name)) + } + + # We get a warning that package:mlr3torch may not be available when loading (?) + dataset_hash = calculate_hash(dataset, dataset_shapes) + obj = structure( + list( + dataset = dataset, + graph = graph, + dataset_shapes = dataset_shapes, + .input_map = .input_map, + .pointer = .pointer, + .pointer_shape = .pointer_shape, + .dataset_hash = dataset_hash, + .hash = NULL, # is set below + # Once a DataDescriptor is created the input PipeOps are fix, we save them + # here because they can be costly to compute + .graph_input = graph$input$name, + .info = .info + ), + class = "DataDescriptor" + ) + + obj = set_data_descriptor_hash(obj) + + return(obj) +} + +# TODO: printer + +set_data_descriptor_hash = function(data_descriptor) { + data_descriptor$.hash = calculate_hash( + data_descriptor$.dataset_hash, + data_descriptor$graph$hash, + data_descriptor$.input_map, + data_descriptor$.pointer, + data_descriptor$.pointer_shape + ) + return(data_descriptor) +} +#' @title Create a lazy tesornsor #' #' @description #' Create a lazy tensor. @@ -105,12 +243,12 @@ vec_ptype_abbr.lazy_tensor <- function(x, ...) { # nolint #' Object to check. #' @export is_lazy_tensor = function(x) { - inherits(x, "lazy_tensor") + test_class(x, "lazy_tensor") } #' @title Transform Lazy Tensor #' @description -#' transform a [`lazy_tensor`] vector by appending a preprocessing step. +#' Transform a [`lazy_tensor`] vector by appending a preprocessing step. #' #' @param lt ([`lazy_tensor`])\cr #' A lazy tensor vector. @@ -118,7 +256,9 @@ is_lazy_tensor = function(x) { #' The pipeop to be added to the preprocessing graph(s) of the lazy tensor. #' Must have one input and one output. #' @param shape (`integer()`)\cr -#' The shape of the lazy tensor (without the batch dimension). +#' The shape of the lazy tensor. +#' @param shape_predict (`integer()`)\cr +#' The shape of the lazy tensor if it was applied during `$predict()`. #' #' @details #' The following is done: @@ -136,20 +276,22 @@ is_lazy_tensor = function(x) { #' lt = as_lazy_tensor(1:10) #' add_five = po("module", module = function(x) x + 5) #' lt_plus_five = transform_lazy_tensor(lt, add_five, c(NA, 1)) -#' torch_cat(list(materialize(lt), materialize(lt_plus_five)), dim = 2) +#' torch_cat(list(materialize(lt, rbind = TRUE), materialize(lt_plus_five, rbind = TRUE)), dim = 2) #' # graph is cloned #' identical(lt$graph, lt_plus_five$graph) #' lt$graph$edges #' lt_plus_five$graph_edges #' # pipeops are not cloned #' identical(lt$graph$pipeops[[1]], lt_plus_five$graph[[1]]) -#' @export -transform_lazy_tensor = function(lt, pipeop, shape) { +#' @noRd +transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { assert_lazy_tensor(lt) assert_class(pipeop, "PipeOpModule") assert_true(nrow(pipeop$input) == 1L) assert_true(nrow(pipeop$output) == 1L) - assert_shape(shape) + assert_shape(shape, unknown_ok = TRUE) + # shape_predict can be NULL if we transform a tensor during `$predict()` in PipeOpTaskPreprocTorch + assert_shape(shape_predict, null_ok = TRUE, unknown_ok = TRUE) data_descriptor = attr(lt, "data_descriptor") @@ -166,6 +308,7 @@ transform_lazy_tensor = function(lt, pipeop, shape) { data_descriptor$.pointer = c(pipeop$id, pipeop$output$name) data_descriptor$.pointer_shape = shape + data_descriptor$.info$.pointer_shape_predict = shape_predict data_descriptor = set_data_descriptor_hash(data_descriptor) new_lazy_tensor(data_descriptor, vec_data(lt)) diff --git a/R/materialize.R b/R/materialize.R index bbe1e18a..91f48a6c 100644 --- a/R/materialize.R +++ b/R/materialize.R @@ -18,21 +18,30 @@ #' For this reason it is possible to provide a cache environment. #' The hash key for a) is the hash of the indices and the dataset. #' The hash key for b) is the hash of the indices dataset and preprocessing graph. +#' @param x (any)\cr +#' The object to materialize. +#' Either a [`lazy_tensor`] or a `list()` / `data.frame()` containing [`lazy_tensor`] columns. +#' @param rbind (`logical(1)`)\cr +#' Whether to rbind the lazy tensor columns (`TRUE`) or return them as a list of tensors (`FALSE`). #' @return ([`torch_tensor()`] or [`list()`]) #' @export #' @examples #' lt1 = as_lazy_tensor(torch_randn(10, 3)) -#' materialize(lt1) +#' materialize(lt1, rbind = TRUE) +#' materialize(lt1, rbind = FALSE) #' lt2 = as_lazy_tensor(torch_randn(10, 4)) #' d = data.frame(lt1 = lt1, lt2 = lt2) -#' materialize(d) -materialize = function(x, device = "cpu", ...) { +#' materialize(d, rbind = TRUE) +#' materialize(d, rbind = FALSE) +materialize = function(x, device = "cpu", rbind = FALSE, ...) { assert_choice(device, mlr_reflections$torch$devices) + assert_flag(rbind) UseMethod("materialize") } #' @export -materialize.list = function(x, device = "cpu") { # nolint +materialize.list = function(x, device = "cpu", rbind = FALSE) { # nolint + # FIXME: smarter cache detecting cache = if (sum(map_lgl(x, is_lazy_tensor)) > 1L) { new.env() } @@ -48,7 +57,7 @@ materialize.list = function(x, device = "cpu") { # nolint # clean up the keep_results after on.exit({walk(x, function(col) { # nolint if (is_lazy_tensor(x)) { - graph = attr(x, "data_descriptor")$graph + graph = x$graph graph$keep_results = keep_results_prev[[graph$hash]] } })}, add = TRUE) @@ -63,7 +72,7 @@ materialize.list = function(x, device = "cpu") { # nolint # TODO: No hashing when there is only one column map(x, function(col) { if (is_lazy_tensor(col)) { - materialize_internal(col, device = device, cache = cache, set_keep_results = FALSE) + materialize_internal(col, device = device, cache = cache, set_keep_results = FALSE, rbind = rbind) } else { col } @@ -72,18 +81,21 @@ materialize.list = function(x, device = "cpu") { # nolint #' @export -materialize.lazy_tensor = function(x, device = "cpu") { # nolint - materialize_internal(x = x, device = device, cache = NULL, set_keep_results = TRUE) +materialize.lazy_tensor = function(x, device = "cpu", rbind = FALSE) { # nolint + materialize_internal(x = x, device = device, cache = NULL, set_keep_results = TRUE, rbind = rbind) } #' @title Materialize a Lazy Tensor #' @description +#' Convert a [`lazy_tensor()`] to a [`torch_tensor()`]. +#' +#' @details #' Materializing a lazy tensor consists of: #' 1. Loading the data from the internal dataset of the [`DataDescriptor`]. #' 2. Processing these batches in the preprocessing [`Graph`]s. #' 3. Returning the result of the [`PipeOp`] pointed to by the [`DataDescriptor`] (`.pointer`). #' -#' With multiple [`lazy_tensor`] columns we can benefit from caching because: +#' When materializing multiple [`lazy_tensor`] columns, caching can be useful because: #' a) Output(s) from the dataset might be input to multiple graphs. #' b) Different lazy tensors might be outputs from the same graph. #' @@ -104,9 +116,14 @@ materialize.lazy_tensor = function(x, device = "cpu") { # nolint #' Therefore we have to include this as part of the `keep_results` field of the [`Graph`]. #' When caching is done, this should be set to `FALSE` as otherwise data will be discarded that might be relevant #' for materializing other lazy tensor columns. +#' @param rbind (`logical(1)`)\cr +#' Whtether to rbind the resulting tensors (`TRUE`) or return them as a list of tensors (`FALSE`). #' @return [`lazy_tensor()`] #' @keywords internal -materialize_internal = function(x, device = "cpu", cache = NULL, set_keep_results = is.null(cache)) { +materialize_internal = function(x, device = "cpu", cache = NULL, set_keep_results = is.null(cache), rbind) { + if (!length(x)) { + stopf("Cannot materialize lazy tensor of length 0.") + } do_caching = !is.null(cache) ids = vec_data(x) @@ -139,10 +156,18 @@ materialize_internal = function(x, device = "cpu", cache = NULL, set_keep_result if (!do_caching || !input_hit) { input = if (is.null(ds$.getbatch)) { # .getindex is never NULL but a function that errs if it was not defined - tmp = transpose_list(map(ids, function(id) map(ds$.getitem(id), function(x) x$unsqueeze(1)))) - map(tmp, function(x) torch_cat(x, dim = 1L)) + x = map(ids, function(id) map(ds$.getitem(id), function(x) x$unsqueeze(1))) + if (rbind) { + map(transpose_list(x), function(x) torch_cat(x, dim = 1L)) + } else { + x + } } else { - ds$.getbatch(ids) + if (rbind) { + ds$.getbatch(ids) + } else { + map(ids, function(id) ds$.getbatch(id)) + } } } @@ -155,11 +180,27 @@ materialize_internal = function(x, device = "cpu", cache = NULL, set_keep_result # This is done after retrieving the element from the cache / before saving the element to the cache because # this can change - input = set_names(input[data_descriptor$.input_map], data_descriptor$.graph_input) + input = if (rbind) { + set_names(input[data_descriptor$.input_map], data_descriptor$.graph_input) + } else { + map(input, function(x) { + set_names(x[data_descriptor$.input_map], data_descriptor$.graph_input) + }) + } - graph$train(input, single_input = FALSE) - output = map(data_descriptor$graph$keep_results, function(id) graph$pipeops[[id]]$.result) - output = set_names(output, data_descriptor$graph$keep_results) + output = if (rbind) { + # in this case, input is a tensor + graph$train(input, single_input = FALSE) + out = map(data_descriptor$graph$keep_results, function(id) graph$pipeops[[id]]$.result) + set_names(out, data_descriptor$graph$keep_results) + } else { + # in this case, input is a list of tensors + map(input, function(x) { + graph$train(x, single_input = FALSE) + out = map(data_descriptor$graph$keep_results, function(id) graph$pipeops[[id]]$.result) + set_names(out, data_descriptor$graph$keep_results) + }) + } if (do_caching) { cache[[output_hash]] = output @@ -168,7 +209,13 @@ materialize_internal = function(x, device = "cpu", cache = NULL, set_keep_result # discard the results walk(data_descriptor$graph$pipeops[data_descriptor$graph$keep_results], function(x) x$.result = NULL) - output[[data_descriptor$.pointer[1L]]][[data_descriptor$.pointer[2L]]]$to(device = device) + if (rbind) { + res = output[[data_descriptor$.pointer[1L]]][[data_descriptor$.pointer[2L]]]$to(device = device) + } else { + res = map(output, function(o) o[[data_descriptor$.pointer[1L]]][[data_descriptor$.pointer[2L]]]$to(device = device)) + } + + return(res) } diff --git a/R/preprocess.R b/R/preprocess.R index fc77910c..8bd0cdf3 100644 --- a/R/preprocess.R +++ b/R/preprocess.R @@ -17,49 +17,77 @@ table_preproc = function() { paste0("* ", keys) } -#' @name PipeOpPreprocTorchResize +#' @name PipeOpPreprocTorchTrafoResize #' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("resize", torchvision::transform_resize, -# packages = "torchvision", -# param_set = ps( -# size = p_uty(tags = c("train", "required")), -# interpolation = p_fct(levels = magick::filter_types(), special_vals = list(0L, 2L, 3L), -# tags = "train", default = 2L -# ) -# ), -# shapes_out = function(shapes_in, param_vals, task) { -# size = param_vals$size -# shape = shapes_in[[1L]] -# assert_true(length(shape) > 2) -# height = shape[[length(shape) - 1L]] -# width = shape[[length(shape)]] -# s = torchvision::transform_resize(torch_ones(c(1, height, width), device = "meta"), size = size)$shape[2:3] -# list(c(shape[seq_len(length(shape) - 2L)], s)) -# } -#) -# +register_preproc("trafo_resize", torchvision::transform_resize, + packages = "torchvision", + param_set = ps( + size = p_uty(tags = c("train", "required")), + interpolation = p_fct(levels = magick::filter_types(), special_vals = list(0L, 2L, 3L), + tags = "train", default = 2L + ) + ), + shapes_out = function(shapes_in, param_vals, task) { + size = param_vals$size + shape = shapes_in[[1L]] + assert_true(length(shape) > 2) + height = shape[[length(shape) - 1L]] + width = shape[[length(shape)]] + s = torchvision::transform_resize(torch_ones(c(1, height, width), device = "meta"), size = size)$shape[2:3] + list(c(shape[seq_len(length(shape) - 2L)], s)) + } +) + + + +## Preprocessing: # ##' @name PipeOpPreprocTorchAdjustGamma ##' @rdname mlr_pipeops_preproc_torch_overview #register_preproc("adjust_gamma", torchvision::transform_adjust_gamma, packages = "torchvision" #) +# +##' @name PipeOpPreprocTorchAdjustBrightness +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("adjust_brightness", torchvision::transform_adjust_brightness, packages = "torchvision") +# +##' @name PipeOpPreprocTorchAdjustHue +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("adjust_hue", torchvision::transform_adjust_hue, packages = "torchvision") +# ##' @name PipeOpPreprocTorchRandomCrop ##' @rdname mlr_pipeops_preproc_torch_overview #register_preproc("random_crop", torchvision::transform_random_crop, packages = "torchvision", # shapes_out = TRUE #) -##' @name PipeOpPreprocTorchResizedCrop -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("resized_crop", torchvision::transform_resized_crop, packages = "torchvision") -##' @name PipeOpPreprocTorchColorJitter +# +##' @name PipeOpPreprocTorchAdjustSaturation ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("color_jitter", torchvision::transform_color_jitter, torchvision::transform_color_jitter, packages = "torchvision") +#register_preproc("adjust_saturation", torchvision::transform_adjust_saturation, packages = "torchvision") +# ##' @name PipeOpPreprocTorchGrayscale ##' @rdname mlr_pipeops_preproc_torch_overview #register_preproc("grayscale", torchvision::transform_grayscale, packages = "torchvision") ##' @name PipeOpPreprocTorchRgdToGrayscale ##' @rdname mlr_pipeops_preproc_torch_overview #register_preproc("rgb_to_grayscale", torchvision::transform_rgb_to_grayscale, packages = "torchvision") +# +##' @name PipeOpPreprocTorchNormalize +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("normalize", torchvision::transform_normalize, packages = "torchvision") +# +##' @name PipeOpPreprocTorchPad +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("pad", torchvision::transform_pad, packages = "torchvision") +# +## Data Augmentation: +# +##' @name PipeOpPreprocTorchResizedCrop +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("resized_crop", torchvision::transform_resized_crop, packages = "torchvision") +##' @name PipeOpPreprocTorchColorJitter +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("color_jitter", torchvision::transform_color_jitter, torchvision::transform_color_jitter, packages = "torchvision") ##' @name PipeOpPreprocTorchRandomResizedCrop ##' @rdname mlr_pipeops_preproc_torch_overview #register_preproc("random_resized_crop", torchvision::transform_random_resized_crop, packages = "torchvision") @@ -69,9 +97,6 @@ table_preproc = function() { ##' @name PipeOpPreprocTorchRandomOrder ##' @rdname mlr_pipeops_preproc_torch_overview #register_preproc("random_order", torchvision::transform_random_order, packages = "torchvision") -##' @name PipeOpPreprocTorchNormalize -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("normalize", torchvision::transform_normalize, packages = "torchvision") ##' @name PipeOpPreprocTorchHflip ##' @rdname mlr_pipeops_preproc_torch_overview #register_preproc("hflip", torchvision::transform_hflip, packages = "torchvision") @@ -96,9 +121,6 @@ table_preproc = function() { ##' @name PipeOpPreprocTorchRandomGrayscale ##' @rdname mlr_pipeops_preproc_torch_overview #register_preproc("random_grayscale", torchvision::transform_random_grayscale, packages = "torchvision") -##' @name PipeOpPreprocTorchAdjustHue -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("adjust_hue", torchvision::transform_adjust_hue, packages = "torchvision") ##' @name PipeOpPreprocTorchRandomAffine ##' @rdname mlr_pipeops_preproc_torch_overview #register_preproc("random_affine", torchvision::transform_random_affine, packages = "torchvision") @@ -120,24 +142,9 @@ table_preproc = function() { ##' @name PipeOpPreprocTorchRotate ##' @rdname mlr_pipeops_preproc_torch_overview #register_preproc("rotate", torchvision::transform_rotate, packages = "torchvision") -##' @name PipeOpPreprocTorchAdjustContrast -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("adjust_contrast", torchvision::transform_adjust_contrast, packages = "torchvision") -##' @name PipeOpPreprocTorchPad -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("pad", torchvision::transform_pad, packages = "torchvision") -##' @name PipeOpPreprocTorchAdjustSaturation -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("adjust_saturation", torchvision::transform_adjust_saturation, packages = "torchvision") ##' @name PipeOpPreprocTorchCenterCrop ##' @rdname mlr_pipeops_preproc_torch_overview #register_preproc("center_crop", torchvision::transform_center_crop, packages = "torchvision") ##' @name PipeOpPreprocTorchRandomChoice ##' @rdname mlr_pipeops_preproc_torch_overview #register_preproc("random_choice", torchvision::transform_random_choice, packages = "torchvision") -##' @name PipeOpPreprocTorchAffine -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("affine", torchvision::transform_affine, packages = "torchvision") -##' @name PipeOpPreprocTorchAdjustBrightness -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("adjust_brightness", torchvision::transform_adjust_brightness, packages = "torchvision") diff --git a/R/utils.R b/R/utils.R index ae9d22d3..8e496f0b 100644 --- a/R/utils.R +++ b/R/utils.R @@ -169,28 +169,33 @@ argument_matcher = function(args) { fn } -as_shape = function(shape) { - assert_integerish(shape) - if (!is.na(shape[1L])) { - shape = c(NA_integer_, shape) +#' Check Shape +#' +#' Checks whether an integer vector is a valid shape. +#' +#' @param shape (`integer()`)\cr +#' @param null_ok (`logical(1)`) +#' @param unknown_ok (`logical(1)`) +assert_shape = function(shape, null_ok = FALSE, unknown_ok = FALSE) { # nolint + if (is.null(shape) && null_ok) return(shape) + shape = assert_integerish(shape, min.len = 2L, all.missing = TRUE, coerce = TRUE) + + is_na = is.na(shape) + all_na = all(is_na) + + if (all_na && unknown_ok) { + return(shape) } - assert_integerish(shape[-1], any.missing = FALSE) - shape -} - -assert_shape = function(shape, null.ok = FALSE) { # nolint - if (is.null(shape) && null.ok) return(TRUE) - - assert_integerish(shape, min.len = 2L) - if (!(is.na(shape[[1L]]) || anyNA(shape[-1L]))) { + if (!is_na[[1L]] || anyNA(shape[-1L])) { stopf("Shape must have exactly one NA in the batch dimension.") } - TRUE + return(shape) } -assert_shapes = function(shapes, named = TRUE) { - assert_list(shapes, names = if (named) "unique", min.len = 1L) - walk(shapes, assert_shape) +assert_shapes = function(shapes, named = TRUE, unknown_ok = FALSE) { # nolint + # + assert_list(shapes, names = if (named && !identical(unique(names(shapes)), "...")) "unique", min.len = 1L) + map(shapes, assert_shape, unknown_ok = unknown_ok, null_ok = FALSE) } assert_lazy_tensor = function(x) { @@ -200,5 +205,3 @@ assert_lazy_tensor = function(x) { uniqueify = function(new, existing) { make.unique(c(existing, new), sep = "_")[length(existing) + seq_along(new)] } - - diff --git a/R/zzz.R b/R/zzz.R index 6d38751c..2fe92700 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -10,6 +10,7 @@ #' @import mlr3 #' @import vctrs #' @importFrom tools R_user_dir +#' @importFrom rlang !! #' #' @section Options: #' * `mlr3torch.cache`: @@ -28,11 +29,9 @@ mlr3torch_resamplings = new.env() mlr3torch_pipeop_tags = c("torch", "activation") mlr3torch_feature_types = c(img = "imageuri", lt = "lazy_tensor") -# metainf must be manually added in the register_mlr3pipelines function -# Because the value is substituted, we cannot pass it through this function -register_po = function(name, constructor) { +register_po = function(name, constructor, metainf = NULL) { if (name %in% names(mlr3torch_pipeops)) stopf("pipeop %s registered twice", name) - mlr3torch_pipeops[[name]] = list(constructor = constructor) + mlr3torch_pipeops[[name]] = list(constructor = constructor, metainf = substitute(metainf)) } register_resampling = function(name, constructor) { @@ -77,7 +76,6 @@ register_mlr3 = function() { mlr_reflections = utils::getFromNamespace("mlr_reflections", ns = "mlr3") # nolint iwalk(as.list(mlr3torch_feature_types), function(ft, nm) mlr_reflections$task_feature_types[[nm]] = ft) # nolint - mlr_reflections$torch = list( devices = c("auto", "cpu", "cuda", "mkldnn", "opengl", "opencl", "ideep", "hip", "fpga", "xla", "mps", "meta"), callback_stages = c( @@ -99,9 +97,10 @@ register_mlr3 = function() { register_mlr3pipelines = function() { mlr_pipeops = utils::getFromNamespace("mlr_pipeops", ns = "mlr3pipelines") iwalk(as.list(mlr3torch_pipeops), function(value, name) { - mlr_pipeops$add(name, value$constructor, value$metainf) + # metainf is quoted by pipelines + add = mlr_pipeops$add + eval(call("add", quote(name), quote(value$constructor), value$metainf)) }) - mlr_pipeops$metainf$torch_loss = list(loss = t_loss("cross_entropy")) mlr_reflections$pipeops$valid_tags = unique(c(mlr_reflections$pipeops$valid_tags, mlr3torch_pipeop_tags)) lapply(mlr3torch_pipeops, eval) } @@ -111,6 +110,18 @@ register_mlr3pipelines = function() { backports::import(pkgname) backports::import(pkgname, "R_user_dir", force = TRUE) + # Configure Logger: + lg = lgr::get_logger(pkgname) + assign("lg", lg, envir = parent.env(environment())) + f = function(event) { + event$msg = paste0("[mlr3torch] ", event$msg) + TRUE + } + lg$set_filters(list(f)) + if (Sys.getenv("IN_PKGDOWN") == "true") { + lg$set_threshold("warn") + } + register_namespace_callback(pkgname, "mlr3", register_mlr3) register_namespace_callback(pkgname, "mlr3pipelines", register_mlr3pipelines) @@ -133,9 +144,9 @@ register_mlr3pipelines = function() { suppressWarnings(fn(...)) }, .parent = getNamespace("mlr3misc"), fn) - unlockBinding("calculate_hash", parent.env(getNamespace("mlr3"))) - assign("calculate_hash", calculate_hash, envir = parent.env(getNamespace("mlr3"))) - lockBinding("calculate_hash", parent.env(getNamespace("mlr3"))) + unlockBinding("calculate_hash", parent.env(getNamespace("mlr3torch"))) + assign("calculate_hash", calculate_hash, envir = parent.env(getNamespace("mlr3torch"))) + lockBinding("calculate_hash", parent.env(getNamespace("mlr3torch"))) } } diff --git a/man/DataDescriptor.Rd b/man/DataDescriptor.Rd index 32f8bfe8..d1bdb893 100644 --- a/man/DataDescriptor.Rd +++ b/man/DataDescriptor.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/DataDescriptor.R +% Please edit documentation in R/lazy_tensor.R \name{DataDescriptor} \alias{DataDescriptor} \title{Data Descriptor} @@ -46,7 +46,7 @@ has no batch dimension.} Whether to clone the preprocessing graph.} \item{.info}{(any)\cr -Any additional meta-information. +Any additional meta-information (internal). This is used by \code{\link{PipeOpTaskPreprocTorch}} to communicate the 'would-be' predict shapes to ensure during the \verb{$train()} phase that \verb{$predict()} will be possible as well.} } diff --git a/man/assert_shape.Rd b/man/assert_shape.Rd new file mode 100644 index 00000000..f6707069 --- /dev/null +++ b/man/assert_shape.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{assert_shape} +\alias{assert_shape} +\title{Check Shape} +\usage{ +assert_shape(shape, null_ok = FALSE, unknown_ok = FALSE) +} +\arguments{ +\item{shape}{(\code{integer()})\cr} + +\item{null_ok}{(\code{logical(1)})} + +\item{unknown_ok}{(\code{logical(1)})} +} +\description{ +Checks whether an integer vector is a valid shape. +} diff --git a/man/lazy_tensor.Rd b/man/lazy_tensor.Rd index 209069fd..640aeef9 100644 --- a/man/lazy_tensor.Rd +++ b/man/lazy_tensor.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/lazy_tensor.R \name{lazy_tensor} \alias{lazy_tensor} -\title{Create a lazy tensor} +\title{Create a lazy tesornsor} \usage{ lazy_tensor(data_descriptor = NULL, ids = NULL) } diff --git a/man/materialize.Rd b/man/materialize.Rd index 08184574..604698b8 100644 --- a/man/materialize.Rd +++ b/man/materialize.Rd @@ -4,7 +4,15 @@ \alias{materialize} \title{Materialize Lazy Tensor Columns} \usage{ -materialize(x, device = "cpu", ...) +materialize(x, device = "cpu", rbind = FALSE, ...) +} +\arguments{ +\item{x}{(any)\cr +The object to materialize. +Either a \code{\link{lazy_tensor}} or a \code{list()} / \code{data.frame()} containing \code{\link{lazy_tensor}} columns.} + +\item{rbind}{(\code{logical(1)})\cr +Whether to rbind the lazy tensor columns (\code{TRUE}) or return them as a list of tensors (\code{FALSE}).} } \value{ (\code{\link[=torch_tensor]{torch_tensor()}} or \code{\link[=list]{list()}}) @@ -33,8 +41,10 @@ The hash key for b) is the hash of the indices dataset and preprocessing graph. } \examples{ lt1 = as_lazy_tensor(torch_randn(10, 3)) -materialize(lt1) +materialize(lt1, rbind = TRUE) +materialize(lt1, rbind = FALSE) lt2 = as_lazy_tensor(torch_randn(10, 4)) d = data.frame(lt1 = lt1, lt2 = lt2) -materialize(d) +materialize(d, rbind = TRUE) +materialize(d, rbind = FALSE) } diff --git a/man/materialize_internal.Rd b/man/materialize_internal.Rd index 1075c64e..261e2e76 100644 --- a/man/materialize_internal.Rd +++ b/man/materialize_internal.Rd @@ -8,7 +8,8 @@ materialize_internal( x, device = "cpu", cache = NULL, - set_keep_results = is.null(cache) + set_keep_results = is.null(cache), + rbind ) } \arguments{ @@ -28,11 +29,17 @@ this result is not part of the output of the \code{\link{Graph}}. Therefore we have to include this as part of the \code{keep_results} field of the \code{\link{Graph}}. When caching is done, this should be set to \code{FALSE} as otherwise data will be discarded that might be relevant for materializing other lazy tensor columns.} + +\item{rbind}{(\code{logical(1)})\cr +Whtether to rbind the resulting tensors (\code{TRUE}) or return them as a list of tensors (\code{FALSE}).} } \value{ \code{\link[=lazy_tensor]{lazy_tensor()}} } \description{ +Convert a \code{\link[=lazy_tensor]{lazy_tensor()}} to a \code{\link[=torch_tensor]{torch_tensor()}}. +} +\details{ Materializing a lazy tensor consists of: \enumerate{ \item Loading the data from the internal dataset of the \code{\link{DataDescriptor}}. @@ -40,7 +47,7 @@ Materializing a lazy tensor consists of: \item Returning the result of the \code{\link{PipeOp}} pointed to by the \code{\link{DataDescriptor}} (\code{.pointer}). } -With multiple \code{\link{lazy_tensor}} columns we can benefit from caching because: +When materializing multiple \code{\link{lazy_tensor}} columns, caching can be useful because: a) Output(s) from the dataset might be input to multiple graphs. b) Different lazy tensors might be outputs from the same graph. diff --git a/man/mlr_learners.alexnet.Rd b/man/mlr_learners.alexnet.Rd index 78ecd032..11fe5348 100644 --- a/man/mlr_learners.alexnet.Rd +++ b/man/mlr_learners.alexnet.Rd @@ -79,12 +79,12 @@ Other Learner: }} diff --git a/man/mlr_learners.mlp.Rd b/man/mlr_learners.mlp.Rd index d443563b..b0d79ac3 100644 --- a/man/mlr_learners.mlp.Rd +++ b/man/mlr_learners.mlp.Rd @@ -107,12 +107,12 @@ Other Learner: }} diff --git a/man/mlr_learners.torch_featureless.Rd b/man/mlr_learners.torch_featureless.Rd index 0db8e2d9..f112208f 100644 --- a/man/mlr_learners.torch_featureless.Rd +++ b/man/mlr_learners.torch_featureless.Rd @@ -96,12 +96,12 @@ Other Learner: }} diff --git a/man/mlr_learners_torch.Rd b/man/mlr_learners_torch.Rd index 55d72e08..0501f416 100644 --- a/man/mlr_learners_torch.Rd +++ b/man/mlr_learners_torch.Rd @@ -124,18 +124,18 @@ Shortcut for \code{learner$model$callbacks$history}.} \item \href{#method-LearnerTorch-new}{\code{LearnerTorch$new()}} \item \href{#method-LearnerTorch-format}{\code{LearnerTorch$format()}} \item \href{#method-LearnerTorch-print}{\code{LearnerTorch$print()}} +\item \href{#method-LearnerTorch-train}{\code{LearnerTorch$train()}} +\item \href{#method-LearnerTorch-predict}{\code{LearnerTorch$predict()}} \item \href{#method-LearnerTorch-clone}{\code{LearnerTorch$clone()}} } } \if{html}{\out{ -
Inherited methods +
Inherited methods
}} @@ -250,6 +250,51 @@ Currently unused.} } } \if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-LearnerTorch-train}{}}} +\subsection{Method \code{train()}}{ +Train the learner. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{LearnerTorch$train(task, row_ids = NULL)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{task}}{(\code{\link{Task}})\cr +The task.} + +\item{\code{row_ids}}{(\code{integer()})\cr +Which rows to use for trainin.g} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-LearnerTorch-predict}{}}} +\subsection{Method \code{predict()}}{ +Predict on a task. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{LearnerTorch$predict(task, row_ids = NULL)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{task}}{(\code{\link{Task}})\cr +The task.} + +\item{\code{row_ids}}{(\code{integer()})\cr +For which rows to predict.} +} +\if{html}{\out{
}} +} +\subsection{Returns}{ +(\code{\link{Prediction}}) +} +} +\if{html}{\out{
}} \if{html}{\out{}} \if{latex}{\out{\hypertarget{method-LearnerTorch-clone}{}}} \subsection{Method \code{clone()}}{ diff --git a/man/mlr_learners_torch_image.Rd b/man/mlr_learners_torch_image.Rd index 033e94a5..a9a9ad17 100644 --- a/man/mlr_learners_torch_image.Rd +++ b/man/mlr_learners_torch_image.Rd @@ -56,12 +56,12 @@ Other Learner:
}} diff --git a/man/mlr_learners_torch_model.Rd b/man/mlr_learners_torch_model.Rd index ce94fb8c..6e04627d 100644 --- a/man/mlr_learners_torch_model.Rd +++ b/man/mlr_learners_torch_model.Rd @@ -79,12 +79,12 @@ Other Graph Network: }} diff --git a/man/mlr_pipeops_preproc_torch.Rd b/man/mlr_pipeops_preproc_torch.Rd index beae7519..51ffed46 100644 --- a/man/mlr_pipeops_preproc_torch.Rd +++ b/man/mlr_pipeops_preproc_torch.Rd @@ -6,37 +6,46 @@ \title{Base Class for Torch Preprocessing} \description{ This \code{PipeOp} can be used to preprocess (one or more) \code{\link{lazy_tensor}} columns contained in an \code{\link[mlr3:Task]{mlr3::Task}}. -The function that is applied is specified as construction argument \code{fn} and additional arguments to this +The preprocessing function is specified as construction argument \code{fn} and additional arguments to this function can be defined through the \code{PipeOp}'s parameter set. -The preprocessing is either done per-column in which case the number lazy tensor output columns is equivalent +The preprocessing is usually done per-column in which case the number lazy tensor output columns is equivalent to the number of lazy tensor input columns. It is also possible to implement preprocessing that is applied to all lazy tensor columns at once and returns -one or more (not necessarily the same number) of lazy tensor columns. +one or more (not necessarily the same number of) lazy tensor columns. +The preprocessing that is applied during \verb{$predict()} uses the parameters that were set during \verb{$train()} +and not those that are set when performing the prediction. } \section{Inheriting}{ -In addition to specifying the parameters \code{fn}, \code{packages} and \code{param_set} during construction you can also overwrite -the private \code{.shapes_out()} or \code{.tranform()} methods: +In addition to specifying the construction arguments, you can overwrite the private \code{.shapes_out()} or +\code{.tranform()} methods: \itemize{ \item \code{.shapes_out(shapes_in, param_vals, task)}\cr (\code{list()}, \verb{list(), }Task\code{or}NULL\verb{) -> }list()`\cr This private method calculates the output shapes of the lazy tensor columns that are created from applying the preprocessing. - -Also see the documentation of \code{\link{PipeOpTorch}} how to implement this method. +Note that the input shapes can be only contain NAs (e.g. (NA, NA, NA)), indicating that only the number of input +dimensions is known, but not the exact shape. +In this case the output shape should also only contain NAs. In case the construction argument \code{per_column} is \code{TRUE}, this private method only has the responsibility -to caclculate the output shapes for one input column, i.e. the input \code{shapes_in} can be assumed to have -exactly one shape vector for which it must calculate the output shapes. +to calculate the output shapes for one input column, i.e. the input \code{shapes_in} can be assumed to have +exactly one shape vector for which it must calculate the output shapes and return it as a \code{list()} of length 1. + +Also see the documentation of \code{\link{PipeOpTorch}} how to implement this method. \item \code{.transform(dt, task, param_vals, stage)}\cr (\code{data.table()}, \code{Task}, \code{list()}, \code{character(1)}) -> \code{data.table()}\cr This method must only be overwritten when the the \code{per_column} construction argument is \code{FALSE}. It receives as inputs all selected lazy tensor columns, the input \code{Task} (already cloned), the paramer values, and whether the preprocessing is applied during training (stage is \code{"train"}) -or prediction (stage is \code{"predict"}). It needs to return a \code{data.table} with lazy tensor columns. -Note that the lazy tensor inputs should not be modified in-place. -Note that overwriting this method (currently) requires a solid understanding of the \code{\link{lazy_tensor}} internals. This might be made easier in the future. -Note also that you need to pay attention to avoid name conflicts with existing columns in the task. +or prediction (stage is \code{"predict"}). One should not work with the parameters currently set in the paramet set, +only use those passed as argument \code{param_vals}. These are the parameters that were specified during the \verb{$train()} +call of the \code{\link{PipeOp}} (otherwise it cannot be ensured that the shapes encountered during \verb{$predict()} can actually +be processed by the neural network). +The method must return a \code{data.table} with lazy tensor columns. +The lazy tensor input columns should \strong{not} be modified in-place. +Overwriting this method (currently) requires a solid understanding of the \code{\link{lazy_tensor}} internals. +You also need to pay attention to avoid name conflicts with existing columns in the task. } } @@ -102,10 +111,10 @@ po_simple$param_set$set_values( ) taskout_train = po_simple$train(list(taskin))[[1L]] -materialize(taskout_train$data(cols = c("x1", "x2"))) +materialize(taskout_train$data(cols = c("x1", "x2")), rbind = TRUE) taskout_predict_noaug = po_simple$predict(list(taskin))[[1L]] -materialize(taskout_predict_noaug$data(cols = c("x1", "x2"))) +materialize(taskout_predict_noaug$data(cols = c("x1", "x2")), rbind = TRUE) po_simple$param_set$set_values( augment = TRUE @@ -113,7 +122,7 @@ po_simple$param_set$set_values( # transformation is not applied taskout_predict_aug = po_simple$predict(list(taskin))[[1L]] -materialize(taskout_predict_aug$data(cols = c("x1", "x2"))) +materialize(taskout_predict_aug$data(cols = c("x1", "x2")), rbind = TRUE) # Creating a more complex preprocessing PipeOp @@ -122,7 +131,7 @@ PipeOpPreprocTorchPoly = R6::R6Class("PipeOpPreprocTorchPoly", public = list( initialize = function(id = "preproc_poly", param_vals = list()) { param_set = paradox::ps( - n_degree = paradox::p_int(lower = 1L, tags = c("train", "predict", "required")) + n_degree = paradox::p_int(lower = 1L, tags = c("train", "required")) ) param_set$set_values( n_degree = 1L @@ -159,14 +168,10 @@ po_poly = PipeOpPreprocTorchPoly$new( param_vals = list(n_degree = 3L, affect_columns = selector_name("x3")) ) -# Note that the 'augment' parameter is not present as the PipeOp -# modifies the input shape and must hence be applied during training **and** prediction -po_poly$param_set - po_poly$shapes_out(list(c(NA, 1L))) taskout = po_poly$train(list(taskin))[[1L]] -materialize(taskout$data(cols = "x3")) +materialize(taskout$data(cols = "x3"), rbind = TRUE) } \section{Super classes}{ \code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3pipelines:PipeOpTaskPreproc]{mlr3pipelines::PipeOpTaskPreproc}} -> \code{PipeOpTaskPreprocTorch} @@ -220,7 +225,8 @@ Parameter values to be set after construction.} \item{\code{param_set}}{(\code{\link{ParamSet}})\cr In case the function \code{fn} takes additional parameter besides a \code{\link[=torch_tensor]{torch_tensor()}} they can be -specfied as parameters. Pay attention to set the correct \code{tags} for the parameters: if tag \code{"train"} is present, +specfied as parameters. None of the parameters can have the \code{\link{"predict"}} tag. +Pay attention to set the correct \code{tags} for the parameters: if tag \code{"train"} is present, the preprocessing is applied during training and if tag \code{"predict"} is present, the preprocessing is applied during prediction (if \code{augment} is set to \code{FALSE}).} diff --git a/man/mlr_pipeops_preproc_torch_overview.Rd b/man/mlr_pipeops_preproc_torch_overview.Rd index e88ee649..b4d5d951 100644 --- a/man/mlr_pipeops_preproc_torch_overview.Rd +++ b/man/mlr_pipeops_preproc_torch_overview.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch_overview} \alias{mlr_pipeops_preproc_torch_overview} +\alias{PipeOpPreprocTorchTrafoResize} \title{Lazy Preprocessing and Transformations} \description{ Overview over all implemented preprocessing methods. diff --git a/man/mlr_pipeops_torch.Rd b/man/mlr_pipeops_torch.Rd index fad5ab9a..5430d3c5 100644 --- a/man/mlr_pipeops_torch.Rd +++ b/man/mlr_pipeops_torch.Rd @@ -343,7 +343,7 @@ The tags of the \code{\link{PipeOp}}. The tags \code{"torch"} is always added.} \subsection{Method \code{shapes_out()}}{ Calculates the output shapes for the given input shapes, parameters and task. \subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorch$shapes_out(shapes_in, task = NULL, stage)}\if{html}{\out{
}} +\if{html}{\out{
}}\preformatted{PipeOpTorch$shapes_out(shapes_in, task = NULL)}\if{html}{\out{
}} } \subsection{Arguments}{ diff --git a/man/pipeop_preproc_torch.Rd b/man/pipeop_preproc_torch.Rd index 2556d0b1..d9a2259e 100644 --- a/man/pipeop_preproc_torch.Rd +++ b/man/pipeop_preproc_torch.Rd @@ -5,17 +5,19 @@ \title{Create Torch Preprocessing PipeOps} \usage{ pipeop_preproc_torch( - name, + id, fn, shapes_out = NULL, param_set = NULL, param_vals = list(), packages = character(0), - per_column = TRUE, - prefix = "trafo" + per_column = TRUE ) } \arguments{ +\item{id}{(\code{character(1)})\cr +The id for of the new object.} + \item{fn}{(\code{function})\cr The preprocessing function.} @@ -23,13 +25,17 @@ The preprocessing function.} The private \code{.shapes_out(shapes_in, param_vals, task)} method of \code{\link{PipeOpTaskPreprocTorch}}. If \code{NULL}, the pipeop does not change the output shapes. If \code{TRUE}, the output shape function is inferred and calculates the output shapes as follows: +a) The input shapes are known: For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is -applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned.} +applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. +b) The input shapes are unknown (all NA): +The dimension is returned as is.} \item{param_set}{(\code{\link{ParamSet}} or \code{NULL})\cr The parameter set. If this is left as \code{NULL} (default) the parameter set is inferred in the following way: -All arguments but the first and \code{...} of \code{fn} are set as untyped parameters with tags 'train' and 'predict'. +All parameters but the first and \code{...} of \code{fn} are set as untyped parameters with tags 'train' and those that +have nod default value are tagged as 'required' as well. Default values are not annotated.} \item{param_vals}{(\code{list()})\cr diff --git a/man/pipeop_preproc_torch_class.Rd b/man/pipeop_preproc_torch_class.Rd index 4c40017f..d9986e19 100644 --- a/man/pipeop_preproc_torch_class.Rd +++ b/man/pipeop_preproc_torch_class.Rd @@ -5,16 +5,18 @@ \title{Create Torch Preprocessing PipeOps} \usage{ pipeop_preproc_torch_class( - name, + id, fn, shapes_out = NULL, param_set = NULL, packages = character(0), - per_column = TRUE, - prefix = "trafo" + per_column = TRUE ) } \arguments{ +\item{id}{(\code{character(1)})\cr +The id for of the new object.} + \item{fn}{(\code{function})\cr The preprocessing function.} @@ -22,13 +24,17 @@ The preprocessing function.} The private \code{.shapes_out(shapes_in, param_vals, task)} method of \code{\link{PipeOpTaskPreprocTorch}}. If \code{NULL}, the pipeop does not change the output shapes. If \code{TRUE}, the output shape function is inferred and calculates the output shapes as follows: +a) The input shapes are known: For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is -applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned.} +applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. +b) The input shapes are unknown (all NA): +The dimension is returned as is.} \item{param_set}{(\code{\link{ParamSet}} or \code{NULL})\cr The parameter set. If this is left as \code{NULL} (default) the parameter set is inferred in the following way: -All arguments but the first and \code{...} of \code{fn} are set as untyped parameters with tags 'train' and 'predict'. +All parameters but the first and \code{...} of \code{fn} are set as untyped parameters with tags 'train' and those that +have nod default value are tagged as 'required' as well. Default values are not annotated.} \item{packages}{(\code{character()})\cr @@ -37,9 +43,6 @@ The R packages this object depends on.} \item{per_column}{(\code{logical(1)})\cr Whether the preprocessing is applied per-column.} -\item{id}{(\code{character(1)})\cr -The id for of the new object.} - \item{param_vals}{(named \code{list()})\cr Parameter values to be set after construction.} } diff --git a/man/transform_lazy_tensor.Rd b/man/transform_lazy_tensor.Rd deleted file mode 100644 index 5e6567fe..00000000 --- a/man/transform_lazy_tensor.Rd +++ /dev/null @@ -1,50 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/lazy_tensor.R -\name{transform_lazy_tensor} -\alias{transform_lazy_tensor} -\title{Transform Lazy Tensor} -\usage{ -transform_lazy_tensor(lt, pipeop, shape) -} -\arguments{ -\item{lt}{(\code{\link{lazy_tensor}})\cr -A lazy tensor vector.} - -\item{pipeop}{(\code{\link{PipeOpModule}})\cr -The pipeop to be added to the preprocessing graph(s) of the lazy tensor. -Must have one input and one output.} - -\item{shape}{(\code{integer()})\cr -The shape of the lazy tensor (without the batch dimension).} -} -\value{ -\code{\link{lazy_tensor}} -} -\description{ -transform a \code{\link{lazy_tensor}} vector by appending a preprocessing step. -} -\details{ -The following is done: -\enumerate{ -\item A shallow copy of the \code{\link{lazy_tensor}}'s preprocessing \code{graph} is created. -\item The provided \code{pipeop} is added to the (shallowly cloned) \code{graph} and connected to the current \code{.pointer} of the -\code{\link{DataDescriptor}}. -\item The \code{.pointer} of the \code{\link{DataDescriptor}} is updated to point to the new output channel of the \code{pipeop}. -\item The \code{.pointer_shape} of the \code{\link{DataDescriptor}} set to the provided \code{shape}. -\item The \code{.hash} of the \code{\link{DataDescriptor}} is updated. -Input must be PipeOpModule with exactly one input and one output -shape must be shape with NA in first dimension -} -} -\examples{ -lt = as_lazy_tensor(1:10) -add_five = po("module", module = function(x) x + 5) -lt_plus_five = transform_lazy_tensor(lt, add_five, c(NA, 1)) -torch_cat(list(materialize(lt), materialize(lt_plus_five)), dim = 2) -# graph is cloned -identical(lt$graph, lt_plus_five$graph) -lt$graph$edges -lt_plus_five$graph_edges -# pipeops are not cloned -identical(lt$graph$pipeops[[1]], lt_plus_five$graph[[1]]) -} diff --git a/tests/testthat/helper_autotest.R b/tests/testthat/helper_autotest.R index 7f37f06f..a4e981e9 100644 --- a/tests/testthat/helper_autotest.R +++ b/tests/testthat/helper_autotest.R @@ -321,7 +321,5 @@ autotest_trafo = function(obj) { autotest_preproc = function(obj) { expect_class(obj, "PipeOpTaskPreprocTorch") - # TODO: Unless the test is disabled, check that all parameters have train and predict tag - - + # TODO: Unless the test is disabled, check that all parameters have train tag } diff --git a/tests/testthat/helper_functions.R b/tests/testthat/helper_functions.R index e78ff384..21bad342 100644 --- a/tests/testthat/helper_functions.R +++ b/tests/testthat/helper_functions.R @@ -247,8 +247,8 @@ random_dataset = dataset("random_dataset", initialize = function(..., n = 10) { self$x = torch_randn(n, ...) }, - .getitem = function(i) { - list(x = self$x[i, ..]) + .getbatch = function(i) { + list(x = self$x[i, .., drop = FALSE]) }, .length = function() { nrow(self$x) diff --git a/tests/testthat/setup.R b/tests/testthat/setup.R index f7b096de..9fde85e8 100644 --- a/tests/testthat/setup.R +++ b/tests/testthat/setup.R @@ -7,6 +7,10 @@ old_opts = options( # https://github.com/HenrikBengtsson/Wishlist-for-R/issues/88 old_opts = lapply(old_opts, function(x) if (is.null(x)) FALSE else x) +lg_mlr3 = lgr::get_logger("mlr3") +old_threshold_mlr3 = lg_mlr3$threshold +lg_mlr3$set_threshold("warn") + old_threshold = lg$threshold old_plan = future::plan() lg$set_threshold("warn") diff --git a/tests/testthat/teardown.R b/tests/testthat/teardown.R index f9d46e3b..69101ac9 100644 --- a/tests/testthat/teardown.R +++ b/tests/testthat/teardown.R @@ -1,2 +1,3 @@ lg$set_threshold(old_threshold) future::plan(old_plan) +lg_mlr3$set_threshold(old_threshold_mlr3) diff --git a/tests/testthat/test_DataDescriptor.R b/tests/testthat/test_DataDescriptor.R deleted file mode 100644 index a1757e80..00000000 --- a/tests/testthat/test_DataDescriptor.R +++ /dev/null @@ -1,32 +0,0 @@ -test_that("DataDescriptor works", { - ds = dataset( - initialize = function() { - self$x = torch_randn(10, 5, 3) - }, - .getitem = function(i) { - list(x = self$x[i, ..]) - }, - .length = function() { - nrow(self$x) - } - )() - - dd = DataDescriptor(ds, dataset_shapes = list(x = c(NA, 5, 3))) - expect_class(dd, "DataDescriptor") - expect_equal(dd$.pointer_shape, c(NA, 5, 3)) - expect_class(dd$graph$pipeops[[1L]], "PipeOpNOP") - expect_true(length(dd$graph$pipeops) == 1L) - expect_equal(dd$.pointer, c(dd$graph$output$op.id, dd$graph$output$channel.name)) - expect_string(dd$.dataset_hash) - expect_string(dd$.hash) - expect_false(dd$.dataset_hash == dd$.hash) - - dd1 = DataDescriptor(ds, dataset_shapes = list(x = c(NA, 5, 3))) - expect_equal(dd$dataset_shapes, dd1$dataset_shapes) - - expect_error(DataDescriptor(ds), "missing") - - graph = as_graph(po("nop", id = "nop")) - - expect_error(DataDescriptor(ds, dataset_shapes = list(x = c(5, 4)), "When passing a graph")) -}) diff --git a/tests/testthat/test_LearnerTorch.R b/tests/testthat/test_LearnerTorch.R index c594370d..99edf5f3 100644 --- a/tests/testthat/test_LearnerTorch.R +++ b/tests/testthat/test_LearnerTorch.R @@ -379,3 +379,8 @@ test_that("resample() works", { rr = resample(task, learner, resampling) expect_r6(rr, "ResampleResult") }) + +test_that("Shapes are checked correctly during `$train()`", { + # FIXME: For this the taskpreproc should work first + +}) diff --git a/tests/testthat/test_PipeOpTaskPreprocTorch.R b/tests/testthat/test_PipeOpTaskPreprocTorch.R index 7949f0f6..cb8c7547 100644 --- a/tests/testthat/test_PipeOpTaskPreprocTorch.R +++ b/tests/testthat/test_PipeOpTaskPreprocTorch.R @@ -48,8 +48,8 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { taskout1 = po_test1$train(list(task))[[1L]] expect_torch_equal( - -materialize(taskout1$data(cols = "x1")[[1L]]), - materialize(taskout1$data(cols = "x2")[[1L]]) + -materialize(taskout1$data(cols = "x1")[[1L]], rbind = TRUE), + materialize(taskout1$data(cols = "x2")[[1L]], rbind = TRUE) ) # "train" and "predict" tags are respected @@ -74,11 +74,11 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { po_test2 = PipeOpTaskPreprocTorchTest2$new(param_vals = list(affect_columns = selector_name("x1"), a = 0)) expect_true( - torch_sum(materialize(po_test2$train(list(task))[[1L]]$data(cols = "x1")[[1L]]))$item() == 0 + torch_sum(materialize(po_test2$train(list(task))[[1L]]$data(cols = "x1")[[1L]], rbind = TRUE))$item() == 0 ) expect_true( - torch_sum(materialize(po_test2$predict(list(task))[[1L]]$data(cols = "x1")[[1L]]))$item() == 2 * sum(1:10) + torch_sum(materialize(po_test2$predict(list(task))[[1L]]$data(cols = "x1")[[1L]], rbind = TRUE))$item() == 0 ) # augment parameter works as intended (above augment was FALSE) @@ -86,8 +86,14 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { po_test2$param_set$set_values( augment = TRUE ) + # augment is TRUE, but a is tagged "train" --> does not change the results expect_true( - torch_sum(materialize(po_test2$predict(list(task))[[1L]]$data(cols = "x1")[[1L]]))$item() == sum(1:10) + torch_sum(materialize(po_test2$predict(list(task))[[1L]]$data(cols = "x1")[[1L]], rbind = TRUE))$item() == 0 + ) + # only if we re-train the augmentation is applied + po_test2$train(list(task)) + expect_true( + torch_sum(materialize(po_test2$predict(list(task))[[1L]]$data(cols = "x1")[[1L]], rbind = TRUE))$item() == sum(1:10) ) }) @@ -105,6 +111,7 @@ test_that("PipeOpTaskPreprocTorch modifies the underlying lazy tensor columns co taskout_pred = po_test$predict(list(taskin))[[1L]] po_test$param_set$set_values(augment = TRUE) + po_test$train(list(taskin))[[1L]] taskout_pred_aug = po_test$predict(list(taskin))[[1L]] expect_true(length(taskin$data(cols = "x")[[1]]$graph$pipeops) == 1L) @@ -118,19 +125,19 @@ test_that("PipeOpTaskPreprocTorch modifies the underlying lazy tensor columns co taskout_pred$data(cols = "x")[[1]]$graph expect_equal( - as_array(materialize(taskin$data(cols = "x")[[1L]])), - as_array(materialize(taskout_train$data(cols = "x")[[1L]]) + 10), + as_array(materialize(taskin$data(cols = "x")[[1L]], rbind = TRUE)), + as_array(materialize(taskout_train$data(cols = "x")[[1L]], rbind = TRUE) + 10), tolerance = 1e-5 ) }) test_that("pipeop_preproc_torch works", { expect_error( - pipeop_preproc_torch("abc", function(x) NULL, shapes_out = function(shapes) NULL), - "Must have formal" + pipeop_preproc_torch("trafo_abc", function(x) NULL, shapes_out = function(shapes) NULL), + "Must have formal arguments" ) - po_test = pipeop_preproc_torch("abc", function(x, a) torch_cat(list(x, torch_pow(x, a)), dim = 2), + po_test = pipeop_preproc_torch("trafo_abc", function(x, a) torch_cat(list(x, torch_pow(x, a)), dim = 2), shapes_out = function(shapes_in, param_vals, task) { s = shapes_in[[1L]] s[2] = 2L @@ -139,7 +146,8 @@ test_that("pipeop_preproc_torch works", { } ) - expect_class(po_test, "PipeOpPreprocTorchAbc") + expect_true("required" %in% po_test$param_set$tags$a) + expect_class(po_test, "PipeOpPreprocTorchTrafoAbc") # parameter a was added expect_set_equal(c("a", "affect_columns", "augment"), po_test$param_set$ids()) @@ -154,7 +162,7 @@ test_that("pipeop_preproc_torch works", { taskout = po_test$train(list(task))[[1L]] - x = materialize(taskout$data(cols = "x")[[1L]]) + x = materialize(taskout$data(cols = "x")[[1L]], rbind = TRUE) expect_torch_equal(x[1, 1]$item(), 3) expect_torch_equal(x[1, 2]$item(), 1) @@ -162,7 +170,8 @@ test_that("pipeop_preproc_torch works", { param_vals = list(size = c(10, 10)) ) - po_test$shapes_out(list(c(NA, 20, 20)), "train") + size = po_test1$shapes_out(list(c(NA, 20, 20)), "train") + expect_equal(size, list(c(NA, 10, 10))) }) test_that("predict shapes are added during training", { @@ -174,4 +183,6 @@ test_that("predict shapes are added during training", { taskout = po_test$train(list(task))[[1L]] + # TODO: + }) diff --git a/tests/testthat/test_PipeOpTorch.R b/tests/testthat/test_PipeOpTorch.R index abab20e5..4144e9a2 100644 --- a/tests/testthat/test_PipeOpTorch.R +++ b/tests/testthat/test_PipeOpTorch.R @@ -134,9 +134,9 @@ test_that("PipeOpTorch errs when there are unexpected NAs in the shape", { md = graph$train(task)[[1L]] md$.pointer_shape = c(4, NA) - expect_error(po("nn_relu")$train(list(md)), regexp = "but must have exactly one NA") + expect_error(po("nn_relu")$train(list(md)), regexp = "must have exactly one NA") md$.pointer_shape = c(NA, NA, 4) - expect_error(po("nn_relu")$train(list(md)), regexp = "but must have exactly one NA") + expect_error(po("nn_relu")$train(list(md)), regexp = "must have exactly one NA") }) diff --git a/tests/testthat/test_PipeOpTorchLazyTransform.R b/tests/testthat/test_PipeOpTorchLazyTransform.R deleted file mode 100644 index 5f4e3cc5..00000000 --- a/tests/testthat/test_PipeOpTorchLazyTransform.R +++ /dev/null @@ -1,40 +0,0 @@ -test_that("PipeOpTorchLazyTransform basic checks", { - trafo = function(x) torchvision::transform_resize(x, c(10, 10)) - po_lt = po("trafo_lazy", trafo, packages = "R6") - expect_pipeop(po_lt) - expect_true("R6" %in% po_lt$packages) - - expect_error( - po("trafo_lazy", function(x) torchvision::transform_resize(x, c(10, 10)), param_set = ps(augment = p_lgl())) - ) - - taskin = nano_mnist() - - taskout = po_lt$train(list(taskin))[[1L]] - - expect_permutation(taskin$feature_names, taskout$feature_names) - - # transformation is applied as we expect it - expect_true(torch_equal( - trafo(materialize(taskin$data(cols = "image")[[1L]])), - materialize(taskout$data(cols = "image")[[1L]]) - )) - -}) - -test_that("PipeOpTorchLazyTransform works in Graph", { - task = nano_mnist() - - graph = po("torch_ingress_ltnsr") %>>% - po("transform_resize", size = c(10, 10)) %>>% - po("nn_flatten") %>>% - po("nn_head") %>>% - po("torch_optimizer") %>>% - po("torch_loss", "cross_entropy") %>>% - po("torch_model_classif", epochs = 1L, device = "cpu", batch_size = 16) - - graph$train(task)[[1L]] - -}) - -test_that("PipeOpTorchLazyTransform works with") diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index f29fe569..6369a3f8 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -1,3 +1,65 @@ +test_that("DataDescriptor works", { + ds = dataset( + initialize = function() { + self$x = torch_randn(10, 5, 3) + }, + .getitem = function(i) { + list(x = self$x[i, ..]) + }, + .length = function() { + nrow(self$x) + } + )() + + dd = DataDescriptor(ds, dataset_shapes = list(x = c(NA, 5, 3))) + expect_class(dd, "DataDescriptor") + expect_equal(dd$.pointer_shape, c(NA, 5, 3)) + expect_class(dd$graph$pipeops[[1L]], "PipeOpNOP") + expect_true(length(dd$graph$pipeops) == 1L) + expect_equal(dd$.pointer, c(dd$graph$output$op.id, dd$graph$output$channel.name)) + expect_string(dd$.dataset_hash) + expect_string(dd$.hash) + expect_false(dd$.dataset_hash == dd$.hash) + + dd1 = DataDescriptor(ds, dataset_shapes = list(x = c(NA, 5, 3))) + expect_equal(dd$dataset_shapes, dd1$dataset_shapes) + + expect_error(DataDescriptor(ds), "missing") + + graph = as_graph(po("nop", id = "nop")) + + expect_error(DataDescriptor(ds, dataset_shapes = list(x = c(5, 4)), "When passing a graph")) +}) + +test_that("Unknown shapes work", { + ds = dataset( + initialize = function() { + self$x = list( + torch_randn(2, 2), + torch_randn(3, 3) + ) + }, + .getitem = function(i) { + list(x = self$x[[i]]) + }, + .length = function() { + length(self$x) + } + )() + + dd = DataDescriptor(ds, dataset_shapes = list(x = c(NA, NA, NA))) + expect_class(dd, "DataDescriptor") + expect_equal(dd$.pointer_shape, c(NA, NA, NA)) + expect_equal(dd$dataset_shapes, list(x = c(NA, NA, NA))) + + lt = as_lazy_tensor(dd) + expect_class(lt, "lazy_tensor") + materialize(lt) + + ds = random_dataset(10, 3) + expect_error(DataDescriptor(ds, list(x = c(NA, NA, NA)))) +}) + test_that("lazy_tensor works", { dd1 = DataDescriptor(random_dataset(5, 4), list(x = c(NA, 5, 4))) dd2 = DataDescriptor(random_dataset(5, 4), list(x = c(NA, 5, 4))) @@ -16,14 +78,12 @@ test_that("lazy_tensor works", { expect_true(is.null(attr(lt1_empty, "data_descriptor"))) expect_class(lt1_empty, "lazy_tensor") - lt1_empty[1] = lt1[1] - - expect_class(materialize(lazy_tensor()), "torch_tensor") + expect_error(materialize(lazy_tensor()), "Cannot materialize") }) test_that("transform_lazy_tensor works", { lt = as_lazy_tensor(torch_randn(16, 2, 5)) - lt_mat = materialize(lt) + lt_mat = materialize(lt, rbind = TRUE) expect_equal(lt_mat$shape, c(16, 2, 5)) @@ -39,7 +99,8 @@ test_that("transform_lazy_tensor works", { lt1 = transform_lazy_tensor(lt, po_module, new_shape) dd1 = attr(lt1, "data_descriptor") - expect_equal(dd$graph$edges, + + expect_equal(dd1$graph$edges, data.table(src_id = "dataset_x", src_channel = "output", dst_id = "mod", dst_channel = "input") ) @@ -47,8 +108,8 @@ test_that("transform_lazy_tensor works", { # graph was cloned expect_true(!identical(dd1$graph, dd$graph)) - # pipeop was cloned - expect_true(!identical(dd1$graph$pipeops$dataset_x, dd$graph$pipeops$dataset_x)) + # pipeop was not cloned + expect_true(identical(dd1$graph$pipeops$dataset_x, dd$graph$pipeops$dataset_x)) # .pointer was set expect_equal(dd1$.pointer, c("mod", "output")) @@ -61,7 +122,7 @@ test_that("transform_lazy_tensor works", { expect_true(dd$.dataset_hash == dd1$.dataset_hash) # materialization gives correct result - lt1_mat = materialize(lt1) + lt1_mat = materialize(lt1, rbind = TRUE) expect_equal(lt1_mat$shape, c(16, 10)) lt1_mat = torch_reshape(lt1_mat, c(-1, 2, 5)) diff --git a/tests/testthat/test_materialize.R b/tests/testthat/test_materialize.R index a5a8a656..db6aa57a 100644 --- a/tests/testthat/test_materialize.R +++ b/tests/testthat/test_materialize.R @@ -2,26 +2,59 @@ test_that("materialize works on lazy_tensor", { ds = random_dataset(5, 4, n = 10) lt = as_lazy_tensor(ds, list(x = c(NA, 5, 4))) - output = materialize(lt, device = "cpu") + output = materialize(lt, device = "cpu", rbind = TRUE) expect_class(output, "torch_tensor") expect_equal(output$shape, c(10, 5, 4)) expect_true(output$device == torch_device("cpu")) expect_true(torch_equal(output, ds$x)) - output_meta = materialize(lt, device = "meta") - expect_true(output_meta$device == torch_device("meta")) + output_meta_list = materialize(lt, device = "meta", rbind = FALSE) + output_meta_tnsr = materialize(lt, device = "meta", rbind = TRUE) + + expect_equal(torch_cat(output_meta_list, dim = 1L)$shape, output_meta_tnsr$shape) + expect_true(output_meta_tnsr$device == torch_device("meta")) +}) + +test_that("materialize works in all 4 cases", { + # .g }) test_that("materialize works for data.frame", { df = nano_mnist()$data(1:10, cols = "image") - out = materialize(df) + out = materialize(df, rbind = TRUE) expect_list(out) expect_equal(names(out), "image") expect_class(out$image, "torch_tensor") expect_equal(out$image$shape, c(10, 1, 28, 28)) }) +test_that("materialize works with differing shapes", { + ds = dataset( + initialize = function() { + self$x = list( + torch_randn(2, 2), + torch_randn(3, 3) + ) + }, + .getitem = function(i) { + list(x = self$x[[i]]) + }, + .length = function() { + length(self$x) + } + )() + + dd = DataDescriptor(ds, dataset_shapes = list(x = c(NA, NA, NA))) + + lt = as_lazy_tensor(dd) + + expect_class(materialize(lt[1], rbind = TRUE), "torch_tensor") + l = materialize(lt, rbind = FALSE) + expect_class(l, "list") + expect_class(l[[1L]], "torch_tensor") +}) + test_that("caching of datasets works", { # TODO }) diff --git a/tests/testthat/test_preproc_and_trafo.R b/tests/testthat/test_preproc_and_trafo.R deleted file mode 100644 index 300d797e..00000000 --- a/tests/testthat/test_preproc_and_trafo.R +++ /dev/null @@ -1 +0,0 @@ -test_that("resize works") diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index 5be4b5a9..f288bcf7 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -293,18 +293,3 @@ test_that("dataset_img works", { expect_true(batch_meta$x$image$device$type == "meta") }) -test_that("task_dataset works with multiple lazy_tensor columns", { - task = nano_mnist() - graph = po("torch_ingress_ltnsr") %>>% - po("trafo_resize", size = c(40, 40)) %>>% - list( - po("trafo_resize_1", size = c(30, 30)), - po("trafo_resize_2", size = c(15, 15)) - ) - - - # What to do next: - # Test that PipeOpTorchLazyTensor works as we want, i.e. all the 8 cases (train-predict, preproc-graph, augment) - - graph$train(task) -}) diff --git a/tests/testthat/test_utils.R b/tests/testthat/test_utils.R index eb0a4d7f..a23a1d89 100644 --- a/tests/testthat/test_utils.R +++ b/tests/testthat/test_utils.R @@ -26,3 +26,31 @@ test_that("get_nout works", { expect_equal(get_nout(tsk("iris")), 3) expect_equal(get_nout(tsk("mtcars")), 1) }) + +test_that("assert_shape works", { + expect_true(is.null(assert_shape(NULL, null_ok = TRUE))) + expect_error(assert_shape(NULL, null_ok = FALSE)) + + # valid examples + expect_integer(assert_shape(c(NA, 1))) + expect_integer(assert_shape(c(NA, 1, 2))) + expect_integer(assert_shape(c(NA, NA), unknown_ok = TRUE)) + + # at least 2 dims + expect_error(assert_shape(NA)) + # one NA in batch dim + expect_error(assert_shape(c(1, NA))) + expect_error(assert_shape(c(NA, NA, unknown_ok = FALSE))) +}) + +test_that("assert_shapes works", { + expect_list(assert_shapes(list(c(NA, 1, 2), c(NA, 1)), named = FALSE)) + expect_error(assert_shapes(list(c(NA, 1, 2), c(NA, 1)), named = TRUE)) + + expect_list(assert_shapes(list(a = c(NA, 1, 2), b = c(NA, 1)), named = TRUE)) + expect_error(assert_shapes(list(a = NULL, b = c(NA, 1)), named = TRUE)) +}) + +test_that("uniqueify works", { + expect_equal(uniqueify("a", "a"), "a_1") +}) From ccbca0a7c95d290ddff80b66b18324da79aa5ab9 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 27 Oct 2023 19:46:23 +0200 Subject: [PATCH 10/90] some progress --- DESCRIPTION | 3 +- R/PipeOpTaskPreprocTorch.R | 13 +- R/PipeOpTorchIngress.R | 99 ++++++++++++--- R/TaskClassif_lazy_iris.R | 35 ++++++ R/bibentries.R | 12 ++ R/lazy_tensor.R | 13 +- R/materialize.R | 111 +++++++++------- R/preprocess.R | 10 +- R/utils.R | 33 ++++- R/zzz.R | 1 + lazy_tensor_old.R | 14 --- man/materialize.Rd | 12 +- man/mlr_pipeops_preproc_torch_overview.Rd | 8 +- man/mlr_pipeops_torch_ingress_categ.Rd | 6 +- man/mlr_pipeops_torch_ingress_ltnsr.Rd | 64 ++++++++-- man/mlr_pipeops_torch_ingress_num.Rd | 6 +- man/mlr_tasks_lazy_iris.Rd | 20 +++ tests/testthat/helper_tasks.R | 19 ++- tests/testthat/test_PipeOpTorch.R | 4 +- tests/testthat/test_lazy_tensor.R | 5 + tests/testthat/test_materialize.R | 146 ++++++++++++++++++---- tests/testthat/test_task_dataset.R | 8 ++ 22 files changed, 506 insertions(+), 136 deletions(-) create mode 100644 R/TaskClassif_lazy_iris.R delete mode 100644 lazy_tensor_old.R create mode 100644 man/mlr_tasks_lazy_iris.Rd diff --git a/DESCRIPTION b/DESCRIPTION index afce1fc1..e4876942 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -101,6 +101,7 @@ Collate: 'PipeOpTorchConvTranspose.R' 'PipeOpTorchDropout.R' 'PipeOpTorchHead.R' + 'utils.R' 'PipeOpTorchIngress.R' 'PipeOpTorchLayerNorm.R' 'PipeOpTorchLinear.R' @@ -113,6 +114,7 @@ Collate: 'PipeOpTorchReshape.R' 'PipeOpTorchSoftmax.R' 'ResamplingRowRoles.R' + 'TaskClassif_lazy_iris.R' 'TaskClassif_mnist.R' 'TaskClassif_tiny_imagenet.R' 'TorchDescriptor.R' @@ -130,5 +132,4 @@ Collate: 'rd_info.R' 'reset_last_layer.R' 'task_dataset.R' - 'utils.R' 'with_torch_settings.R' diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 98d5ef38..013776da 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -220,7 +220,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", shapes_out = function(shapes_in, stage = NULL, task = NULL) { assert_r6(task, "Task", null.ok = TRUE) assert_choice(stage, c("train", "predict")) - assert_shapes(shapes_in, named = FALSE) + assert_shapes(shapes_in, named = FALSE, unknown_ok = TRUE) names(shapes_in) = NULL if (is.null(private$.shapes_out)) { @@ -238,7 +238,13 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", } s = if (private$.per_column) { - map(shapes_in, function(s) private$.shapes_out(list(s), param_vals = pv, task = task)[[1L]]) + map(shapes_in, function(s) { + if (all(is.na(s))) { + s + } else { + private$.shapes_out(list(s), param_vals = pv, task = task)[[1L]] + } + }) } else { private$.shapes_out(shapes_in, param_vals = pv, task = task) } @@ -497,8 +503,9 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out = NULL, param_set = NUL return(Class) } -register_preproc = function(id, fn, param_set = NULL, shapes_out = NULL, packages) { +register_preproc = function(id, fn, param_set = NULL, shapes_out = NULL, packages = character(0)) { Class = pipeop_preproc_torch_class(id, fn, param_set = substitute(param_set), shapes_out = shapes_out, packages = packages) + assign(Class$classname, Class, parent.frame()) register_po(id, Class) } diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index 70b887b4..1f5911fd 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -182,9 +182,9 @@ print.TorchIngressToken = function(x, ...) { #' graph = po("select", selector = selector_type(c("numeric", "integer"))) %>>% #' po("torch_ingress_num") #' task = tsk("german_credit") -#' # The output is a TorchIngressToken -#' token = graph$train(task)[[1L]] -#' ingress = token$ingress[[1L]] +#' # The output is a model descriptor +#' md = graph$train(task)[[1L]] +#' ingress = md$ingress[[1L]] #' ingress$batchgetter(task$data(1:5, ingress$features), "cpu") PipeOpTorchIngressNumeric = R6Class("PipeOpTorchIngressNumeric", inherit = PipeOpTorchIngress, @@ -233,9 +233,9 @@ register_po("torch_ingress_num", PipeOpTorchIngressNumeric) #' graph = po("select", selector = selector_type("factor")) %>>% #' po("torch_ingress_categ") #' task = tsk("german_credit") -#' # The output is a TorchIngressToken -#' token = graph$train(task)[[1L]] -#' ingress = token$ingress[[1L]] +#' # The output is a model descriptor +#' md = graph$train(task)[[1L]] +#' ingress = md$ingress[[1L]] #' ingress$batchgetter(task$data(1, ingress$features), "cpu") PipeOpTorchIngressCategorical = R6Class("PipeOpTorchIngressCategorical", inherit = PipeOpTorchIngress, @@ -317,23 +317,66 @@ register_po("torch_ingress_img", PipeOpTorchIngressImage) #' @title Ingress for Lazy Tensor #' @name mlr_pipeops_torch_ingress_ltnsr #' @description -#' Ingress for [`lazy_tensor`] column. -#' This ingress might not return the #' @inheritSection mlr_pipeops_torch_ingress Input and Output Channels +#' Ingress for a single [`lazy_tensor`] column. +#' +#' @inheritSection mlr_pipeops_torch_ingress Input and Output Channels #' @inheritSection mlr_pipeops_torch_ingress State #' #' @section Parameters: -#' No parameters. +#' * `shape` :: `integer()`\cr +#' The shape of the tensor, excluding the batch dimension. +#' Whether it is necessary to specify the shape depends on whether the lazy tensor input column has a known shape. +#' If the input shape is known, this parameter can be set, but must match the input shape. #' #' @section Internals: -#' The output of the created batchgetter merely returns the data as is. -#' The dataset is then responsible to materialize the tensors. -#' By doing so, the data-loading can be made more efficient, e.g. when two different ingress tokens exist -#' for lazy tensors columns that share the same dataset. +#' The returned batchgetter materializes the lazy tensor column to a tensor. #' @family PipeOps #' @family Graph Network #' @export +#' @include utils.R #' @examples -#' TODO: +#' po_ingress = po("torch_ingress_ltnsr") +#' task = tsk("lazy_iris") +#' +#' md = po_ingress$train(list(task))[[1L]] +#' +#' ingress = md$ingress +#' x_batch = ingress[[1L]]$batchgetter( data = task$data(1, "x"), device = "cpu", cache = NULL) +#' x_batch +#' +#' # Now we try a lazy tensor with unknown shape, i.e. the shapes between the rows can differ +#' +#' ds = dataset( +#' initialize = function() self$x = list(torch_randn(3, 10, 10), torch_randn(10, 8, 8)), +#' .getitem = function(i) list(x = self$x[[i]]), +#' .length = function() 2)() +#' +#' task_unknown = as_task_regr(data.table( +#' x = as_lazy_tensor(ds, dataset_shapes = list(x = c(NA, NA, NA, NA))), +#' y = rnorm(2) +#' ), target = "y", id = "example2") +#' +#' # this task (as it is) can NOT be processed by PipeOpTorchIngressLazyTensor +#' # It therefore needs to be preprocessed +#' po_resize = po("trafo_resize", size = c(6, 6)) +#' task_unknown_resize = po_resize$train(list(task_unknown))[[1L]] +#' +#' # printing the transformed column still hows unknown shapes, because the preprocessing pipeop cannot infer +#' # the shapes, however we know that the shape is now (3, 10, 10) for all rows +#' task_unknown_resize$data(1:2, "x") +#' po_ingress$param_set$set_values(shape = c(NA, 3, 6, 6)) +#' +#' md2 = po_ingress$train(list(task_unknown_resize))[[1L]] +#' +#' ingress2 = md2$ingress +#' x_batch2 = ingress2[[1L]]$batchgetter( +#' data = task_unknown_resize$data(1:2, "x"), +#' device = "cpu", +#' cache = NULL +#' ) +#' +#' x_batch2 +#' PipeOpTorchIngressLazyTensor = R6Class("PipeOpTorchIngressLazyTensor", inherit = PipeOpTorchIngress, public = list( @@ -341,26 +384,46 @@ PipeOpTorchIngressLazyTensor = R6Class("PipeOpTorchIngressLazyTensor", #' Creates a new instance of this [R6][R6::R6Class] class. #' @template params_pipelines initialize = function(id = "torch_ingress_ltnsr", param_vals = list()) { - super$initialize(id = id, param_vals = param_vals, feature_types = "lazy_tensor") + param_set = ps( + shape = p_uty(tags = "train", custom_check = check_shape) + ) + super$initialize(id = id, param_vals = param_vals, feature_types = "lazy_tensor", param_set = param_set) } ), private = list( .shape = function(task, param_vals) { lazy_cols = task$feature_types[get("type") == "lazy_tensor", "id"][[1L]] if (length(lazy_cols) != 1L) { - stopf("PipeOpTorchIngressLazyTensor expects 1 lazy_tensor feature, but got %i.", length(lazy_cols)) + stopf("PipeOpTorchIngressLazyTensor expects 1 'lazy_tensor' feature, but got %i.", length(lazy_cols)) } example = task$data(task$row_ids[1L], lazy_cols)[[1L]][[1L]] - example$.pointer_shape + input_shape = example$.pointer_shape + pv_shape = param_vals$shape + + if (all(is.na(input_shape))) { + pv_shape = assert_shape(pv_shape, null_ok = FALSE) + if (length(input_shape) != length(pv_shape)) { + stopf("Number of dimensions of lazy_tensor column '%s' does not match those of parameter 'shape' set in PipeOp '%s'.", # nolint + lazy_cols, self$id) + } + return(pv_shape) + } + + if (!is.null(pv_shape) && isTRUE(all.equal(pv_shape, input_shape))) { + stopf("Parameter 'shape' is set for PipeOp '%s', but differs from the (known) lazy tensor input shape.", self$id) # nolint + } + + input_shape }, .get_batchgetter = function(task, param_vals) { - # FIXME: Various checks batchgetter_lazy_tensor } ) ) batchgetter_lazy_tensor = function(data, device, cache) { + # FIXME: Should we here check for the shapes? + # If the user set them wrong, the network should fail anyway materialize_internal(x = data[[1L]], device = device, cache = cache, rbind = TRUE) } diff --git a/R/TaskClassif_lazy_iris.R b/R/TaskClassif_lazy_iris.R new file mode 100644 index 00000000..ae6819ac --- /dev/null +++ b/R/TaskClassif_lazy_iris.R @@ -0,0 +1,35 @@ +#' @title Iris Classification Task +#' +#' @name mlr_tasks_lazy_iris +#' @format [R6::R6Class] inheriting from [TaskClassif]. +#' @include zzz.R +#' +#' @description +#' A classification task for the popular [datasets::iris] data set. +#' Just like the the iris task from mlr3, but the features are represented as one lazy tensor column. +#' +#' @source +#' \url{https://en.wikipedia.org/wiki/Iris_flower_data_set} +#' +#' `r format_bib("anderson_1936")` +#' +NULL + +load_task_lazy_iris = function(id = "lazy_iris") { + d = load_dataset("iris", "datasets") + target = d[, 5] + features = as.matrix(d[, -5]) + + d = data.table( + Species = target, + x = as_lazy_tensor(features) + ) + + b = as_data_backend(d) + task = TaskClassif$new(id, b, target = "Species", label = "Iris Flowers") + b$hash = task$man = "mlr3torch::mlr_tasks_lazy_iris" + task +} + +#' @include zzz.R +mlr3torch_tasks[["lazy_iris"]] = load_task_lazy_iris diff --git a/R/bibentries.R b/R/bibentries.R index 6e4d7289..452e87e7 100644 --- a/R/bibentries.R +++ b/R/bibentries.R @@ -73,5 +73,17 @@ bibentries = c( # nolint start number='11', pages='2278-2324', doi='10.1109/5.726791' + ), + anderson_1936 = bibentry("article", + doi = "10.2307/2394164", + year = "1936", + month = "9", + publisher = "JSTOR", + volume = "23", + number = "3", + pages = "457", + author = "Edgar Anderson", + title = "The Species Problem in Iris", + journal = "Annals of the Missouri Botanical Garden" ) ) # nolint end diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index 7afff374..6745f04d 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -100,7 +100,10 @@ DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NU } # We get a warning that package:mlr3torch may not be available when loading (?) + # for some reason, the hash of the dataset changes + #dataset_hash = calculate_hash(dataset, dataset_shapes) dataset_hash = calculate_hash(dataset, dataset_shapes) + obj = structure( list( dataset = dataset, @@ -161,7 +164,13 @@ lazy_tensor = function(data_descriptor = NULL, ids = NULL) { } new_lazy_tensor = function(data_descriptor, ids) { - vctrs::new_vctr(ids, data_descriptor = data_descriptor, class = "lazy_tensor") + hash = data_descriptor$.hash + # previously, only the id was included and not the hash + # this led to issues with stuff like unlist(), which dropped attribute and suddenly the lazy_tensor column + # was a simple integer vector. (this caused stuff like PipeOpFeatureUnion to go havock and lead to bugs) + # For this reason, we now also include the hash of the data_descriptor + # We can then later also use this to support different DataDescriptors in a single lazy tensor column + vctrs::new_vctr(map(ids, function(id) list(id, hash)), data_descriptor = data_descriptor, class = "lazy_tensor") } #' @export @@ -311,7 +320,7 @@ transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { data_descriptor$.info$.pointer_shape_predict = shape_predict data_descriptor = set_data_descriptor_hash(data_descriptor) - new_lazy_tensor(data_descriptor, vec_data(lt)) + new_lazy_tensor(data_descriptor, map_int(vec_data(lt), 1)) } #' @export diff --git a/R/materialize.R b/R/materialize.R index 91f48a6c..fa4d1ec3 100644 --- a/R/materialize.R +++ b/R/materialize.R @@ -1,9 +1,11 @@ #' @title Materialize Lazy Tensor Columns #' @description -#' This will materialize a [`lazy_tensor()`] or a [`data.frame()`] / [`list()`] containing -- among other things -- +#' This will materialize a [`lazy_tensor()`] or a `data.frame()` / `list()` containing -- among other things -- #' [`lazy_tensor()`] columns. -#' I.e. the data described in the underlying [`DataDescriptors`] is loaded for the indices in the [`lazy_tensor()`] -#' and is afterwards put on the specified device. +#' I.e. the data described in the underlying [`DataDescriptors`] is loaded for the indices in the [`lazy_tensor()`], +#' is preprocessed and then put unto the specified device. +#' Because not all elements in a lazy tensor must have the same shape, a list of tensors is returned by default. +#' If all elements have the same shape, these tensors can also be rbinded into a single tensor (parameter `rbind`). #' #' @details #' Materializing a lazy tensor consists of: @@ -17,13 +19,14 @@ #' #' For this reason it is possible to provide a cache environment. #' The hash key for a) is the hash of the indices and the dataset. -#' The hash key for b) is the hash of the indices dataset and preprocessing graph. +#' The hash key for b) is the hash of the indices, dataset and preprocessing graph. +#' #' @param x (any)\cr #' The object to materialize. #' Either a [`lazy_tensor`] or a `list()` / `data.frame()` containing [`lazy_tensor`] columns. #' @param rbind (`logical(1)`)\cr #' Whether to rbind the lazy tensor columns (`TRUE`) or return them as a list of tensors (`FALSE`). -#' @return ([`torch_tensor()`] or [`list()`]) +#' @return (`list()` of [`lazy_tensor`]s or a [`lazy_tensor`]) #' @export #' @examples #' lt1 = as_lazy_tensor(torch_randn(10, 3)) @@ -39,39 +42,46 @@ materialize = function(x, device = "cpu", rbind = FALSE, ...) { UseMethod("materialize") } +#' @param cache (`character(1)` or `environment()` or `NULL`)\cr +#' Optional cache for (intermediate) materialization results. +#' Per default, caching will be enabled when the same dataset / graph is used for more than one lazy tensor column. #' @export -materialize.list = function(x, device = "cpu", rbind = FALSE) { # nolint - # FIXME: smarter cache detecting - cache = if (sum(map_lgl(x, is_lazy_tensor)) > 1L) { - new.env() +materialize.list = function(x, device = "cpu", rbind = FALSE, cache = "auto") { # nolint + x_lt = x[map_lgl(x, is_lazy_tensor)] + assert(check_choice(cache, "auto"), check_environment(cache, null.ok = TRUE)) + + if (identical(cache, "auto")) { + data_hashes = map_chr(x_lt, function(x) x$.dataset_hash) + hashes = map_chr(x_lt, function(x) x$.hash) + cache = if (uniqueN(data_hashes) > 1L || uniqueN(hashes) > 1L) { + new.env() + } } + # if we are materializing more than one lazy tensor, we must specify what we want to keep from the graph + # BEFORE calling materialize_internal because materialize_internal does not know about the other columns keep_results_prev = list() - walk(x, function(col) { - if (is_lazy_tensor(col)) { - graph = attr(col, "data_descriptor")$graph - keep_results_prev[[graph$hash]] = graph$keep_results - graph$keep_results = character() - } + keep_results_prev = map(x_lt, function(x) { + graph = x$graph + keep_results = graph$keep_results + graph$keep_results = character(0) + return(keep_results) }) - # clean up the keep_results after - on.exit({walk(x, function(col) { # nolint - if (is_lazy_tensor(x)) { - graph = x$graph - graph$keep_results = keep_results_prev[[graph$hash]] - } - })}, add = TRUE) + on.exit({ + walk(seq_along(x_lt), function(i) { + graph = x_lt[[i]]$graph + graph$keep_results = keep_results_prev[[i]] + }) + }, add = TRUE) - walk(x, function(col) { - if (is_lazy_tensor(col)) { - dd = attr(col, "data_descriptor") - dd$graph$keep_results = union(dd$graph$keep_results, dd$.pointer[1L]) - } + walk(x_lt, function(col) { + graph = col$graph + graph$keep_results = union(graph$keep_results, col$.pointer[1L]) }) - # TODO: No hashing when there is only one column map(x, function(col) { if (is_lazy_tensor(col)) { + browser() materialize_internal(col, device = device, cache = cache, set_keep_results = FALSE, rbind = rbind) } else { col @@ -80,6 +90,15 @@ materialize.list = function(x, device = "cpu", rbind = FALSE) { # nolint } + + +#' @method materialize data.frame +#' @export +materialize.data.frame = function(x, device = "cpu", rbind = FALSE, cache = "auto") { # nolint + materialize(as.list(x), device = device, rbind = rbind, cache = cache) +} + + #' @export materialize.lazy_tensor = function(x, device = "cpu", rbind = FALSE) { # nolint materialize_internal(x = x, device = device, cache = NULL, set_keep_results = TRUE, rbind = rbind) @@ -125,11 +144,12 @@ materialize_internal = function(x, device = "cpu", cache = NULL, set_keep_result stopf("Cannot materialize lazy tensor of length 0.") } do_caching = !is.null(cache) - ids = vec_data(x) + ids = map_int(vec_data(x), 1) - data_descriptor = attr(x, "data_descriptor") + data_descriptor = x$data_descriptor ds = data_descriptor$dataset graph = data_descriptor$graph + varying_shapes = some(data_descriptor$dataset_shapes, function(shape) all(is.na(shape))) if (set_keep_results) { prev_results = graph$keep_results @@ -157,10 +177,10 @@ materialize_internal = function(x, device = "cpu", cache = NULL, set_keep_result if (!do_caching || !input_hit) { input = if (is.null(ds$.getbatch)) { # .getindex is never NULL but a function that errs if it was not defined x = map(ids, function(id) map(ds$.getitem(id), function(x) x$unsqueeze(1))) - if (rbind) { - map(transpose_list(x), function(x) torch_cat(x, dim = 1L)) - } else { + if (varying_shapes || !rbind) { x + } else { + map(transpose_list(x), function(x) torch_cat(x, dim = 1L)) } } else { if (rbind) { @@ -180,7 +200,7 @@ materialize_internal = function(x, device = "cpu", cache = NULL, set_keep_result # This is done after retrieving the element from the cache / before saving the element to the cache because # this can change - input = if (rbind) { + input = if (rbind && !varying_shapes) { set_names(input[data_descriptor$.input_map], data_descriptor$.graph_input) } else { map(input, function(x) { @@ -188,18 +208,28 @@ materialize_internal = function(x, device = "cpu", cache = NULL, set_keep_result }) } - output = if (rbind) { - # in this case, input is a tensor + output = if (rbind && !varying_shapes) { + # tensor --graph--> tensor graph$train(input, single_input = FALSE) out = map(data_descriptor$graph$keep_results, function(id) graph$pipeops[[id]]$.result) set_names(out, data_descriptor$graph$keep_results) } else { - # in this case, input is a list of tensors - map(input, function(x) { + # list --graph--> (list or tensor) + out = map(input, function(x) { graph$train(x, single_input = FALSE) out = map(data_descriptor$graph$keep_results, function(id) graph$pipeops[[id]]$.result) set_names(out, data_descriptor$graph$keep_results) }) + if (rbind) { + # here, is a list with hierarchy: [id = [po_id = [ch_nm = ]]] + # We want to obtain a list [po_id = [ch_nm = [...]]] where the [...] is the rbind over all ids + out = map(names(out[[1L]]), function(po_id) { + map(names(out[[1]][[po_id]]), function(ch_nm) { + torch_cat(map(seq_along(out), function(i) out[[i]][[po_id]][[ch_nm]]), dim = 1L) + }) + }) + } + out } if (do_caching) { @@ -217,8 +247,3 @@ materialize_internal = function(x, device = "cpu", cache = NULL, set_keep_result return(res) } - - -#' @method materialize data.frame -#' @export -materialize.data.frame = materialize.list # nolint diff --git a/R/preprocess.R b/R/preprocess.R index 8bd0cdf3..36ec92c9 100644 --- a/R/preprocess.R +++ b/R/preprocess.R @@ -2,8 +2,6 @@ #' @description #' Overview over all implemented preprocessing methods. #' See [`PipeOpTaskPreprocTorch`] for more details on the class itself. -#' @section Overview: -#' * trafo_resize: Calls [`torchvision::transform_resize`] #' @usage NULL #' @format NULL #' @name mlr_pipeops_preproc_torch_overview @@ -19,6 +17,8 @@ table_preproc = function() { #' @name PipeOpPreprocTorchTrafoResize #' @rdname mlr_pipeops_preproc_torch_overview +#' @description +#' * `trafo_resize`: Calls [`torchvision::transform_resize`] register_preproc("trafo_resize", torchvision::transform_resize, packages = "torchvision", param_set = ps( @@ -38,6 +38,12 @@ register_preproc("trafo_resize", torchvision::transform_resize, } ) +#' @name PipeOpPreprocTorchTrafoNop +#' @rdname mlr_pipeops_preproc_torch_overview +#' @description +#' * `trafo_nop`: Calls `identity()`. +register_preproc("trafo_nop", identity) + ## Preprocessing: diff --git a/R/utils.R b/R/utils.R index 8e496f0b..81837d60 100644 --- a/R/utils.R +++ b/R/utils.R @@ -177,19 +177,42 @@ argument_matcher = function(args) { #' @param null_ok (`logical(1)`) #' @param unknown_ok (`logical(1)`) assert_shape = function(shape, null_ok = FALSE, unknown_ok = FALSE) { # nolint - if (is.null(shape) && null_ok) return(shape) - shape = assert_integerish(shape, min.len = 2L, all.missing = TRUE, coerce = TRUE) + if (!test_shape(shape, null_ok = null_ok, unknown_ok = unknown_ok)) { + stopf("Invalid shape.") + } + if (is.null(shape)) { + return(NULL) + } + return(as.integer(shape)) +} + +test_shape = function(shape, null_ok = FALSE, unknown_ok = FALSE) { + if (is.null(shape) && null_ok) { + return(TRUE) + } + ok = test_integerish(shape, min.len = 2L, all.missing = TRUE) + + if (!ok) { + return(FALSE) + } is_na = is.na(shape) all_na = all(is_na) if (all_na && unknown_ok) { - return(shape) + return(TRUE) } if (!is_na[[1L]] || anyNA(shape[-1L])) { - stopf("Shape must have exactly one NA in the batch dimension.") + return(FALSE) + } + return(TRUE) +} + +check_shape = function(x, null_ok = FALSE, unknown_ok = FALSE) { + if (test_shape(x, null_ok = null_ok, unknown_ok = unknown_ok)) { + return(TRUE) } - return(shape) + "Must be a valid shape." } assert_shapes = function(shapes, named = TRUE, unknown_ok = FALSE) { # nolint diff --git a/R/zzz.R b/R/zzz.R index 2fe92700..ffca8d18 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -26,6 +26,7 @@ mlr3torch_pipeops = new.env() mlr3torch_learners = new.env() mlr3torch_tasks = new.env() mlr3torch_resamplings = new.env() +mlr3torch_task_generators = new.env() mlr3torch_pipeop_tags = c("torch", "activation") mlr3torch_feature_types = c(img = "imageuri", lt = "lazy_tensor") diff --git a/lazy_tensor_old.R b/lazy_tensor_old.R deleted file mode 100644 index 253d60de..00000000 --- a/lazy_tensor_old.R +++ /dev/null @@ -1,14 +0,0 @@ -#' @export -format.lazy_tensor = function(x, ...) { # nolint - if (!length(x)) return(character(0)) - shape = paste0(x$shape[-1L], collapse = "x") - map_chr(x, function(elt) { - sprintf("", shape) - }) -} - - -#' @export -vec_ptype_abbr.lazy_tensor <- function(x, ...) { # nolint - "ltnsr" -} diff --git a/man/materialize.Rd b/man/materialize.Rd index 604698b8..7396682a 100644 --- a/man/materialize.Rd +++ b/man/materialize.Rd @@ -15,13 +15,15 @@ Either a \code{\link{lazy_tensor}} or a \code{list()} / \code{data.frame()} cont Whether to rbind the lazy tensor columns (\code{TRUE}) or return them as a list of tensors (\code{FALSE}).} } \value{ -(\code{\link[=torch_tensor]{torch_tensor()}} or \code{\link[=list]{list()}}) +(\code{list()} of \code{\link{lazy_tensor}}s or a \code{\link{lazy_tensor}}) } \description{ -This will materialize a \code{\link[=lazy_tensor]{lazy_tensor()}} or a \code{\link[=data.frame]{data.frame()}} / \code{\link[=list]{list()}} containing -- among other things -- +This will materialize a \code{\link[=lazy_tensor]{lazy_tensor()}} or a \code{data.frame()} / \code{list()} containing -- among other things -- \code{\link[=lazy_tensor]{lazy_tensor()}} columns. -I.e. the data described in the underlying \code{\link{DataDescriptors}} is loaded for the indices in the \code{\link[=lazy_tensor]{lazy_tensor()}} -and is afterwards put on the specified device. +I.e. the data described in the underlying \code{\link{DataDescriptors}} is loaded for the indices in the \code{\link[=lazy_tensor]{lazy_tensor()}}, +is preprocessed and then put unto the specified device. +Because not all elements in a lazy tensor must have the same shape, a list of tensors is returned by default. +If all elements have the same shape, these tensors can also be rbinded into a single tensor (parameter \code{rbind}). } \details{ Materializing a lazy tensor consists of: @@ -37,7 +39,7 @@ b) Different lazy tensors might be outputs from the same graph. For this reason it is possible to provide a cache environment. The hash key for a) is the hash of the indices and the dataset. -The hash key for b) is the hash of the indices dataset and preprocessing graph. +The hash key for b) is the hash of the indices, dataset and preprocessing graph. } \examples{ lt1 = as_lazy_tensor(torch_randn(10, 3)) diff --git a/man/mlr_pipeops_preproc_torch_overview.Rd b/man/mlr_pipeops_preproc_torch_overview.Rd index b4d5d951..3f0c9fca 100644 --- a/man/mlr_pipeops_preproc_torch_overview.Rd +++ b/man/mlr_pipeops_preproc_torch_overview.Rd @@ -3,15 +3,17 @@ \name{mlr_pipeops_preproc_torch_overview} \alias{mlr_pipeops_preproc_torch_overview} \alias{PipeOpPreprocTorchTrafoResize} +\alias{PipeOpPreprocTorchTrafoNop} \title{Lazy Preprocessing and Transformations} \description{ Overview over all implemented preprocessing methods. See \code{\link{PipeOpTaskPreprocTorch}} for more details on the class itself. + +\itemize{ +\item \code{trafo_resize}: Calls \code{\link[torchvision:transform_resize]{torchvision::transform_resize}} } -\section{Overview}{ \itemize{ -\item trafo_resize: Calls \code{\link[torchvision:transform_resize]{torchvision::transform_resize}} +\item \code{trafo_nop}: Calls \code{identity()}. } } - diff --git a/man/mlr_pipeops_torch_ingress_categ.Rd b/man/mlr_pipeops_torch_ingress_categ.Rd index 5abeb625..c7ae7247 100644 --- a/man/mlr_pipeops_torch_ingress_categ.Rd +++ b/man/mlr_pipeops_torch_ingress_categ.Rd @@ -36,9 +36,9 @@ The state is set to the input shape. graph = po("select", selector = selector_type("factor")) \%>>\% po("torch_ingress_categ") task = tsk("german_credit") -# The output is a TorchIngressToken -token = graph$train(task)[[1L]] -ingress = token$ingress[[1L]] +# The output is a model descriptor +md = graph$train(task)[[1L]] +ingress = md$ingress[[1L]] ingress$batchgetter(task$data(1, ingress$features), "cpu") } \seealso{ diff --git a/man/mlr_pipeops_torch_ingress_ltnsr.Rd b/man/mlr_pipeops_torch_ingress_ltnsr.Rd index d8d471e7..7d4926d4 100644 --- a/man/mlr_pipeops_torch_ingress_ltnsr.Rd +++ b/man/mlr_pipeops_torch_ingress_ltnsr.Rd @@ -5,20 +5,27 @@ \alias{PipeOpTorchIngressLazyTensor} \title{Ingress for Lazy Tensor} \description{ -Ingress for \code{\link{lazy_tensor}} column. -This ingress might not return the #' @inheritSection mlr_pipeops_torch_ingress Input and Output Channels +Ingress for a single \code{\link{lazy_tensor}} column. } \section{Parameters}{ -No parameters. +\itemize{ +\item \code{shape} :: \code{integer()}\cr +The shape of the tensor, excluding the batch dimension. +Whether it is necessary to specify the shape depends on whether the lazy tensor input column has a known shape. +If the input shape is known, this parameter can be set, but must match the input shape. +} } \section{Internals}{ -The output of the created batchgetter merely returns the data as is. -The dataset is then responsible to materialize the tensors. -By doing so, the data-loading can be made more efficient, e.g. when two different ingress tokens exist -for lazy tensors columns that share the same dataset. +The returned batchgetter materializes the lazy tensor column to a tensor. +} + +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. } \section{State}{ @@ -27,7 +34,48 @@ The state is set to the input shape. } \examples{ -TODO: +po_ingress = po("torch_ingress_ltnsr") +task = tsk("lazy_iris") + +md = po_ingress$train(list(task))[[1L]] + +ingress = md$ingress +x_batch = ingress[[1L]]$batchgetter( data = task$data(1, "x"), device = "cpu", cache = NULL) +x_batch + +# Now we try a lazy tensor with unknown shape, i.e. the shapes between the rows can differ + +ds = dataset( + initialize = function() self$x = list(torch_randn(3, 10, 10), torch_randn(10, 8, 8)), + .getitem = function(i) list(x = self$x[[i]]), + .length = function() 2)() + +task_unknown = as_task_regr(data.table( + x = as_lazy_tensor(ds, dataset_shapes = list(x = c(NA, NA, NA, NA))), + y = rnorm(2) +), target = "y", id = "example2") + +# this task (as it is) can NOT be processed by PipeOpTorchIngressLazyTensor +# It therefore needs to be preprocessed +po_resize = po("trafo_resize", size = c(6, 6)) +task_unknown_resize = po_resize$train(list(task_unknown))[[1L]] + +# printing the transformed column still hows unknown shapes, because the preprocessing pipeop cannot infer +# the shapes, however we know that the shape is now (3, 10, 10) for all rows +task_unknown_resize$data(1:2, "x") +po_ingress$param_set$set_values(shape = c(NA, 3, 6, 6)) + +md2 = po_ingress$train(list(task_unknown_resize))[[1L]] + +ingress2 = md2$ingress +x_batch2 = ingress2[[1L]]$batchgetter( + data = task_unknown_resize$data(1:2, "x"), + device = "cpu", + cache = NULL +) + +x_batch2 + } \seealso{ Other PipeOps: diff --git a/man/mlr_pipeops_torch_ingress_num.Rd b/man/mlr_pipeops_torch_ingress_num.Rd index f3691f3d..e83ae5ca 100644 --- a/man/mlr_pipeops_torch_ingress_num.Rd +++ b/man/mlr_pipeops_torch_ingress_num.Rd @@ -27,9 +27,9 @@ The state is set to the input shape. graph = po("select", selector = selector_type(c("numeric", "integer"))) \%>>\% po("torch_ingress_num") task = tsk("german_credit") -# The output is a TorchIngressToken -token = graph$train(task)[[1L]] -ingress = token$ingress[[1L]] +# The output is a model descriptor +md = graph$train(task)[[1L]] +ingress = md$ingress[[1L]] ingress$batchgetter(task$data(1:5, ingress$features), "cpu") } \seealso{ diff --git a/man/mlr_tasks_lazy_iris.Rd b/man/mlr_tasks_lazy_iris.Rd new file mode 100644 index 00000000..8dac6945 --- /dev/null +++ b/man/mlr_tasks_lazy_iris.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TaskClassif_lazy_iris.R +\name{mlr_tasks_lazy_iris} +\alias{mlr_tasks_lazy_iris} +\title{Iris Classification Task} +\format{ +\link[R6:R6Class]{R6::R6Class} inheriting from \link{TaskClassif}. +} +\source{ +\url{https://en.wikipedia.org/wiki/Iris_flower_data_set} + +Anderson E (1936). +\dQuote{The Species Problem in Iris.} +\emph{Annals of the Missouri Botanical Garden}, \bold{23}(3), 457. +\doi{10.2307/2394164}. +} +\description{ +A classification task for the popular \link[datasets:iris]{datasets::iris} data set. +Just like the the iris task from mlr3, but the features are represented as one lazy tensor column. +} diff --git a/tests/testthat/helper_tasks.R b/tests/testthat/helper_tasks.R index 42109805..d8e2b75c 100644 --- a/tests/testthat/helper_tasks.R +++ b/tests/testthat/helper_tasks.R @@ -4,7 +4,20 @@ nano_dogs_vs_cats = function(id = "nano_dogs_vs_cats") { image_names = list.files(path) uris = normalizePath(file.path(path, image_names)) - images = imageuri(uris) + ds = dataset("dogs_vs_cats", + initialize = function(uris) { + self$uris = uris + }, + .getitem = function(id) { + list(x = torchvision::transform_to_tensor(magick::image_read(self$uris[id]))$to(dtype = torch_float32())) + }, + .length = function() { + length(self$uris) + } + )(uris) + + + images = as_lazy_tensor(ds, dataset_shapes = list(x = rep(NA_integer_, 4))) labels = map_chr(image_names, function(name) { if (startsWith(name, "cat")) { @@ -18,9 +31,9 @@ nano_dogs_vs_cats = function(id = "nano_dogs_vs_cats") { labels = factor(labels) - dat = data.table(x = images, animal = labels) + dat = data.table(x = images, y = labels) - task = as_task_classif(dat, id = "nano_dogs_vs_cats", label = "Cats vs Dogs", target = "animal", positive = "cat") + task = as_task_classif(dat, id = "nano_dogs_vs_cats", label = "Cats vs Dogs", target = "y", positive = "cat") task } diff --git a/tests/testthat/test_PipeOpTorch.R b/tests/testthat/test_PipeOpTorch.R index 4144e9a2..ad52d193 100644 --- a/tests/testthat/test_PipeOpTorch.R +++ b/tests/testthat/test_PipeOpTorch.R @@ -134,9 +134,9 @@ test_that("PipeOpTorch errs when there are unexpected NAs in the shape", { md = graph$train(task)[[1L]] md$.pointer_shape = c(4, NA) - expect_error(po("nn_relu")$train(list(md)), regexp = "must have exactly one NA") + expect_error(po("nn_relu")$train(list(md)), regexp = "Invalid shape") md$.pointer_shape = c(NA, NA, 4) - expect_error(po("nn_relu")$train(list(md)), regexp = "must have exactly one NA") + expect_error(po("nn_relu")$train(list(md)), regexp = "Invalid shape") }) diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index 6369a3f8..6e911c13 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -128,3 +128,8 @@ test_that("transform_lazy_tensor works", { lt1_mat = torch_reshape(lt1_mat, c(-1, 2, 5)) expect_true(torch_equal(lt1_mat, lt_mat)) }) + +test_that("unlist does not have any surprises", { + + +}) diff --git a/tests/testthat/test_materialize.R b/tests/testthat/test_materialize.R index db6aa57a..8b0a0f05 100644 --- a/tests/testthat/test_materialize.R +++ b/tests/testthat/test_materialize.R @@ -7,19 +7,90 @@ test_that("materialize works on lazy_tensor", { expect_equal(output$shape, c(10, 5, 4)) expect_true(output$device == torch_device("cpu")) expect_true(torch_equal(output, ds$x)) + # the correct elements are returned + expect_torch_equal(ds$.getbatch(1)[[1]], materialize(lt[1])[[1]]) + expect_torch_equal(ds$.getbatch(2)[[1]], materialize(lt[2])[[1]]) + expect_torch_equal(ds$.getbatch(2:1)[[1]], materialize(lt[2:1], rbind = TRUE)) output_meta_list = materialize(lt, device = "meta", rbind = FALSE) output_meta_tnsr = materialize(lt, device = "meta", rbind = TRUE) expect_equal(torch_cat(output_meta_list, dim = 1L)$shape, output_meta_tnsr$shape) expect_true(output_meta_tnsr$device == torch_device("meta")) + + expect_error(materialize(lazy_tensor()), "Cannot materialize ") +}) + +test_that("materialize works with differing shapes (hence uses .getitem)", { + task = nano_dogs_vs_cats() + + lt = task$data(1:2, cols = "x")[[1L]] + + res1 = materialize(lt, rbind = FALSE, device = "meta") + expect_list(res1, types = "torch_tensor") + expect_false(identical(res1[[1]]$shape, res1[[2]]$shape)) + expect_true(res1[[1]]$device == torch_device("meta")) + + # cannot rbind tensors with varying shapes + expect_error(materialize(lt, rbind = TRUE)) }) -test_that("materialize works in all 4 cases", { - # .g +test_that("materialize works with same shapes and .getbatch method", { + task = tsk("lazy_iris") + + x = task$data(1:2, cols = "x")[[1L]] + + res1 = materialize(x, rbind = FALSE, device = "meta") + expect_list(res1, types = "torch_tensor") + expect_true(res1[[1]]$device == torch_device("meta")) + + res2 = materialize(x, rbind = TRUE, device = "meta") + expect_class(res2, "torch_tensor") + expect_true(res2$device == torch_device("meta")) + + res1cpu = materialize(x, rbind = FALSE) + res2cpu = materialize(x, rbind = TRUE) + expect_torch_equal(torch_cat(res1cpu, dim = 1L), res2cpu) + expect_equal(res2cpu$shape, res2$shape) +}) + +test_that("materialize works with same shapes and .getitem method", { + task = nano_mnist() + + x = task$data(1:2, cols = "image")[[1L]] + + res1 = materialize(x, rbind = FALSE, device = "meta") + expect_list(res1, types = "torch_tensor") + expect_true(res1[[1]]$device == torch_device("meta")) + + res2 = materialize(x, rbind = TRUE, device = "meta") + expect_class(res2, "torch_tensor") + expect_true(res2$device == torch_device("meta")) + expect_equal(res2$shape, c(2, 1, 28, 28)) + + res1cpu = materialize(x, rbind = FALSE) + res2cpu = materialize(x, rbind = TRUE) + expect_torch_equal(torch_cat(res1cpu, dim = 1L), res2cpu) + expect_equal(res2cpu$shape, res2$shape) +}) + +test_that("materialize_internal works", { + expect_error(materialize_internal(lazy_tensor()), "Cannot materialize ") + task = tsk("lazy_iris") + x = task$data(1:2, cols = "x")[[1L]] + res1 = materialize(x) + res2 = materialize(x, rbind = TRUE) + expect_list(res1, types = "torch_tensor") + expect_class(res2, "torch_tensor") + expect_torch_equal(torch_cat(res1, dim = 1L), res2) + + res1cpu = materialize(x, rbind = FALSE) + res2cpu = materialize(x, rbind = TRUE) + expect_torch_equal(torch_cat(res1cpu, dim = 1L), res2cpu) }) -test_that("materialize works for data.frame", { + +test_that("materialize.list works", { df = nano_mnist()$data(1:10, cols = "image") out = materialize(df, rbind = TRUE) @@ -27,40 +98,73 @@ test_that("materialize works for data.frame", { expect_equal(names(out), "image") expect_class(out$image, "torch_tensor") expect_equal(out$image$shape, c(10, 1, 28, 28)) + + # to check: + # a) caching works when en / disabling cache manually + # b) set_keep_results stuff works + # c) default = "auto" works as expected + + # TODO + +}) + +test_that("materialize_internal: caching of graphs works", { + cache = new.env() + task = tsk("lazy_iris") + # need to rename because of a nasty bug in pipelines: + # https://github.com/mlr-org/mlr3pipelines/issues/738` + + dt = task$data(1:2, cols = "x") + dt$x1 = dt$x + names(dt) = c("x1", "x2") + + materialize(dt, rbind = TRUE) + }) -test_that("materialize works with differing shapes", { +test_that("materialize_internal: caching of datasets works", { ds = dataset( initialize = function() { - self$x = list( - torch_randn(2, 2), - torch_randn(3, 3) - ) + self$x = torch_randn(10, 3) + self$count = 0 }, .getitem = function(i) { - list(x = self$x[[i]]) + #self$count = self$count + 1 + list(x = self$x[i, ]) }, .length = function() { - length(self$x) + 10 } )() + ds$initialize() + debugonce(print) + print(dataset) + x1 = as_lazy_tensor(ds, list(x = c(NA, 3))) + x2 = as_lazy_tensor(ds, list(x = c(NA, 3))) - dd = DataDescriptor(ds, dataset_shapes = list(x = c(NA, NA, NA))) + x1$.dataset_hash + x2$.dataset_hash + + dd1 = DataDescriptor(ds, list(x = c(NA, 3))) + dd2 = DataDescriptor(ds, list(x = c(NA, 3))) + + dd1$.dataset_hash + dd2$.dataset_hash + + + d = data.table(x1 = x1, x2 = x2) + debugonce(materialize) + materialize(d, rbind = TRUE, cache = new.env()) + expect_true(d$count == 10) - lt = as_lazy_tensor(dd) - expect_class(materialize(lt[1], rbind = TRUE), "torch_tensor") - l = materialize(lt, rbind = FALSE) - expect_class(l, "list") - expect_class(l[[1L]], "torch_tensor") -}) -test_that("caching of datasets works", { - # TODO }) -test_that("caching of graphs works", { - # TODO +test_that("materialize_internal: resets everything to previous state", { + }) +test_that("materialize_internal: set_keep_results works") + diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index f288bcf7..de30ffa2 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -293,3 +293,11 @@ test_that("dataset_img works", { expect_true(batch_meta$x$image$device$type == "meta") }) + +test_that("caching works", { + # TODO +}) + +test_that("merging of graphs works as expected", { + # TODO +}) From 5db7750da487f0f558a3131d3790676860928456 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 27 Oct 2023 20:37:52 +0200 Subject: [PATCH 11/90] bug fix + important test --- R/lazy_tensor.R | 5 ++++- tests/testthat/test_materialize.R | 27 ++++++++++++++++++++------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index 6745f04d..d10ee1a8 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -102,7 +102,10 @@ DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NU # We get a warning that package:mlr3torch may not be available when loading (?) # for some reason, the hash of the dataset changes #dataset_hash = calculate_hash(dataset, dataset_shapes) - dataset_hash = calculate_hash(dataset, dataset_shapes) + dataset$.length() + dataset_hash = calculate_hash(dataset, dataset_shapes"") + # what we could do: + # 1) set the hah as field .__mlr3torch__dataset_hash in the dataset (and check before whether something like this is already set) obj = structure( list( diff --git a/tests/testthat/test_materialize.R b/tests/testthat/test_materialize.R index 8b0a0f05..6535a3b3 100644 --- a/tests/testthat/test_materialize.R +++ b/tests/testthat/test_materialize.R @@ -136,14 +136,15 @@ test_that("materialize_internal: caching of datasets works", { 10 } )() - ds$initialize() - debugonce(print) - print(dataset) x1 = as_lazy_tensor(ds, list(x = c(NA, 3))) x2 = as_lazy_tensor(ds, list(x = c(NA, 3))) - x1$.dataset_hash - x2$.dataset_hash + # hashes of environments change after a function was called (?) + # https://github.com/mlr-org/mlr3torch/issues/156 + expect_equal( + x1$.dataset_hash, + x2$.dataset_hash + ) dd1 = DataDescriptor(ds, list(x = c(NA, 3))) dd2 = DataDescriptor(ds, list(x = c(NA, 3))) @@ -157,14 +158,26 @@ test_that("materialize_internal: caching of datasets works", { materialize(d, rbind = TRUE, cache = new.env()) expect_true(d$count == 10) +}) + +test_that("materialize_internal: resets everything to previous state", { }) -test_that("materialize_internal: resets everything to previous state", { +test_that("materialize_internal: set_keep_results works", { }) -test_that("materialize_internal: set_keep_results works") +test_that("PipeOpFeatureUnion can properly check whether to lazy tensors are identical", { + # when lazy_tensor only stored the integers in the vec_data() (and not integer + hash) this test failed + task = tsk("lazy_iris") + + graph = po("nop") %>>% + list(po("preproc_torch", function(x) x + 1), po("trafo_nop")) %>>% + po("featureunion") + + expect_error(graph$train(task), "cannot aggregate different features sharing") +}) From 7097cb4dfa890db4b46aa99777bdab2f1017ae68 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 3 Nov 2023 14:50:31 +0100 Subject: [PATCH 12/90] tests are passing --- DESCRIPTION | 1 + NAMESPACE | 1 - R/LearnerTorch.R | 2 +- R/PipeOpTaskPreprocTorch.R | 140 ++++++++----------- R/PipeOpTorch.R | 2 +- R/PipeOpTorchIngress.R | 12 +- R/lazy_tensor.R | 51 +++---- R/materialize.R | 1 - R/preprocess.R | 7 +- R/shape.R | 46 ++++++ R/task_dataset.R | 6 +- R/utils.R | 52 ------- R/zzz.R | 23 +-- man/assert_shape.Rd | 10 +- man/mlr_pipeops_preproc_torch.Rd | 39 ++---- man/mlr_pipeops_torch_ingress_ltnsr.Rd | 2 +- man/pipeop_preproc_torch.Rd | 10 +- man/pipeop_preproc_torch_class.Rd | 10 +- tests/testthat/helper_tasks.R | 2 +- tests/testthat/test_PipeOpTaskPreprocTorch.R | 27 +++- tests/testthat/test_lazy_tensor.R | 16 +-- tests/testthat/test_materialize.R | 6 +- tests/testthat/test_utils.R | 24 ---- 23 files changed, 218 insertions(+), 272 deletions(-) create mode 100644 R/shape.R diff --git a/DESCRIPTION b/DESCRIPTION index e4876942..7f2e0191 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -131,5 +131,6 @@ Collate: 'preprocess.R' 'rd_info.R' 'reset_last_layer.R' + 'shape.R' 'task_dataset.R' 'with_torch_settings.R' diff --git a/NAMESPACE b/NAMESPACE index 41e6f200..008a9f7a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,7 +2,6 @@ S3method("$",lazy_tensor) S3method("[",imageuri) -S3method("[",lazy_tensor) S3method("[<-",imageuri) S3method("[[",imageuri) S3method("[[<-",imageuri) diff --git a/R/LearnerTorch.R b/R/LearnerTorch.R index 0d8747ff..9db03387 100644 --- a/R/LearnerTorch.R +++ b/R/LearnerTorch.R @@ -307,7 +307,7 @@ LearnerTorch = R6Class("LearnerTorch", .param_set_base = NULL, .callbacks = NULL, .verify_train_task = function(task, row_ids) { - first_row = task$head(0) + first_row = task$head(1) iwalk(first_row, function(x, nm) { if (!is_lazy_tensor(x)) return(NULL) predict_shape = x$.info$.predict_shape diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 013776da..c8a4c234 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -19,13 +19,13 @@ #' (`list()`, `list(), `Task` or `NULL`) -> `list()`\cr #' This private method calculates the output shapes of the lazy tensor columns that are created from applying #' the preprocessing. -#' Note that the input shapes can be only contain NAs (e.g. (NA, NA, NA)), indicating that only the number of input -#' dimensions is known, but not the exact shape. -#' In this case the output shape should also only contain NAs. #' -#' In case the construction argument `per_column` is `TRUE`, this private method only has the responsibility -#' to calculate the output shapes for one input column, i.e. the input `shapes_in` can be assumed to have +#' This private method only has the responsibility to calculate the output shapes for one input column, i.e. the +#' input `shapes_in` can be assumed to have #' exactly one shape vector for which it must calculate the output shapes and return it as a `list()` of length 1. +#' It can also be assumed, that the shape is not `NULL`. +#' It should also output a shape with exactly one NA in the first dimension. +#' It is also possible to output `NULL`, if the output shape cannot be determined (e.g. because it is random). #' #' Also see the documentation of [`PipeOpTorch`] how to implement this method. #' @@ -36,7 +36,7 @@ #' the paramer values, and whether the preprocessing is applied during training (stage is `"train"`) #' or prediction (stage is `"predict"`). One should not work with the parameters currently set in the paramet set, #' only use those passed as argument `param_vals`. These are the parameters that were specified during the `$train()` -#' call of the [`PipeOp`] (otherwise it cannot be ensured that the shapes encountered during `$predict()` can actually +#' call of the [`PipeOp`] (otherwise it cannot be ensured that the shapes encountered during `$predict()` can actuallT #' be processed by the neural network). #' The method must return a `data.table` with lazy tensor columns. #' The lazy tensor input columns should **not** be modified in-place. @@ -55,17 +55,13 @@ #' Pay attention to set the correct `tags` for the parameters: if tag `"train"` is present, #' the preprocessing is applied during training and if tag `"predict"` is present, the preprocessing is applied #' during prediction (if `augment` is set to `FALSE`). -#' @param per_column (`logical(1)`)\cr -#' Whether the transformation is applied per column. -#' If this is `FALSE`, is applied to all lazy tensor columns at once and might produce -#' one or more new lazy tensor columns. -#' @param augment_init (`logical(1)`)\cr +#' @param augment_init (`logical(1)` or `NULL`)\cr #' Initial value for the `augment` parameter. -#' +#' If it is `NULL`, there is no `augment` parameter. #' @section Input and Output Channels: #' See [`PipeOpTaskPreproc`]. #' @section State: -#' See [`PipeOpTaskPreproc`]. +#' TODO: #' @section Parameters: #' In addition to the parameters inherited from [`PipeOpTaskPreproc`] as well as those specified during construction #' as the argument `param_set` there are the following parameters: @@ -76,19 +72,12 @@ #' This parameter is initialized to `FALSE`. #' #' @section Internals: -#' If `per_column` is `TRUE`: -#' #' A [`PipeOpModule`] with one input and one output channel is created. #' The pipeop simply applies the function `fn` to the input tensor while additionally #' passing the paramter values (minus `augment` and `affect_columns`) to `fn`. #' Then [`transform_lazy_tensor`] is called with the created [`PipeOpModule`] and the shapes obtained from the #' `$shapes_out()` method of this `PipeOp`. #' -#' -#' If `per_column` is `FALSE`: -#' It is the obligation of the user to overwrite the `.transform()` method appropriately. -#' Note that on -#' #' @include PipeOpTorch.R #' @export #' @examples @@ -183,17 +172,15 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' @description #' Creates a new instance of this [`R6`][R6::R6Class] class. initialize = function(fn, id = "preproc_torch", param_vals = list(), param_set = ps(), packages = character(0), - per_column = TRUE, augment_init = FALSE) { - private$.per_column = assert_flag(per_column) - private$.fn = assert_function(fn, null.ok = per_column) - assert_flag(augment_init) - - if (per_column) { - param_set$add(ps( - augment = p_lgl(tags = c("train", "required")) - )) - param_set$set_values(augment = augment_init) - } + augment_init = FALSE) { + private$.fn = assert_function(fn) + assert_flag(augment_init, null.ok = TRUE) + + param_set$add(ps( + augment = p_lgl(tags = c("train", "required")) + )) + param_set$set_values(augment = augment_init) + if (some(param_set$tags, function(tags) "predict" %in% tags)) { stopf("Parameter set cannot contain tags 'predict'.") } @@ -210,46 +197,46 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' Calculates the output shapes that would result in applying the preprocessing to one or more #' lazy tensor columns with the provided shape. #' Names are ignored and only order matters. - #' @param shapes_in (`list()` of `integer()`)\cr + #' It uses the parameeter values that are currently set. + #' @param shapes_in (`list()` of (`integer()` or `NULL`))\cr #' The input input shapes of the lazy tensors. - #' @param task ([`Task`] or `NULL`)\cr - #' The task, which is very rarely needed. + #' `NULL` indicates that the shape is unknown. #' @param stage (`character(1)`)\cr #' The stage: either `"train"` or `"predict"`. - #' @return `list()` of `integer()` + #' @param task ([`Task`] or `NULL`)\cr + #' The task, which is very rarely needed. + #' @return `list()` of (`integer()` or `NULL`) shapes_out = function(shapes_in, stage = NULL, task = NULL) { - assert_r6(task, "Task", null.ok = TRUE) assert_choice(stage, c("train", "predict")) - assert_shapes(shapes_in, named = FALSE, unknown_ok = TRUE) + if (stage == "predict" && is.null(self$state$param_vals)) { + stopf("Predict shapes can only be calculated after training the PipeOp.") + } + assert_r6(task, "Task", null.ok = TRUE) + # either all shapes are NULL or none are NULL + assert_shapes(shapes_in, named = FALSE, null_ok = TRUE) names(shapes_in) = NULL - if (is.null(private$.shapes_out)) { - # shapes_out can only be NULL if per_column is TRUE - return(shapes_in) + pv = if (stage == "train") { + self$param_set$get_values(tags = "train") + } else { + self$state$param_vals } - pv = self$param_set$get_values(tags = "train") augment = pv$augment pv$augment = NULL pv$affect_columns = NULL - if (stage == "predict") { - pv = if (augment) list() else pv + if (is.null(private$.shapes_out) || ((stage == "predict") && augment)) { + return(shapes_in) } - s = if (private$.per_column) { - map(shapes_in, function(s) { - if (all(is.na(s))) { - s - } else { - private$.shapes_out(list(s), param_vals = pv, task = task)[[1L]] - } - }) - } else { - private$.shapes_out(shapes_in, param_vals = pv, task = task) - } + shapes = map(shapes_in, function(s) { + if (!is.null(s)) { + private$.shapes_out(list(s), pv, task)[[1L]] + } + }) - return(s) + return(shapes) } ), private = list( @@ -257,7 +244,6 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", dt_columns = private$.select_cols(task) cols = dt_columns param_vals = self$param_set$get_values(tags = "train") - param_vals$affect_columns = NULL if (!length(cols)) { self$state = list(dt_columns = dt_columns, param_vals = param_vals) @@ -265,7 +251,6 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", } dt = task$data(cols = cols) - self$state$param_vals = param_vals self$state$dt_columns = dt_columns @@ -288,6 +273,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", }, .transform = function(dt, task, param_vals, stage) { # stage is "train" or "predict" + param_vals$affect_columns = NULL trafo = private$.fn if (stage == "train") { @@ -349,10 +335,9 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", return(dt) }, .additional_phash_input = function() { - list(self$param_set$ids(), private$.fn, self$packages, private$.per_column) + list(self$param_set$ids(), private$.fn, self$packages) }, - .fn = NULL, - .per_column = NULL + .fn = NULL ) ) @@ -363,15 +348,14 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' @param param_vals (`list()`)\cr #' The parameter values. #' @export -pipeop_preproc_torch = function(id, fn, shapes_out = NULL, param_set = NULL, param_vals = list(), - packages = character(0), per_column = TRUE) { +pipeop_preproc_torch = function(id, fn, shapes_out, param_set = NULL, param_vals = list(), + packages = character(0)) { pipeop_preproc_torch_class( id = id, fn = fn, shapes_out = shapes_out, param_set = param_set, - packages = packages, - per_column = per_column + packages = packages )$new(param_vals = param_vals) } @@ -409,7 +393,7 @@ create_ps_call = function(fn) { #' @template param_id #' @param fn (`function`)\cr #' The preprocessing function. -#' @param shapes_out (`function` or `NULL` or `TRUE`)\cr +#' @param shapes_out (`function` or `NULL` or "infer")\cr #' The private `.shapes_out(shapes_in, param_vals, task)` method of [`PipeOpTaskPreprocTorch`]. #' If `NULL`, the pipeop does not change the output shapes. #' If `TRUE`, the output shape function is inferred and calculates the output shapes as follows: @@ -426,23 +410,19 @@ create_ps_call = function(fn) { #' Default values are not annotated. #' @template param_param_vals #' @template param_packages -#' @param per_column (`logical(1)`)\cr -#' Whether the preprocessing is applied per-column. #' @export #' @returns An [`R6Class`][R6::R6Class] instance inheriting from [`PipeOpTaskPreprocTorch`] #' @examples #' po_example = pipeop_preproc_torch("preproc_example", function(x, a) x + a) #' po_example #' po_example$param_set -pipeop_preproc_torch_class = function(id, fn, shapes_out = NULL, param_set = NULL, - packages = character(0), per_column = TRUE) { - assert_string(id) +pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, packages = character(0)) { assert_function(fn) - if (!isTRUE(shapes_out)) { - assert_function(shapes_out, args = c("shapes_in", "param_vals", "task"), null.ok = TRUE) - } - assert_character(packages) - assert_flag(per_column) + assert_true(length(formals(fn)) >= 1L) + assert( + check_function(shapes_out, args = c("shapes_in", "param_vals", "task"), null.ok = TRUE), + check_choice(shapes_out, "infer") + ) if (!is.null(param_set)) { assert_param_set(eval(param_set)) @@ -454,7 +434,7 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out = NULL, param_set = NUL classname = paste0("PipeOpPreprocTorch", paste0(capitalize(strsplit(id, split = "_")[[1L]]), collapse = "")) # Note that we don't set default values - if (isTRUE(shapes_out)) { + if (identical(shapes_out, "infer")) { shapes_out = crate(function(shapes_in, param_vals, task) { sin = shapes_in[[1L]] if (all(is.na(sin))) { @@ -462,17 +442,17 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out = NULL, param_set = NUL return(list(sin)) } # set batch-dim to 1 + sin[1] = 1L tensor_in = invoke(torch_empty, .args = sin, device = torch_device("meta")) tensor_out = invoke(private$.fn, tensor_in, .args = param_vals) - sout = dim(tensor_out) - if (sout[1] != 1) { - stopf("The automatically inferred private .shapes_out() method for class '%s' is wrong.", classname) - } + sout[1] = NA list(sout) }) + } else { + assert_function(shapes_out, args = c("shapes_in", "param_vals", "task"), null.ok = TRUE) } init_fun = crate(function(id = idname, param_vals = list()) { diff --git a/R/PipeOpTorch.R b/R/PipeOpTorch.R index 6f9f4d76..df41e74c 100644 --- a/R/PipeOpTorch.R +++ b/R/PipeOpTorch.R @@ -320,7 +320,7 @@ PipeOpTorch = R6Class("PipeOpTorch", input_pointers = map(inputs, ".pointer") input_shapes = map(inputs, ".pointer_shape") - assert_shapes(input_shapes, named = FALSE) + assert_shapes(input_shapes, named = FALSE, null_ok = FALSE) # Now begin creating the result-object: it contains a merged version of all `inputs`' $graph slots etc. # The only thing missing afterwards is (1) integrating module_op to the merged $graph, and adding `.pointer`s. result_template = Reduce(model_descriptor_union, inputs) diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index 1f5911fd..b2265f85 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -352,7 +352,7 @@ register_po("torch_ingress_img", PipeOpTorchIngressImage) #' .length = function() 2)() #' #' task_unknown = as_task_regr(data.table( -#' x = as_lazy_tensor(ds, dataset_shapes = list(x = c(NA, NA, NA, NA))), +#' x = as_lazy_tensor(ds, dataset_shapes = list(x = NULL)), #' y = rnorm(2) #' ), target = "y", id = "example2") #' @@ -396,15 +396,13 @@ PipeOpTorchIngressLazyTensor = R6Class("PipeOpTorchIngressLazyTensor", if (length(lazy_cols) != 1L) { stopf("PipeOpTorchIngressLazyTensor expects 1 'lazy_tensor' feature, but got %i.", length(lazy_cols)) } - example = task$data(task$row_ids[1L], lazy_cols)[[1L]][[1L]] + example = task$data(task$row_ids[1L], lazy_cols)[[1L]] input_shape = example$.pointer_shape pv_shape = param_vals$shape - if (all(is.na(input_shape))) { - pv_shape = assert_shape(pv_shape, null_ok = FALSE) - if (length(input_shape) != length(pv_shape)) { - stopf("Number of dimensions of lazy_tensor column '%s' does not match those of parameter 'shape' set in PipeOp '%s'.", # nolint - lazy_cols, self$id) + if (is.null(input_shape)) { + if (is.null(pv_shape)) { + stopf("If input shape is unknown, the 'shape' parameter must be set.") } return(pv_shape) } diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index d10ee1a8..b62bb897 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -66,8 +66,8 @@ DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NU .pointer_shape = NULL, clone_graph = TRUE, .info = list()) { assert_class(dataset, "dataset") - # If the dataest implements a .getbatch() method the shaoe must be specified. - assert_shapes(dataset_shapes, unknown_ok = is.null(dataset$.getbatch)) + # If the dataset implements a .getbatch() method the shape must be specified. + assert_shapes(dataset_shapes, null_ok = is.null(dataset$.getbatch)) if (is.null(graph)) { if ((length(dataset_shapes) == 1L) && is.null(.input_map)) { @@ -93,19 +93,13 @@ DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NU assert_choice(.pointer[[1]], names(graph$pipeops)) assert_choice(.pointer[[2]], graph$pipeops[[.pointer[[1]]]]$output$name) assert_subset(paste0(.pointer, collapse = "."), graph$output$name) - assert_shape(.pointer_shape, unknown_ok = TRUE) + assert_shape(.pointer_shape, null_ok = TRUE) assert_subset(.input_map, names(dataset_shapes)) assert_true(length(.input_map) == length(graph$input$name)) } - # We get a warning that package:mlr3torch may not be available when loading (?) - # for some reason, the hash of the dataset changes - #dataset_hash = calculate_hash(dataset, dataset_shapes) - dataset$.length() - dataset_hash = calculate_hash(dataset, dataset_shapes"") - # what we could do: - # 1) set the hah as field .__mlr3torch__dataset_hash in the dataset (and check before whether something like this is already set) + dataset_hash = calculate_hash(address(dataset)) obj = structure( list( @@ -167,19 +161,24 @@ lazy_tensor = function(data_descriptor = NULL, ids = NULL) { } new_lazy_tensor = function(data_descriptor, ids) { - hash = data_descriptor$.hash # previously, only the id was included and not the hash # this led to issues with stuff like unlist(), which dropped attribute and suddenly the lazy_tensor column # was a simple integer vector. (this caused stuff like PipeOpFeatureUnion to go havock and lead to bugs) # For this reason, we now also include the hash of the data_descriptor # We can then later also use this to support different DataDescriptors in a single lazy tensor column - vctrs::new_vctr(map(ids, function(id) list(id, hash)), data_descriptor = data_descriptor, class = "lazy_tensor") + vctrs::new_vctr(map(ids, function(id) list(id, data_descriptor)), hash = data_descriptor$.hash, class = "lazy_tensor") } #' @export format.lazy_tensor = function(x, ...) { # nolint if (!length(x)) return(character(0)) - shape = paste0(attr(x, "data_descriptor")$.pointer_shape[-1L], collapse = "x") + shape = x$data_descriptor + shape = if (is.null(shape)) { + "?" + } else { + shape = paste0(x$data_descriptor$.pointer_shape[-1L], collapse = "x") + } + map_chr(x, function(elt) { sprintf("", shape) }) @@ -239,15 +238,6 @@ vec_ptype_abbr.lazy_tensor <- function(x, ...) { # nolint "ltnsr" } -#' @export -`[.lazy_tensor` = function(x, i, ...) { # nolint - x = NextMethod() - if (length(x) == 0L) { - attr(x, "data_descriptor") = NULL - } - return(x) -} - #' @title Check for lazy tensor #' @description #' Checks whether an object is a lazy tensor. @@ -301,11 +291,11 @@ transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { assert_class(pipeop, "PipeOpModule") assert_true(nrow(pipeop$input) == 1L) assert_true(nrow(pipeop$output) == 1L) - assert_shape(shape, unknown_ok = TRUE) + assert_shape(shape, null_ok = TRUE) # shape_predict can be NULL if we transform a tensor during `$predict()` in PipeOpTaskPreprocTorch - assert_shape(shape_predict, null_ok = TRUE, unknown_ok = TRUE) + assert_shape(shape_predict, null_ok = TRUE) - data_descriptor = attr(lt, "data_descriptor") + data_descriptor = lt$data_descriptor data_descriptor$graph = data_descriptor$graph$clone(deep = FALSE) data_descriptor$graph$edges = copy(data_descriptor$graph$edges) @@ -328,13 +318,16 @@ transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { #' @export `$.lazy_tensor` = function(x, name) { + if (!length(x)) { + stop("lazy tensor has length 0.") + } + dd = x[[1L]][[2L]] if (name == "data_descriptor") { - return(attr(x, "data_descriptor")) + return(dd) } - x = attr(x, "data_descriptor")[[name]] - if (is.null(x)) { + if (!(name %in% names(dd))) { stopf("Unknown field '%s'.", name) } - return(x) + dd[[name]] } diff --git a/R/materialize.R b/R/materialize.R index fa4d1ec3..381d1934 100644 --- a/R/materialize.R +++ b/R/materialize.R @@ -81,7 +81,6 @@ materialize.list = function(x, device = "cpu", rbind = FALSE, cache = "auto") { map(x, function(col) { if (is_lazy_tensor(col)) { - browser() materialize_internal(col, device = device, cache = cache, set_keep_results = FALSE, rbind = rbind) } else { col diff --git a/R/preprocess.R b/R/preprocess.R index 36ec92c9..4a200a02 100644 --- a/R/preprocess.R +++ b/R/preprocess.R @@ -9,11 +9,6 @@ #' @include PipeOpTaskPreprocTorch.R NULL -table_preproc = function() { - keys = names(mlr3torch_pipeops) - keys = keys[grepl("^preproc_(?!torch).*", keys, perl = TRUE)] - paste0("* ", keys) -} #' @name PipeOpPreprocTorchTrafoResize #' @rdname mlr_pipeops_preproc_torch_overview @@ -42,7 +37,7 @@ register_preproc("trafo_resize", torchvision::transform_resize, #' @rdname mlr_pipeops_preproc_torch_overview #' @description #' * `trafo_nop`: Calls `identity()`. -register_preproc("trafo_nop", identity) +register_preproc("trafo_nop", identity, shapes_out = NULL) diff --git a/R/shape.R b/R/shape.R new file mode 100644 index 00000000..be2bc6f1 --- /dev/null +++ b/R/shape.R @@ -0,0 +1,46 @@ +#' Check Shape +#' +#' Checks whether an integer vector is a valid shape. +#' Unknown shapes are represted as `NULL`. +#' +#' @param shape (`integer()`)\cr +#' @param null_ok (`logical(1)`)\cr +#' Whether `NULL` is a valid shape. +assert_shape = function(shape, null_ok = FALSE) { + if (!test_shape(shape, null_ok = null_ok)) { + stopf("Invalid shape.") + } + if (is.null(shape)) { + return(NULL) + } + return(as.integer(shape)) +} + +test_shape = function(shape, null_ok = FALSE) { + if (is.null(shape) && null_ok) { + return(TRUE) + } + ok = test_integerish(shape, min.len = 2L, all.missing = TRUE) + + if (!ok) { + return(FALSE) + } + + is_na = is.na(shape) + if (!is_na[[1L]] || anyNA(shape[-1L])) { + return(FALSE) + } + return(TRUE) +} + +check_shape = function(x, null_ok = FALSE) { + if (test_shape(x, null_ok = null_ok)) { + return(TRUE) + } + "Must be a valid shape." +} + +assert_shapes = function(shapes, named = TRUE, null_ok = FALSE) { # nolint + assert_list(shapes, names = if (named && !identical(unique(names(shapes)), "...")) "unique", min.len = 1L) + map(shapes, assert_shape, null_ok = null_ok) +} diff --git a/R/task_dataset.R b/R/task_dataset.R index 45461a46..4ae50aab 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -57,7 +57,8 @@ task_dataset = dataset( stopf("Not working yet I think") # TODO: Inspect hashes of data descriptors to check whether caching is possible first_row = self$task$data(self$task$row_ids[1L], cols = lazy_tensor_features) - graphs = map(first_row, function(x) attr(x, "data_descriptor")$graph) + # attr no longer exists + # graphs = map(first_row, function(x) attr(x, "data_descriptor")$graph) graphs = graphs[!duplicated(graphs)] graphs[[1L]] = graphs[[1L]]$clone(deep = TRUE) merged_graph = try(Reduce(function(x, y) merge_graphs(x, y, in_place = TRUE), graphs), silent = TRUE) @@ -65,7 +66,8 @@ task_dataset = dataset( if (!inherits(merged_graph, "try-error")) { data = self$task$data(cols = lazy_tensor_features) data = map_dtc(data, function(x) { - attr(x, "data_descriptor")$graph = merged_graph + #attr(x, "data_descriptor")$graph = merged_graph + # attr no longer exists x }) task$cbind(data) diff --git a/R/utils.R b/R/utils.R index 81837d60..d6a4a613 100644 --- a/R/utils.R +++ b/R/utils.R @@ -169,58 +169,6 @@ argument_matcher = function(args) { fn } -#' Check Shape -#' -#' Checks whether an integer vector is a valid shape. -#' -#' @param shape (`integer()`)\cr -#' @param null_ok (`logical(1)`) -#' @param unknown_ok (`logical(1)`) -assert_shape = function(shape, null_ok = FALSE, unknown_ok = FALSE) { # nolint - if (!test_shape(shape, null_ok = null_ok, unknown_ok = unknown_ok)) { - stopf("Invalid shape.") - } - if (is.null(shape)) { - return(NULL) - } - return(as.integer(shape)) -} - -test_shape = function(shape, null_ok = FALSE, unknown_ok = FALSE) { - if (is.null(shape) && null_ok) { - return(TRUE) - } - ok = test_integerish(shape, min.len = 2L, all.missing = TRUE) - - if (!ok) { - return(FALSE) - } - - is_na = is.na(shape) - all_na = all(is_na) - - if (all_na && unknown_ok) { - return(TRUE) - } - if (!is_na[[1L]] || anyNA(shape[-1L])) { - return(FALSE) - } - return(TRUE) -} - -check_shape = function(x, null_ok = FALSE, unknown_ok = FALSE) { - if (test_shape(x, null_ok = null_ok, unknown_ok = unknown_ok)) { - return(TRUE) - } - "Must be a valid shape." -} - -assert_shapes = function(shapes, named = TRUE, unknown_ok = FALSE) { # nolint - # - assert_list(shapes, names = if (named && !identical(unique(names(shapes)), "...")) "unique", min.len = 1L) - map(shapes, assert_shape, unknown_ok = unknown_ok, null_ok = FALSE) -} - assert_lazy_tensor = function(x) { assert_class(x, "lazy_tensor") } diff --git a/R/zzz.R b/R/zzz.R index ffca8d18..75be0637 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -140,14 +140,21 @@ register_mlr3pipelines = function() { # # Because this is quite annoying, we here suppress warnings that arise from the calculate_hash function. - fn = force(mlr3misc::calculate_hash) - calculate_hash = mlr3misc::crate(function(...) { - suppressWarnings(fn(...)) - }, .parent = getNamespace("mlr3misc"), fn) - - unlockBinding("calculate_hash", parent.env(getNamespace("mlr3torch"))) - assign("calculate_hash", calculate_hash, envir = parent.env(getNamespace("mlr3torch"))) - lockBinding("calculate_hash", parent.env(getNamespace("mlr3torch"))) + suppress = function(name, fn, env) { + fn = mlr3misc::crate(function(...) { + suppressWarnings(fn(...)) + }, .parent = parent.env(environment(fn)), fn) + + unlockBinding(name, env) + assign(name, fn, envir = env) + lockBinding(name, env) + } + + suppress("calculate_hash", mlr3misc::calculate_hash, parent.env(getNamespace("mlr3torch"))) + + suppress("calculate_hash", mlr3misc::calculate_hash, parent.env(getNamespace("mlr3"))) + suppress("calculate_hash", mlr3misc::calculate_hash, parent.env(getNamespace("mlr3pipelines"))) + suppress("digest", digest::digest, parent.env(getNamespace("mlr3pipelines"))) } } diff --git a/man/assert_shape.Rd b/man/assert_shape.Rd index f6707069..915869ad 100644 --- a/man/assert_shape.Rd +++ b/man/assert_shape.Rd @@ -1,18 +1,18 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R +% Please edit documentation in R/shape.R \name{assert_shape} \alias{assert_shape} \title{Check Shape} \usage{ -assert_shape(shape, null_ok = FALSE, unknown_ok = FALSE) +assert_shape(shape, null_ok = FALSE) } \arguments{ \item{shape}{(\code{integer()})\cr} -\item{null_ok}{(\code{logical(1)})} - -\item{unknown_ok}{(\code{logical(1)})} +\item{null_ok}{(\code{logical(1)})\cr +Whether \code{NULL} is a valid shape.} } \description{ Checks whether an integer vector is a valid shape. +Unknown shapes are represted as \code{NULL}. } diff --git a/man/mlr_pipeops_preproc_torch.Rd b/man/mlr_pipeops_preproc_torch.Rd index 51ffed46..0255b33f 100644 --- a/man/mlr_pipeops_preproc_torch.Rd +++ b/man/mlr_pipeops_preproc_torch.Rd @@ -24,13 +24,13 @@ In addition to specifying the construction arguments, you can overwrite the priv (\code{list()}, \verb{list(), }Task\code{or}NULL\verb{) -> }list()`\cr This private method calculates the output shapes of the lazy tensor columns that are created from applying the preprocessing. -Note that the input shapes can be only contain NAs (e.g. (NA, NA, NA)), indicating that only the number of input -dimensions is known, but not the exact shape. -In this case the output shape should also only contain NAs. -In case the construction argument \code{per_column} is \code{TRUE}, this private method only has the responsibility -to calculate the output shapes for one input column, i.e. the input \code{shapes_in} can be assumed to have +This private method only has the responsibility to calculate the output shapes for one input column, i.e. the +input \code{shapes_in} can be assumed to have exactly one shape vector for which it must calculate the output shapes and return it as a \code{list()} of length 1. +It can also be assumed, that the shape is not \code{NULL}. +It should also output a shape with exactly one NA in the first dimension. +It is also possible to output \code{NULL}, if the output shape cannot be determined (e.g. because it is random). Also see the documentation of \code{\link{PipeOpTorch}} how to implement this method. \item \code{.transform(dt, task, param_vals, stage)}\cr @@ -40,7 +40,7 @@ It receives as inputs all selected lazy tensor columns, the input \code{Task} (a the paramer values, and whether the preprocessing is applied during training (stage is \code{"train"}) or prediction (stage is \code{"predict"}). One should not work with the parameters currently set in the paramet set, only use those passed as argument \code{param_vals}. These are the parameters that were specified during the \verb{$train()} -call of the \code{\link{PipeOp}} (otherwise it cannot be ensured that the shapes encountered during \verb{$predict()} can actually +call of the \code{\link{PipeOp}} (otherwise it cannot be ensured that the shapes encountered during \verb{$predict()} can actuallT be processed by the neural network). The method must return a \code{data.table} with lazy tensor columns. The lazy tensor input columns should \strong{not} be modified in-place. @@ -56,7 +56,7 @@ See \code{\link{PipeOpTaskPreproc}}. \section{State}{ -See \code{\link{PipeOpTaskPreproc}}. +TODO: } \section{Parameters}{ @@ -73,17 +73,11 @@ This parameter is initialized to \code{FALSE}. \section{Internals}{ -If \code{per_column} is \code{TRUE}: - A \code{\link{PipeOpModule}} with one input and one output channel is created. The pipeop simply applies the function \code{fn} to the input tensor while additionally passing the paramter values (minus \code{augment} and \code{affect_columns}) to \code{fn}. Then \code{\link{transform_lazy_tensor}} is called with the created \code{\link{PipeOpModule}} and the shapes obtained from the \verb{$shapes_out()} method of this \code{PipeOp}. - -If \code{per_column} is \code{FALSE}: -It is the obligation of the user to overwrite the \code{.transform()} method appropriately. -Note that on } \examples{ @@ -206,7 +200,6 @@ Creates a new instance of this \code{\link[R6:R6Class]{R6}} class. param_vals = list(), param_set = ps(), packages = character(0), - per_column = TRUE, augment_init = FALSE )}\if{html}{\out{
}} } @@ -233,13 +226,9 @@ during prediction (if \code{augment} is set to \code{FALSE}).} \item{\code{packages}}{(\code{character()})\cr The packages the preprocessing function depends on.} -\item{\code{per_column}}{(\code{logical(1)})\cr -Whether the transformation is applied per column. -If this is \code{FALSE}, is applied to all lazy tensor columns at once and might produce -one or more new lazy tensor columns.} - -\item{\code{augment_init}}{(\code{logical(1)})\cr -Initial value for the \code{augment} parameter.} +\item{\code{augment_init}}{(\code{logical(1)} or \code{NULL})\cr +Initial value for the \code{augment} parameter. +If it is \code{NULL}, there is no \code{augment} parameter.} } \if{html}{\out{
}} } @@ -251,6 +240,7 @@ Initial value for the \code{augment} parameter.} Calculates the output shapes that would result in applying the preprocessing to one or more lazy tensor columns with the provided shape. Names are ignored and only order matters. +It uses the parameeter values that are currently set. \subsection{Usage}{ \if{html}{\out{
}}\preformatted{PipeOpTaskPreprocTorch$shapes_out(shapes_in, stage = NULL, task = NULL)}\if{html}{\out{
}} } @@ -258,8 +248,9 @@ Names are ignored and only order matters. \subsection{Arguments}{ \if{html}{\out{
}} \describe{ -\item{\code{shapes_in}}{(\code{list()} of \code{integer()})\cr -The input input shapes of the lazy tensors.} +\item{\code{shapes_in}}{(\code{list()} of (\code{integer()} or \code{NULL}))\cr +The input input shapes of the lazy tensors. +\code{NULL} indicates that the shape is unknown.} \item{\code{stage}}{(\code{character(1)})\cr The stage: either \code{"train"} or \code{"predict"}.} @@ -270,7 +261,7 @@ The task, which is very rarely needed.} \if{html}{\out{
}} } \subsection{Returns}{ -\code{list()} of \code{integer()} +\code{list()} of (\code{integer()} or \code{NULL}) } } \if{html}{\out{
}} diff --git a/man/mlr_pipeops_torch_ingress_ltnsr.Rd b/man/mlr_pipeops_torch_ingress_ltnsr.Rd index 7d4926d4..a4863be4 100644 --- a/man/mlr_pipeops_torch_ingress_ltnsr.Rd +++ b/man/mlr_pipeops_torch_ingress_ltnsr.Rd @@ -51,7 +51,7 @@ ds = dataset( .length = function() 2)() task_unknown = as_task_regr(data.table( - x = as_lazy_tensor(ds, dataset_shapes = list(x = c(NA, NA, NA, NA))), + x = as_lazy_tensor(ds, dataset_shapes = list(x = NULL)), y = rnorm(2) ), target = "y", id = "example2") diff --git a/man/pipeop_preproc_torch.Rd b/man/pipeop_preproc_torch.Rd index d9a2259e..a0291eb0 100644 --- a/man/pipeop_preproc_torch.Rd +++ b/man/pipeop_preproc_torch.Rd @@ -7,11 +7,10 @@ pipeop_preproc_torch( id, fn, - shapes_out = NULL, + shapes_out, param_set = NULL, param_vals = list(), - packages = character(0), - per_column = TRUE + packages = character(0) ) } \arguments{ @@ -21,7 +20,7 @@ The id for of the new object.} \item{fn}{(\code{function})\cr The preprocessing function.} -\item{shapes_out}{(\code{function} or \code{NULL} or \code{TRUE})\cr +\item{shapes_out}{(\code{function} or \code{NULL} or "infer")\cr The private \code{.shapes_out(shapes_in, param_vals, task)} method of \code{\link{PipeOpTaskPreprocTorch}}. If \code{NULL}, the pipeop does not change the output shapes. If \code{TRUE}, the output shape function is inferred and calculates the output shapes as follows: @@ -43,9 +42,6 @@ The parameter values.} \item{packages}{(\code{character()})\cr The R packages this object depends on.} - -\item{per_column}{(\code{logical(1)})\cr -Whether the preprocessing is applied per-column.} } \description{ Calls \code{\link{pipeop_preproc_torch_class}} and instantiates the instance with the given parameter values. diff --git a/man/pipeop_preproc_torch_class.Rd b/man/pipeop_preproc_torch_class.Rd index d9986e19..da125330 100644 --- a/man/pipeop_preproc_torch_class.Rd +++ b/man/pipeop_preproc_torch_class.Rd @@ -7,10 +7,9 @@ pipeop_preproc_torch_class( id, fn, - shapes_out = NULL, + shapes_out, param_set = NULL, - packages = character(0), - per_column = TRUE + packages = character(0) ) } \arguments{ @@ -20,7 +19,7 @@ The id for of the new object.} \item{fn}{(\code{function})\cr The preprocessing function.} -\item{shapes_out}{(\code{function} or \code{NULL} or \code{TRUE})\cr +\item{shapes_out}{(\code{function} or \code{NULL} or "infer")\cr The private \code{.shapes_out(shapes_in, param_vals, task)} method of \code{\link{PipeOpTaskPreprocTorch}}. If \code{NULL}, the pipeop does not change the output shapes. If \code{TRUE}, the output shape function is inferred and calculates the output shapes as follows: @@ -40,9 +39,6 @@ Default values are not annotated.} \item{packages}{(\code{character()})\cr The R packages this object depends on.} -\item{per_column}{(\code{logical(1)})\cr -Whether the preprocessing is applied per-column.} - \item{param_vals}{(named \code{list()})\cr Parameter values to be set after construction.} } diff --git a/tests/testthat/helper_tasks.R b/tests/testthat/helper_tasks.R index d8e2b75c..270055b7 100644 --- a/tests/testthat/helper_tasks.R +++ b/tests/testthat/helper_tasks.R @@ -17,7 +17,7 @@ nano_dogs_vs_cats = function(id = "nano_dogs_vs_cats") { )(uris) - images = as_lazy_tensor(ds, dataset_shapes = list(x = rep(NA_integer_, 4))) + images = as_lazy_tensor(ds, dataset_shapes = list(x = NULL)) labels = map_chr(image_names, function(name) { if (startsWith(name, "cat")) { diff --git a/tests/testthat/test_PipeOpTaskPreprocTorch.R b/tests/testthat/test_PipeOpTaskPreprocTorch.R index cb8c7547..e560f831 100644 --- a/tests/testthat/test_PipeOpTaskPreprocTorch.R +++ b/tests/testthat/test_PipeOpTaskPreprocTorch.R @@ -31,7 +31,8 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { shapes_in = list(c(NA, 1), c(NA, 1)) expect_identical(shapes_in, po_test1$shapes_out(shapes_in, stage = "train")) - expect_identical(shapes_in, po_test1$shapes_out(shapes_in, stage = "predict")) + expect_error(po_test1$shapes_out(shapes_in, stage = "predict"), "can only be calculated") + shapes_in1 = list(a = c(NA, 1), b = c(NA, 1)) expect_true(is.null(names(po_test1$shapes_out(shapes_in1, "train")))) @@ -97,6 +98,26 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { ) }) +test_that("PipeOptaskPreprocTorch: shapes_out() works", { + task = nano_dogs_vs_cats() + po_resize = po("trafo_resize", size = c(10, 10)) + expect_identical(po_resize$shapes_out(list(x = NULL), stage = "train"), list(NULL)) + expect_identical(po_resize$shapes_out(list(x = NULL, y = c(NA, 3, 5, 5)), stage = "train"), list(NULL, c(NA, 3, 10, 10))) + expect_error(po_resize$shapes_out(list(x = c(NA, 1, 3)), stage = "predict"), "can only be calculated") + + # predict when augment is TRUE + po_resize$param_set$set_values(augment = TRUE) + po_resize$train(list(task)) + expect_identical(po_resize$shapes_out(list(x = NULL), stage = "predict"), list(NULL)) + expect_identical(po_resize$shapes_out(list(x = NULL, y = c(NA, 3, 5, 5)), stage = "predict"), list(NULL, c(NA, 3, 5, 5))) + + # predict when augment is FALSE + po_resize$param_set$set_values(augment = FALSE) + po_resize$train(list(task)) + expect_identical(po_resize$shapes_out(list(x = NULL), stage = "predict"), list(NULL)) + expect_identical(po_resize$shapes_out(list(x = NULL, y = c(NA, 3, 5, 5)), stage = "predict"), list(NULL, c(NA, 3, 10, 10))) +}) + test_that("PipeOpTaskPreprocTorch modifies the underlying lazy tensor columns correctly", { d = data.table( y = 1:10, @@ -166,7 +187,7 @@ test_that("pipeop_preproc_torch works", { expect_torch_equal(x[1, 1]$item(), 3) expect_torch_equal(x[1, 2]$item(), 1) - po_test1 = pipeop_preproc_torch("test1", torchvision::transform_resize, shapes_out = TRUE, + po_test1 = pipeop_preproc_torch("test1", torchvision::transform_resize, shapes_out = "infer", param_vals = list(size = c(10, 10)) ) @@ -175,7 +196,7 @@ test_that("pipeop_preproc_torch works", { }) test_that("predict shapes are added during training", { - po_test = pipeop_preproc_torch("test", function(x) torch_cat(list(x, x * 2), dim = 2)) + po_test = pipeop_preproc_torch("test", function(x) torch_cat(list(x, x * 2), dim = 2), shapes_out = "infer") task = as_task_regr(data.table( y = 1, x = as_lazy_tensor(1) diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index 6e911c13..96491384 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -47,17 +47,17 @@ test_that("Unknown shapes work", { } )() - dd = DataDescriptor(ds, dataset_shapes = list(x = c(NA, NA, NA))) + dd = DataDescriptor(ds, dataset_shapes = list(x = NULL)) expect_class(dd, "DataDescriptor") - expect_equal(dd$.pointer_shape, c(NA, NA, NA)) - expect_equal(dd$dataset_shapes, list(x = c(NA, NA, NA))) + expect_equal(dd$.pointer_shape, NULL) + expect_equal(dd$dataset_shapes, list(x = NULL)) lt = as_lazy_tensor(dd) expect_class(lt, "lazy_tensor") materialize(lt) ds = random_dataset(10, 3) - expect_error(DataDescriptor(ds, list(x = c(NA, NA, NA)))) + expect_error(DataDescriptor(ds, list(x = NULL))) }) test_that("lazy_tensor works", { @@ -67,7 +67,7 @@ test_that("lazy_tensor works", { lt = lazy_tensor() expect_class(lt, "lazy_tensor") expect_true(length(lt) == 0L) - expect_true(is.null(attr(lt, "data_descriptor"))) + expect_error(is.null(lt$data_descriptor)) lt1 = lazy_tensor(dd1) lt2 = lazy_tensor(dd2) @@ -75,7 +75,7 @@ test_that("lazy_tensor works", { expect_error(c(lt1, lt2), "attributes are incompatible") lt1_empty = lt1[integer(0)] - expect_true(is.null(attr(lt1_empty, "data_descriptor"))) + expect_error(is.null(lt1_empty$data_descriptor)) expect_class(lt1_empty, "lazy_tensor") expect_error(materialize(lazy_tensor()), "Cannot materialize") @@ -98,13 +98,13 @@ test_that("transform_lazy_tensor works", { lt1 = transform_lazy_tensor(lt, po_module, new_shape) - dd1 = attr(lt1, "data_descriptor") + dd1 = lt1$data_descriptor expect_equal(dd1$graph$edges, data.table(src_id = "dataset_x", src_channel = "output", dst_id = "mod", dst_channel = "input") ) - dd = attr(lt, "data_descriptor") + dd = lt$data_descriptor # graph was cloned expect_true(!identical(dd1$graph, dd$graph)) diff --git a/tests/testthat/test_materialize.R b/tests/testthat/test_materialize.R index 6535a3b3..973c0950 100644 --- a/tests/testthat/test_materialize.R +++ b/tests/testthat/test_materialize.R @@ -129,7 +129,7 @@ test_that("materialize_internal: caching of datasets works", { self$count = 0 }, .getitem = function(i) { - #self$count = self$count + 1 + self$count = self$count + 1 list(x = self$x[i, ]) }, .length = function() { @@ -154,10 +154,8 @@ test_that("materialize_internal: caching of datasets works", { d = data.table(x1 = x1, x2 = x2) - debugonce(materialize) materialize(d, rbind = TRUE, cache = new.env()) - expect_true(d$count == 10) - + expect_true(ds$count == 10) }) test_that("materialize_internal: resets everything to previous state", { diff --git a/tests/testthat/test_utils.R b/tests/testthat/test_utils.R index a23a1d89..43b38c13 100644 --- a/tests/testthat/test_utils.R +++ b/tests/testthat/test_utils.R @@ -27,30 +27,6 @@ test_that("get_nout works", { expect_equal(get_nout(tsk("mtcars")), 1) }) -test_that("assert_shape works", { - expect_true(is.null(assert_shape(NULL, null_ok = TRUE))) - expect_error(assert_shape(NULL, null_ok = FALSE)) - - # valid examples - expect_integer(assert_shape(c(NA, 1))) - expect_integer(assert_shape(c(NA, 1, 2))) - expect_integer(assert_shape(c(NA, NA), unknown_ok = TRUE)) - - # at least 2 dims - expect_error(assert_shape(NA)) - # one NA in batch dim - expect_error(assert_shape(c(1, NA))) - expect_error(assert_shape(c(NA, NA, unknown_ok = FALSE))) -}) - -test_that("assert_shapes works", { - expect_list(assert_shapes(list(c(NA, 1, 2), c(NA, 1)), named = FALSE)) - expect_error(assert_shapes(list(c(NA, 1, 2), c(NA, 1)), named = TRUE)) - - expect_list(assert_shapes(list(a = c(NA, 1, 2), b = c(NA, 1)), named = TRUE)) - expect_error(assert_shapes(list(a = NULL, b = c(NA, 1)), named = TRUE)) -}) - test_that("uniqueify works", { expect_equal(uniqueify("a", "a"), "a_1") }) From 4c6d5a66a2da5704e0c5393dbb9e9e2cfcb02af0 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 8 Nov 2023 16:39:23 +0100 Subject: [PATCH 13/90] more fixes --- R/DataBackendLazy.R | 5 +- R/LearnerTorch.R | 16 +++-- R/PipeOpModule.R | 66 ++++++++++++++------- R/PipeOpTaskPreprocTorch.R | 44 ++++---------- R/PipeOpTorch.R | 11 +--- R/TaskClassif_lazy_iris.R | 17 +++++- R/TaskClassif_mnist.R | 10 +++- R/TorchLoss.R | 2 +- R/TorchOptimizer.R | 4 +- R/lazy_tensor.R | 36 ++++++----- R/materialize.R | 1 + man-roxygen/task_download.R | 5 ++ man/DataDescriptor.Rd | 9 ++- man/TorchOptimizer.Rd | 6 +- man/materialize.Rd | 7 +++ man/mlr_backends_lazy.Rd | 5 +- man/mlr_learners_torch.Rd | 4 +- man/mlr_pipeops_module.Rd | 38 +++++++----- man/mlr_pipeops_torch.Rd | 3 - man/mlr_tasks_lazy_iris.Rd | 34 +++++++++-- man/mlr_tasks_mnist.Rd | 17 +++++- tests/testthat/helper_autotest.R | 35 +++++------ tests/testthat/helper_functions.R | 5 +- tests/testthat/test_LearnerTorch.R | 48 ++++++++++++++- tests/testthat/test_PipeOpModule.R | 39 ++++++++++++ tests/testthat/test_PipeOpTorch.R | 3 +- tests/testthat/test_TaskClassif_lazy_iris.R | 3 + tests/testthat/test_TaskClassif_mnist.R | 6 ++ 28 files changed, 337 insertions(+), 142 deletions(-) create mode 100644 man-roxygen/task_download.R create mode 100644 tests/testthat/test_TaskClassif_lazy_iris.R create mode 100644 tests/testthat/test_TaskClassif_mnist.R diff --git a/R/DataBackendLazy.R b/R/DataBackendLazy.R index 9612e564..ab1495cb 100644 --- a/R/DataBackendLazy.R +++ b/R/DataBackendLazy.R @@ -21,7 +21,10 @@ #' #' Beware that accessing the backend's hash also contructs the backend. #' -#' @param constructor (`function()`)\cr +#' Note that while in most cases the data contains [`lazy_tensor`] columns, this is not necessary and the naming +#' of backend has nothing to do with the [`lazy_tensor`] datatype. +#' +#' @param constructor (`function`)\cr #' A function with no arguments, whose return value must be the actual backend. #' This function is called the first time the field `$backend` is accessed. #' @param rownames (`integer()`)\cr diff --git a/R/LearnerTorch.R b/R/LearnerTorch.R index 9db03387..18caa950 100644 --- a/R/LearnerTorch.R +++ b/R/LearnerTorch.R @@ -204,7 +204,7 @@ LearnerTorch = R6Class("LearnerTorch", #' @param task ([`Task`])\cr #' The task. #' @param row_ids (`integer()`)\cr - #' Which rows to use for trainin.g + #' Which rows to use for training. train = function(task, row_ids = NULL) { private$.verify_train_task(task, row_ids) super$train(task, row_ids) @@ -213,7 +213,7 @@ LearnerTorch = R6Class("LearnerTorch", #' @param task ([`Task`])\cr #' The task. #' @param row_ids (`integer()`)\cr - #' For which rows to predict. + #' The rows for which to make predictions. #' @return ([`Prediction`]) predict = function(task, row_ids = NULL) { private$.verify_predict_task(task, row_ids) @@ -310,13 +310,17 @@ LearnerTorch = R6Class("LearnerTorch", first_row = task$head(1) iwalk(first_row, function(x, nm) { if (!is_lazy_tensor(x)) return(NULL) - predict_shape = x$.info$.predict_shape + predict_shape = x$.pointer_shape_predict train_shape = x$.pointer_shape # If no information on hypothetical predict shape is available we continue training # This is e.g. the case when a completely un-preprocessed lazy tensor is used # Otherwise we expect the predict_shape to be equal to the train shape - if (!is.null(predict_shape) && !identical(predict_shape, train_shape)) { - stopf("Lazy tensor column '%s' would have a different shape during training and prediction.", nm) + if (is.null(train_shape) || is.null(predict_shape)) { + return(NULL) + } + if (!isTRUE(all.equal(train_shape, predict_shape))) { + stopf("Lazy tensor column '%s' would have a different shape during training (%s) and prediction (%s).", + nm, paste0(train_shape, collapse = "x"), paste0(predict_shape, collapse = "x")) } }) }, @@ -327,7 +331,7 @@ LearnerTorch = R6Class("LearnerTorch", if (!test_equal_col_info(ci_train, ci_predict)) { # nolint stopf(paste0( "Predict task's `$col_info` does not match the train task's column info.\n", - "This will be handled more gracefully in the future.\n", + "This migth be handled more gracefully in the future.\n", "Training column info:\n'%s'\n", "Prediction column info:\n'%s'"), paste0(capture.output(ci_train), collapse = "\n"), diff --git a/R/PipeOpModule.R b/R/PipeOpModule.R index 95054490..b11252c2 100644 --- a/R/PipeOpModule.R +++ b/R/PipeOpModule.R @@ -3,14 +3,13 @@ #' @name mlr_pipeops_module #' #' @description -#' `PipeOpModule` wraps an [`nn_module`] that is being called during the `train` phase of this [`mlr3pipelines::PipeOp`]. -#' By doing so, this allows to assemble `PipeOpModule`s in a computational [`mlr3pipelines::Graph`] that -#' represents a neural network architecture. Such a graph can also be used to create a [`nn_graph`] which inherits -#' from [`nn_module`]. +#' `PipeOpModule` wraps an [`nn_module`] or `function` that is being called during the `train` phase of this +#' [`mlr3pipelines::PipeOp`]. By doing so, this allows to assemble `PipeOpModule`s in a computational +#' [`mlr3pipelines::Graph`] that represents either a neural network or a preprocessing graph of a [`lazy_tensor`]. +#' In most cases it is easier to create such a network by creating a graph that generates this graph. #' -#' In most cases it is easier to create such a network by creating a isomorphic graph consisting -#' of nodes of class [`PipeOpTorchIngress`] and [`PipeOpTorch`]. This graph will then generate the graph consisting -#' of `PipeOpModule`s as part of the [`ModelDescriptor`]. +#' To construct a neural network one combines mostly [`PipeOpTorchIngress`] and [`PipeOpTorch`] operators. +#' To construct a preprocessing graph, one combines mostly `PipeOp`s inheriting from [`PipeOpTaskPreprocTorch`]. #' #' @section Input and Output Channels: #' The number and names of the input and output channels can be set during construction. They input and output @@ -22,8 +21,8 @@ #' No parameters. #' #' @section Internals: -#' During training, the wrapped [`nn_module`] is called with the provided inputs in the order in which the channels -#' are defined. Arguments are **not** matched by name. +#' During training, the wrapped [`nn_module`] / `function` is called with the provided inputs in the order in which +#' the channels are defined. Arguments are **not** matched by name. #' #' @family Graph Network #' @family PipeOp @@ -32,8 +31,9 @@ #' ## creating an PipeOpModule manually #' #' # one input and output channel -#' po_module = PipeOpModule$new("linear", -#' torch::nn_linear(10, 20), +#' po_module = po("module", +#' id = "linear", +#' module = torch::nn_linear(10, 20), #' inname = "input", #' outname = "output" #' ) @@ -54,9 +54,9 @@ #' ) #' #' module = nn_custom(3, 2) -#' po_module = PipeOpModule$new( -#' "custom", -#' module, +#' po_module = po("module", +#' id = "custom", +#' module = module, #' inname = c("x", "z"), #' outname = c("out1", "out2") #' ) @@ -65,7 +65,7 @@ #' out = po_module$train(list(x = x, z = z)) #' str(out) #' -#' # How a PipeOpModule is usually generated +#' # How such a PipeOpModule is usually generated #' graph = po("torch_ingress_num") %>>% po("nn_linear", out_features = 10L) #' result = graph$train(tsk("iris")) #' # The PipeOpTorchLinear generates a PipeOpModule and adds it to a new (module) graph @@ -74,6 +74,15 @@ #' linear_module #' formalArgs(linear_module$module) #' linear_module$input$name +#' +#' +# Constructing a PipeOpModule using a simple function +#' po_add1 = po("module", +#' id = "add_one", +#' module = function(x) x + 1 +#' ) +#' input = list(torch_tensor(1)) +#' po_add1$train(input)$output PipeOpModule = R6Class("PipeOpModule", inherit = PipeOp, public = list( @@ -97,8 +106,10 @@ PipeOpModule = R6Class("PipeOpModule", private$.multi_output = length(outname) > 1L self$module = assert(check_class(module, "nn_module"), check_class(module, "function"), combine = "or") self$module = module + assert_names(inname, type = "strict") assert_names(outname, type = "strict") assert_character(packages, any.missing = FALSE) + packages = union(c("mlr3torch", "torch"), packages) input = data.table(name = inname, train = "torch_tensor", predict = "NULL") output = data.table(name = outname, train = "torch_tensor", predict = "NULL") @@ -115,9 +126,6 @@ PipeOpModule = R6Class("PipeOpModule", private = list( .train = function(inputs) { self$state = list() # PipeOp API requires this. - # the inputs are passed in the order in which they appear in `graph$input` - # Note that PipeOpTorch ensures that (unless the forward method has a ... argument) the input channels are - # identical to the arguments of the forward method. outputs = do.call(self$module, unname(inputs)) outname = self$output$name if (!private$.multi_output) outputs = list(outputs) @@ -126,9 +134,27 @@ PipeOpModule = R6Class("PipeOpModule", .predict = function(inputs) { rep(list(NULL), nrow(self$output)) }, - .multi_output = FALSE, + .multi_output = NULL, .additional_phash_input = function() { - list(address(self$module), self$input$name, self$output$name, self$packages) + # mlr3pipelines does not use calculate_hash, but calls directly into digest, hence we have to take + # care of the byte code + fn_input = if (test_class(self$module, "nn_module")) { + address(self$module) + } else { + list(formals(self$module), body(self$module), address(environment(self$module))) + } + + list(fn_input, self$input$name, self$output$name, self$packages) + }, + deep_clone = function(name, value) { + if (name != "fn") { + return(super$deep_clone(name, value)) + } + if (test_class(value, "nn_module")) { + value$clone(deep = TRUE) + } else { + value + } } ) ) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index c8a4c234..045638f0 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -5,43 +5,24 @@ #' This `PipeOp` can be used to preprocess (one or more) [`lazy_tensor`] columns contained in an [`mlr3::Task`]. #' The preprocessing function is specified as construction argument `fn` and additional arguments to this #' function can be defined through the `PipeOp`'s parameter set. -#' The preprocessing is usually done per-column in which case the number lazy tensor output columns is equivalent +#' The preprocessing is done per-column, i.e. the number lazy tensor output columns is equivalent #' to the number of lazy tensor input columns. -#' It is also possible to implement preprocessing that is applied to all lazy tensor columns at once and returns -#' one or more (not necessarily the same number of) lazy tensor columns. -#' The preprocessing that is applied during `$predict()` uses the parameters that were set during `$train()` -#' and not those that are set when performing the prediction. +#' The preprocessing that is applied during `$predict()` uses the parameters that were set during `$train()` and not +#' those that are set when performing the prediction. #' #' @section Inheriting: -#' In addition to specifying the construction arguments, you can overwrite the private `.shapes_out()` or -#' `.tranform()` methods: +#' In addition to specifying the construction arguments, you can overwrite the private `.shapes_out()` method: #' * `.shapes_out(shapes_in, param_vals, task)`\cr #' (`list()`, `list(), `Task` or `NULL`) -> `list()`\cr #' This private method calculates the output shapes of the lazy tensor columns that are created from applying #' the preprocessing. #' #' This private method only has the responsibility to calculate the output shapes for one input column, i.e. the -#' input `shapes_in` can be assumed to have -#' exactly one shape vector for which it must calculate the output shapes and return it as a `list()` of length 1. -#' It can also be assumed, that the shape is not `NULL`. -#' It should also output a shape with exactly one NA in the first dimension. -#' It is also possible to output `NULL`, if the output shape cannot be determined (e.g. because it is random). -#' -#' Also see the documentation of [`PipeOpTorch`] how to implement this method. -#' -#' * `.transform(dt, task, param_vals, stage)`\cr -#' (`data.table()`, `Task`, `list()`, `character(1)`) -> `data.table()`\cr -#' This method must only be overwritten when the the `per_column` construction argument is `FALSE`. -#' It receives as inputs all selected lazy tensor columns, the input `Task` (already cloned), -#' the paramer values, and whether the preprocessing is applied during training (stage is `"train"`) -#' or prediction (stage is `"predict"`). One should not work with the parameters currently set in the paramet set, -#' only use those passed as argument `param_vals`. These are the parameters that were specified during the `$train()` -#' call of the [`PipeOp`] (otherwise it cannot be ensured that the shapes encountered during `$predict()` can actuallT -#' be processed by the neural network). -#' The method must return a `data.table` with lazy tensor columns. -#' The lazy tensor input columns should **not** be modified in-place. -#' Overwriting this method (currently) requires a solid understanding of the [`lazy_tensor`] internals. -#' You also need to pay attention to avoid name conflicts with existing columns in the task. +#' input `shapes_in` can be assumed to have exactly one shape vector for which it must calculate the output shapes +#' and return it as a `list()` of length 1. +#' It can also be assumed that the shape is not `NULL` (unknown). +#' It should also output a shape with exactly one NA in the first dimension or `NULL`if the output shape cannot be +#' determined (e.g. because it is random). #' #' @template param_id #' @template param_param_vals @@ -50,7 +31,7 @@ #' @param packages (`character()`)\cr #' The packages the preprocessing function depends on. #' @param param_set ([`ParamSet`])\cr -#' In case the function `fn` takes additional parameter besides a [`torch_tensor()`] they can be +#' In case the function `fn` takes additional parameter besides a [`torch_tensor`] they can be #' specfied as parameters. None of the parameters can have the [`"predict"`] tag. #' Pay attention to set the correct `tags` for the parameters: if tag `"train"` is present, #' the preprocessing is applied during training and if tag `"predict"` is present, the preprocessing is applied @@ -226,7 +207,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", pv$augment = NULL pv$affect_columns = NULL - if (is.null(private$.shapes_out) || ((stage == "predict") && augment)) { + if ((stage == "predict") && augment) { return(shapes_in) } @@ -317,7 +298,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", shape_out = self$shapes_out(list(shape_before), stage = stage, task = task)[[1L]] shape_out_predict = if (stage == "train") { - shape_in_predict = if (is.null(lt$.info$.predict_shape)) shape_before + shape_in_predict = if (is.null(lt$.pointer_shape_predict)) shape_before # during `$train()` we also keep track of the shapes that would arise during train # This avoids that we first train a learner and then only notice during predict that the shapes # during the predict phase are wrong @@ -337,6 +318,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", .additional_phash_input = function() { list(self$param_set$ids(), private$.fn, self$packages) }, + .shapes_out = function(shapes_in, param_vals, task) shapes_in, .fn = NULL ) ) diff --git a/R/PipeOpTorch.R b/R/PipeOpTorch.R index df41e74c..998151db 100644 --- a/R/PipeOpTorch.R +++ b/R/PipeOpTorch.R @@ -256,16 +256,11 @@ PipeOpTorch = R6Class("PipeOpTorch", assert_character(tags, null.ok = TRUE) assert_character(packages, any.missing = FALSE) - packages = union(packages, "torch") + packages = union(packages, c("mlr3torch", "torch")) input = data.table(name = inname, train = "ModelDescriptor", predict = "Task") output = data.table(name = outname, train = "ModelDescriptor", predict = "Task") assert_r6(param_set, "ParamSet") - #walk(param_set$params, function(p) { - # if (!(("train" %in% p$tags) && !("predict" %in% p$tags))) { - # stopf("Parameters of PipeOps inheriting from PipeOpTorch must only be active during training.") - # } - #}) super$initialize( id = id, @@ -283,8 +278,6 @@ PipeOpTorch = R6Class("PipeOpTorch", #' The input input shapes, which must be in the same order as the input channel names of the `PipeOp`. #' @param task ([`Task`] or `NULL`)\cr #' The task, which is very rarely used (default is `NULL`). An exception is [`PipeOpTorchHead`]. - #' @param stage (`character(1)`)\cr - #' Either `"train"` or `"predict"`. #' @return #' A named `list()` containing the output shapes. The names are the names of the output channels of #' the `PipeOp`. @@ -310,7 +303,7 @@ PipeOpTorch = R6Class("PipeOpTorch", # TODO: printer that calls the nn_module's printer ), private = list( - .shapes_out = function(shapes_in, param_vals, task, stage) shapes_in, + .shapes_out = function(shapes_in, param_vals, task) shapes_in, .shape_dependent_params = function(shapes_in, param_vals, task) param_vals, .make_module = function(shapes_in, param_vals, task) { do.call(self$module_generator, private$.shape_dependent_params(shapes_in, param_vals, task)) diff --git a/R/TaskClassif_lazy_iris.R b/R/TaskClassif_lazy_iris.R index ae6819ac..cd14fd63 100644 --- a/R/TaskClassif_lazy_iris.R +++ b/R/TaskClassif_lazy_iris.R @@ -1,18 +1,31 @@ #' @title Iris Classification Task #' #' @name mlr_tasks_lazy_iris +#' #' @format [R6::R6Class] inheriting from [TaskClassif]. #' @include zzz.R #' #' @description #' A classification task for the popular [datasets::iris] data set. -#' Just like the the iris task from mlr3, but the features are represented as one lazy tensor column. +#' Just like the the [iris task from mlr3](mlr3::mlr_tasks_iris), but the features are represented as one lazy tensor column. #' +#' @section Construction: +#' ``` +#' tsk("lazy_iris") +#' ``` #' @source #' \url{https://en.wikipedia.org/wiki/Iris_flower_data_set} #' -#' `r format_bib("anderson_1936")` #' +#' @section Meta Information: +#' `r rd_info_task_torch("lazy_iris", missings = FALSE)` +#' +#' @references +#' `r format_bib("anderson_1936")` +#' @examples +#' task = tsk("lazy_iris") +#' df = task$data() +#' materialize(df$x[1:6], rbind = TRUE) NULL load_task_lazy_iris = function(id = "lazy_iris") { diff --git a/R/TaskClassif_mnist.R b/R/TaskClassif_mnist.R index b46ceac3..b001ef4e 100644 --- a/R/TaskClassif_mnist.R +++ b/R/TaskClassif_mnist.R @@ -1,24 +1,30 @@ #' @title MNIST Image classification #' @name mlr_tasks_mnist #' @description -#' Classical MNIST image classification +#' Classical MNIST image classification. #' #' The underlying [`DataBackend`] contains columns `"label"`, `"image"`, `"row_id"`, `"split"`, where the last column #' indicates whether the row belongs to the train or test set. #' #' The first 60000 rows belong to the training set, the last 10000 rows to the test set. #' +#' @template task_download #' @section Construction: #' ``` #' tsk("mnist") #' ``` #' +#' @source +#' \url{https://torchvision.mlverse.org/reference/mnist_dataset.html} +#' #' @section Meta Information: #' `r rd_info_task_torch("mnist", missings = FALSE)` #' #' @references #' `r format_bib("mnist")` -#' +#' @examples +#' task = tsk("mnist") +#' task NULL # @param path (`character(1)`)\cr diff --git a/R/TorchLoss.R b/R/TorchLoss.R index 783a1ffe..4c75f161 100644 --- a/R/TorchLoss.R +++ b/R/TorchLoss.R @@ -106,7 +106,7 @@ TorchLoss = R6::R6Class("TorchLoss", id = NULL, label = NULL, packages = NULL, man = NULL) { force(id) self$task_types = assert_subset(task_types, mlr_reflections$task_types$type) - torch_loss = assert_class(torch_loss, "nn_loss") + torch_loss = assert_class(torch_loss, "nn_module") super$initialize( generator = torch_loss, diff --git a/R/TorchOptimizer.R b/R/TorchOptimizer.R index b4452827..5690df06 100644 --- a/R/TorchOptimizer.R +++ b/R/TorchOptimizer.R @@ -120,7 +120,9 @@ TorchOptimizer = R6::R6Class("TorchOptimizer", }, #' @description #' Instantiates the optimizer. - #' @param params The parameters of the network. + #' @param params (named `list()` of [`torch_tensor`])\cr + #' The parameters of the network. + #' @return `torch_optimizer` generate = function(params) { require_namespaces(self$packages) invoke(self$generator, .args = self$param_set$get_values(), params = params) diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index b62bb897..6391dd9c 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -28,10 +28,9 @@ #' has no batch dimension. #' @param clone_graph (`logical(1)`)\cr #' Whether to clone the preprocessing graph. -#' @param .info (any)\cr -#' Any additional meta-information (internal). -#' This is used by [`PipeOpTaskPreprocTorch`] to communicate the 'would-be' predict shapes to ensure -#' during the `$train()` phase that `$predict()` will be possible as well. +#' @param .pointer_shape_predict (`integer()` or `NULL`)\cr +#' Internal use only. +#' Used in a [`Graph`] to anticipate possible mismatches between train and predict shapes. #' #' @export #' @seealso ModelDescriptor, lazy_tensor @@ -63,11 +62,12 @@ #' # with no preprocessing #' dd1 = DataDescriptor(ds, list(x = c(NA, 3, 3))) DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NULL, .pointer = NULL, - .pointer_shape = NULL, clone_graph = TRUE, .info = list()) { + .pointer_shape = NULL, clone_graph = TRUE, .pointer_shape_predict = NULL) { assert_class(dataset, "dataset") # If the dataset implements a .getbatch() method the shape must be specified. assert_shapes(dataset_shapes, null_ok = is.null(dataset$.getbatch)) + assert_shape(.pointer_shape_predict, null_ok = TRUE) if (is.null(graph)) { if ((length(dataset_shapes) == 1L) && is.null(.input_map)) { @@ -114,7 +114,7 @@ DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NU # Once a DataDescriptor is created the input PipeOps are fix, we save them # here because they can be costly to compute .graph_input = graph$input$name, - .info = .info + .pointer_shape_predict = .pointer_shape_predict ), class = "DataDescriptor" ) @@ -172,12 +172,11 @@ new_lazy_tensor = function(data_descriptor, ids) { #' @export format.lazy_tensor = function(x, ...) { # nolint if (!length(x)) return(character(0)) - shape = x$data_descriptor + shape = x$data_descriptor$.pointer_shape shape = if (is.null(shape)) { - "?" - } else { - shape = paste0(x$data_descriptor$.pointer_shape[-1L], collapse = "x") + return(rep("", length(x))) } + shape = paste0(x$data_descriptor$.pointer_shape[-1L], collapse = "x") map_chr(x, function(elt) { sprintf("", shape) @@ -310,7 +309,7 @@ transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { data_descriptor$.pointer = c(pipeop$id, pipeop$output$name) data_descriptor$.pointer_shape = shape - data_descriptor$.info$.pointer_shape_predict = shape_predict + data_descriptor$.pointer_shape_predict = shape_predict data_descriptor = set_data_descriptor_hash(data_descriptor) new_lazy_tensor(data_descriptor, map_int(vec_data(lt), 1)) @@ -326,8 +325,17 @@ transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { return(dd) } - if (!(name %in% names(dd))) { - stopf("Unknown field '%s'.", name) - } + assert_choice(name, c( + "dataset", + "graph", + "dataset_shapes", + ".input_map", + ".pointer", + ".pointer_shape", + ".dataset_hash", + ".hash", + ".graph_input", + ".pointer_shape_predict" + )) dd[[name]] } diff --git a/R/materialize.R b/R/materialize.R index 381d1934..beabfc84 100644 --- a/R/materialize.R +++ b/R/materialize.R @@ -42,6 +42,7 @@ materialize = function(x, device = "cpu", rbind = FALSE, ...) { UseMethod("materialize") } +#' @rdname materialize #' @param cache (`character(1)` or `environment()` or `NULL`)\cr #' Optional cache for (intermediate) materialization results. #' Per default, caching will be enabled when the same dataset / graph is used for more than one lazy tensor column. diff --git a/man-roxygen/task_download.R b/man-roxygen/task_download.R new file mode 100644 index 00000000..9fc94184 --- /dev/null +++ b/man-roxygen/task_download.R @@ -0,0 +1,5 @@ +#' @section Download: +#' The [task][Task]'s backend is a [`DataBackendLazy`] which will download the data once it is requested. +#' Other meta-data is already available before that. +#' You can cache these datasets by setting the `mlr3torch.cache` option to `TRUE` or to a specific path to be used +#' as the cache directory. diff --git a/man/DataDescriptor.Rd b/man/DataDescriptor.Rd index d1bdb893..abdd7f57 100644 --- a/man/DataDescriptor.Rd +++ b/man/DataDescriptor.Rd @@ -12,7 +12,7 @@ DataDescriptor( .pointer = NULL, .pointer_shape = NULL, clone_graph = TRUE, - .info = list() + .pointer_shape_predict = NULL ) } \arguments{ @@ -45,10 +45,9 @@ has no batch dimension.} \item{clone_graph}{(\code{logical(1)})\cr Whether to clone the preprocessing graph.} -\item{.info}{(any)\cr -Any additional meta-information (internal). -This is used by \code{\link{PipeOpTaskPreprocTorch}} to communicate the 'would-be' predict shapes to ensure -during the \verb{$train()} phase that \verb{$predict()} will be possible as well.} +\item{.pointer_shape_predict}{(\code{integer()} or \code{NULL})\cr +Internal use only. +Used in a \code{\link{Graph}} to anticipate possible mismatches between train and predict shapes.} } \description{ A data descriptor is a rather internal structure used in the \code{\link{lazy_tensor}} data type. diff --git a/man/TorchOptimizer.Rd b/man/TorchOptimizer.Rd index 40031ba4..1bdd53c5 100644 --- a/man/TorchOptimizer.Rd +++ b/man/TorchOptimizer.Rd @@ -136,10 +136,14 @@ Instantiates the optimizer. \subsection{Arguments}{ \if{html}{\out{
}} \describe{ -\item{\code{params}}{The parameters of the network.} +\item{\code{params}}{(named \code{list()} of \code{\link{torch_tensor}})\cr +The parameters of the network.} } \if{html}{\out{
}} } +\subsection{Returns}{ +\code{torch_optimizer} +} } \if{html}{\out{
}} \if{html}{\out{}} diff --git a/man/materialize.Rd b/man/materialize.Rd index 7396682a..de791b89 100644 --- a/man/materialize.Rd +++ b/man/materialize.Rd @@ -2,9 +2,12 @@ % Please edit documentation in R/materialize.R \name{materialize} \alias{materialize} +\alias{materialize.list} \title{Materialize Lazy Tensor Columns} \usage{ materialize(x, device = "cpu", rbind = FALSE, ...) + +\method{materialize}{list}(x, device = "cpu", rbind = FALSE, cache = "auto") } \arguments{ \item{x}{(any)\cr @@ -13,6 +16,10 @@ Either a \code{\link{lazy_tensor}} or a \code{list()} / \code{data.frame()} cont \item{rbind}{(\code{logical(1)})\cr Whether to rbind the lazy tensor columns (\code{TRUE}) or return them as a list of tensors (\code{FALSE}).} + +\item{cache}{(\code{character(1)} or \code{environment()} or \code{NULL})\cr +Optional cache for (intermediate) materialization results. +Per default, caching will be enabled when the same dataset / graph is used for more than one lazy tensor column.} } \value{ (\code{list()} of \code{\link{lazy_tensor}}s or a \code{\link{lazy_tensor}}) diff --git a/man/mlr_backends_lazy.Rd b/man/mlr_backends_lazy.Rd index 71b45b4a..6fe50d79 100644 --- a/man/mlr_backends_lazy.Rd +++ b/man/mlr_backends_lazy.Rd @@ -24,6 +24,9 @@ Information that is available before the backend is constructed is: } Beware that accessing the backend's hash also contructs the backend. + +Note that while in most cases the data contains \code{\link{lazy_tensor}} columns, this is not necessary and the naming +of backend has nothing to do with the \code{\link{lazy_tensor}} datatype. } \examples{ # We first define a backend constructor @@ -118,7 +121,7 @@ Creates a new instance of this \link[R6:R6Class]{R6} class. \subsection{Arguments}{ \if{html}{\out{
}} \describe{ -\item{\code{constructor}}{(\verb{function()})\cr +\item{\code{constructor}}{(\code{function})\cr A function with no arguments, whose return value must be the actual backend. This function is called the first time the field \verb{$backend} is accessed.} diff --git a/man/mlr_learners_torch.Rd b/man/mlr_learners_torch.Rd index 0501f416..90058129 100644 --- a/man/mlr_learners_torch.Rd +++ b/man/mlr_learners_torch.Rd @@ -265,7 +265,7 @@ Train the learner. The task.} \item{\code{row_ids}}{(\code{integer()})\cr -Which rows to use for trainin.g} +Which rows to use for training.} } \if{html}{\out{
}} } @@ -286,7 +286,7 @@ Predict on a task. The task.} \item{\code{row_ids}}{(\code{integer()})\cr -For which rows to predict.} +The rows for which to make predictions.} } \if{html}{\out{}} } diff --git a/man/mlr_pipeops_module.Rd b/man/mlr_pipeops_module.Rd index 4a16df29..9361a48d 100644 --- a/man/mlr_pipeops_module.Rd +++ b/man/mlr_pipeops_module.Rd @@ -5,14 +5,13 @@ \alias{PipeOpModule} \title{Class for Torch Module Wrappers} \description{ -\code{PipeOpModule} wraps an \code{\link{nn_module}} that is being called during the \code{train} phase of this \code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}}. -By doing so, this allows to assemble \code{PipeOpModule}s in a computational \code{\link[mlr3pipelines:Graph]{mlr3pipelines::Graph}} that -represents a neural network architecture. Such a graph can also be used to create a \code{\link{nn_graph}} which inherits -from \code{\link{nn_module}}. +\code{PipeOpModule} wraps an \code{\link{nn_module}} or \code{function} that is being called during the \code{train} phase of this +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}}. By doing so, this allows to assemble \code{PipeOpModule}s in a computational +\code{\link[mlr3pipelines:Graph]{mlr3pipelines::Graph}} that represents either a neural network or a preprocessing graph of a \code{\link{lazy_tensor}}. +In most cases it is easier to create such a network by creating a graph that generates this graph. -In most cases it is easier to create such a network by creating a isomorphic graph consisting -of nodes of class \code{\link{PipeOpTorchIngress}} and \code{\link{PipeOpTorch}}. This graph will then generate the graph consisting -of \code{PipeOpModule}s as part of the \code{\link{ModelDescriptor}}. +To construct a neural network one combines mostly \code{\link{PipeOpTorchIngress}} and \code{\link{PipeOpTorch}} operators. +To construct a preprocessing graph, one combines mostly \code{PipeOp}s inheriting from \code{\link{PipeOpTaskPreprocTorch}}. } \section{Input and Output Channels}{ @@ -33,16 +32,17 @@ No parameters. \section{Internals}{ -During training, the wrapped \code{\link{nn_module}} is called with the provided inputs in the order in which the channels -are defined. Arguments are \strong{not} matched by name. +During training, the wrapped \code{\link{nn_module}} / \code{function} is called with the provided inputs in the order in which +the channels are defined. Arguments are \strong{not} matched by name. } \examples{ ## creating an PipeOpModule manually # one input and output channel -po_module = PipeOpModule$new("linear", - torch::nn_linear(10, 20), +po_module = po("module", + id = "linear", + module = torch::nn_linear(10, 20), inname = "input", outname = "output" ) @@ -63,9 +63,9 @@ nn_custom = torch::nn_module("nn_custom", ) module = nn_custom(3, 2) -po_module = PipeOpModule$new( - "custom", - module, +po_module = po("module", + id = "custom", + module = module, inname = c("x", "z"), outname = c("out1", "out2") ) @@ -74,7 +74,7 @@ z = torch::torch_randn(1, 3) out = po_module$train(list(x = x, z = z)) str(out) -# How a PipeOpModule is usually generated +# How such a PipeOpModule is usually generated graph = po("torch_ingress_num") \%>>\% po("nn_linear", out_features = 10L) result = graph$train(tsk("iris")) # The PipeOpTorchLinear generates a PipeOpModule and adds it to a new (module) graph @@ -83,6 +83,14 @@ linear_module = result[[1L]]$graph$pipeops$nn_linear linear_module formalArgs(linear_module$module) linear_module$input$name + + +po_add1 = po("module", + id = "add_one", + module = function(x) x + 1 +) +input = list(torch_tensor(1)) +po_add1$train(input)$output } \seealso{ Other Graph Network: diff --git a/man/mlr_pipeops_torch.Rd b/man/mlr_pipeops_torch.Rd index 5430d3c5..e90db5c3 100644 --- a/man/mlr_pipeops_torch.Rd +++ b/man/mlr_pipeops_torch.Rd @@ -354,9 +354,6 @@ The input input shapes, which must be in the same order as the input channel nam \item{\code{task}}{(\code{\link{Task}} or \code{NULL})\cr The task, which is very rarely used (default is \code{NULL}). An exception is \code{\link{PipeOpTorchHead}}.} - -\item{\code{stage}}{(\code{character(1)})\cr -Either \code{"train"} or \code{"predict"}.} } \if{html}{\out{}} } diff --git a/man/mlr_tasks_lazy_iris.Rd b/man/mlr_tasks_lazy_iris.Rd index 8dac6945..11a5d300 100644 --- a/man/mlr_tasks_lazy_iris.Rd +++ b/man/mlr_tasks_lazy_iris.Rd @@ -8,13 +8,39 @@ } \source{ \url{https://en.wikipedia.org/wiki/Iris_flower_data_set} +} +\description{ +A classification task for the popular \link[datasets:iris]{datasets::iris} data set. +Just like the the \href{mlr3::mlr_tasks_iris}{iris task from mlr3}, but the features are represented as one lazy tensor column. +} +\section{Construction}{ + + +\if{html}{\out{
}}\preformatted{tsk("lazy_iris") +}\if{html}{\out{
}} +} + +\section{Meta Information}{ +\itemize{ +\item Task type: \dQuote{classif} +\item Properties: \dQuote{multiclass} +\item Has Missings: no +\item Target: \dQuote{Species} +\item Features: \dQuote{x} +\item Backend Dimension: 150x3 +\item Default Roles (use / test / holdout): 150, 0, 0 +} +} + +\examples{ +task = tsk("lazy_iris") +df = task$data() +materialize(df$x[1:6], rbind = TRUE) +} +\references{ Anderson E (1936). \dQuote{The Species Problem in Iris.} \emph{Annals of the Missouri Botanical Garden}, \bold{23}(3), 457. \doi{10.2307/2394164}. } -\description{ -A classification task for the popular \link[datasets:iris]{datasets::iris} data set. -Just like the the iris task from mlr3, but the features are represented as one lazy tensor column. -} diff --git a/man/mlr_tasks_mnist.Rd b/man/mlr_tasks_mnist.Rd index 53c4c4a2..edaa44e5 100644 --- a/man/mlr_tasks_mnist.Rd +++ b/man/mlr_tasks_mnist.Rd @@ -3,14 +3,25 @@ \name{mlr_tasks_mnist} \alias{mlr_tasks_mnist} \title{MNIST Image classification} +\source{ +\url{https://torchvision.mlverse.org/reference/mnist_dataset.html} +} \description{ -Classical MNIST image classification +Classical MNIST image classification. The underlying \code{\link{DataBackend}} contains columns \code{"label"}, \code{"image"}, \code{"row_id"}, \code{"split"}, where the last column indicates whether the row belongs to the train or test set. The first 60000 rows belong to the training set, the last 10000 rows to the test set. } +\section{Download}{ + +The \link[=Task]{task}'s backend is a \code{\link{DataBackendLazy}} which will download the data once it is requested. +Other meta-data is already available before that. +You can cache these datasets by setting the \code{mlr3torch.cache} option to \code{TRUE} or to a specific path to be used +as the cache directory. +} + \section{Construction}{ @@ -31,6 +42,10 @@ The first 60000 rows belong to the training set, the last 10000 rows to the test } } +\examples{ +task = tsk("mnist") +task +} \references{ Lecun, Y., Bottou, L., Bengio, Y., Haffner, P. (1998). \dQuote{Gradient-based learning applied to document recognition.} diff --git a/tests/testthat/helper_autotest.R b/tests/testthat/helper_autotest.R index a4e981e9..6f663e39 100644 --- a/tests/testthat/helper_autotest.R +++ b/tests/testthat/helper_autotest.R @@ -120,14 +120,21 @@ autotest_pipeop_torch = function(graph, id, task, module_class = id, exclude_arg predicted = po_test$shapes_out(map(layerin, dim), task) observed = map(layerout, dim) - test_shapes(predicted, observed) + expect_compatible_shapes(predicted, observed) + + # parameters must only ce active during training + walk(po_test$param_set$params, function(p) { + if (!(("train" %in% p$tags) && !("predict" %in% p$tags))) { + stopf("Parameters of PipeOps inheriting from PipeOpTorch must only be active during training.") + } + }) return(TRUE) } # Note that we don't simply compare the shapes for equality. The actually observed shape does not have NAs, # so wherevery the predicted dimension is NA, the observed dimension can be anything. -test_shapes = function(predicted, observed) { +expect_compatible_shapes = function(predicted, observed) { # they are both lists if (length(predicted) != length(observed)){ stopf("This should have been impossible!") @@ -306,20 +313,14 @@ autotest_torch_callback = function(torch_callback, check_man = TRUE) { autotest_pipeop_torch_preprocess = function() { # TODO: - # a) Check that all parameters but augment have tags train and predict (this should hold in basically all cases) -} - -autotest_preproc_and_trafo = function(obj) { - autotest_trafo(obj) - autotest_preproc(obj) -} - -autotest_trafo = function(obj) { - -} - -autotest_preproc = function(obj) { expect_class(obj, "PipeOpTaskPreprocTorch") - - # TODO: Unless the test is disabled, check that all parameters have train tag + # a) Check that all parameters but augment have tags train and predict (this should hold in basically all cases) + # b) Check that the shape prediction is compatible (already done in autotest for pipeop torch) + # c) check that start with augment / trafo, depending on the initial value + + #walk(po_test$param_set$params, function(p) { + # if (!(("train" %in% p$tags) && !("predict" %in% p$tags))) { + # stopf("Parameters of PipeOps inheriting from PipeOpTorch must only be active during training.") + # } + #}) } diff --git a/tests/testthat/helper_functions.R b/tests/testthat/helper_functions.R index 21bad342..856969da 100644 --- a/tests/testthat/helper_functions.R +++ b/tests/testthat/helper_functions.R @@ -55,8 +55,7 @@ expect_deep_clone = function(one, two) { # TODO: Take care of torch parameters tensors and buffers and torch optimizer and nn module etc. - if (inherits(a, "nn_module_generator") || inherits(a, "torch_optimizer_generator") || - inherits(a, "R6ClassGenerator")) { + if (inherits(a, "nn_module_generator") || inherits(a, "torch_optimizer_generator") || inherits(a, "R6ClassGenerator")) { return(invisible(NULL)) } @@ -248,7 +247,7 @@ random_dataset = dataset("random_dataset", self$x = torch_randn(n, ...) }, .getbatch = function(i) { - list(x = self$x[i, .., drop = FALSE]) + list(x = self$x[i, ..,]) }, .length = function() { nrow(self$x) diff --git a/tests/testthat/test_LearnerTorch.R b/tests/testthat/test_LearnerTorch.R index 99edf5f3..006896e0 100644 --- a/tests/testthat/test_LearnerTorch.R +++ b/tests/testthat/test_LearnerTorch.R @@ -380,7 +380,51 @@ test_that("resample() works", { expect_r6(rr, "ResampleResult") }) -test_that("Shapes are checked correctly during `$train()`", { - # FIXME: For this the taskpreproc should work first +test_that("Input verification works during `$train()` (train-predict shapes work together)", { + task = nano_mnist() + task_invalid = po("trafo_resize", size = c(10, 10), augment = TRUE) $train(list(task))[[1L]] + task_valid = po("trafo_resize", size = c(10, 10), augment = FALSE) $train(list(task))[[1L]] + + learner = lrn("classif.torch_featureless", + batch_size = 1L, epochs = 0L + ) + + # fallback learner cannot help in this case! + learner$fallback = lrn("classif.featureless") + expect_error( + learner$train(task_invalid), + "would have a different shape during" + ) + + expect_error( + learner$train(task_valid), + NA + ) + + task_unknown = po("trafo_resize", size = c(10, 10), augment = TRUE) $train(list(nano_dogs_vs_cats()))[[1L]] + + expect_error( + learner$train(task_unknown), + NA + ) + +}) + +test_that("Input verification works during `$predict()` (same column info, problematic fct -> int conversion)", { + task1 = as_task_classif(data.table( + y = factor(c("A", "B")) + ), target = "y", id = "test1") + + task2 = as_task_classif(data.table( + y = factor(c("A", "B"), labels = c("B", "A"), levels = c("B", "A")) + ), target = "y", id = "test2") + + learner = lrn("classif.torch_featureless", batch_size = 1L, epochs = 0L) + + learner$train(task1) + expect_error( + learner$predict(task2), + "does not match" + ) }) diff --git a/tests/testthat/test_PipeOpModule.R b/tests/testthat/test_PipeOpModule.R index d155a672..fe3b896e 100644 --- a/tests/testthat/test_PipeOpModule.R +++ b/tests/testthat/test_PipeOpModule.R @@ -1,3 +1,17 @@ +test_that("PipeOpModule: basic checks", { + # nn_Module cannot be used (otherwise the phash would be wrong) + expect_error(po("module", module = attr(nn_relu(), "module"))) + + po_fn = po("module", id = "identity", module = identity, packages = "R6", inname = "a", outname = "b") + expect_pipeop(po_fn) + expect_equal(po_fn$id, "identity") + expect_equal(po_fn$input$name, "a") + expect_equal(po_fn$output$name, "b") + po_nn = po("module", id = "relu", module = nn_relu()) + expect_pipeop(po_nn) + expect_equal(po_nn$id, "relu") +}) + test_that("PipeOpModule works", { po_module = PipeOpModule$new("linear", torch::nn_linear(10, 20), inname = "abc", outname = "xyz") x = torch::torch_randn(16, 10) @@ -27,3 +41,28 @@ test_that("PipeOpModule works", { expect_true(all(sort(names(y)) == c("out1", "out2"))) expect_list(y, types = "torch_tensor") }) + +test_that("Cloning works", { + expect_error(po("module", module = nn_linear(1, 1))$clone(deep = TRUE)) + expect_error(po("module", module = idenity)$clone(deep = TRUE)) +}) + +test_that("phash for PipeOpModule works", { + f = function(x) x + + fc = compiler::cmpfun(f) + + fe = f + environment(fe) = new.env() + + p1 = po("module", module = f) + p2 = po("module", module = fc) + p3 = po("module", module = fe) + + expect_equal(p1$phash, p2$phash) + expect_false(p1$phash == p3$phash) + + f1 = po("module", module = nn_linear(1, 1)) + f2 = po("module", module = nn_linear(1, 1)) + expect_false(f1$phash == f2$phash) +}) diff --git a/tests/testthat/test_PipeOpTorch.R b/tests/testthat/test_PipeOpTorch.R index ad52d193..50068ee6 100644 --- a/tests/testthat/test_PipeOpTorch.R +++ b/tests/testthat/test_PipeOpTorch.R @@ -3,7 +3,7 @@ test_that("Basic checks", { # basic checks that output is checked correctly obj = PipeOpTorchDebug$new(id = "debug", inname = paste0("input", 1:2), outname = paste0("output", 1:2)) - expect_pipeop(obj, ) + expect_pipeop(obj) expect_class(obj, "PipeOpTorch") expect_equal(unique(obj$input$train), "ModelDescriptor") @@ -13,6 +13,7 @@ test_that("Basic checks", { expect_equal(unique(obj$output$predict), "Task") expect_class(obj$module_generator, "nn_module_generator") expect_equal(obj$tags, "torch") + expect_set_equal(obj$packages, c("mlr3torch", "torch", "mlr3pipelines")) }) test_that("cloning works", { diff --git a/tests/testthat/test_TaskClassif_lazy_iris.R b/tests/testthat/test_TaskClassif_lazy_iris.R new file mode 100644 index 00000000..d8cb09f2 --- /dev/null +++ b/tests/testthat/test_TaskClassif_lazy_iris.R @@ -0,0 +1,3 @@ +test_that("tiny_imagenet task works", { + task = tsk("lazy_iris") +}) diff --git a/tests/testthat/test_TaskClassif_mnist.R b/tests/testthat/test_TaskClassif_mnist.R new file mode 100644 index 00000000..c8c92e2e --- /dev/null +++ b/tests/testthat/test_TaskClassif_mnist.R @@ -0,0 +1,6 @@ +test_that("tiny_imagenet task works", { + task = tsk("lazy_iris") + expect_task(task) + expect_equal(task$id == "lazy_iris") + expect_equal(task$man == "mlr3torch::mlr_tasks_lazy_iris") +}) From becbcff98d794a6e12f064c7a5c9d0b313c1d837 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 24 Nov 2023 17:31:53 +0100 Subject: [PATCH 14/90] add implementations, change augment -> stages --- R/DataBackendLazy.R | 2 +- R/LearnerTorch.R | 4 +- R/PipeOpModule.R | 19 +- R/PipeOpTaskPreprocTorch.R | 187 ++++++++---------- R/PipeOpTorch.R | 2 +- R/TaskClassif_lazy_iris.R | 1 - R/TaskClassif_mnist.R | 9 +- R/TaskClassif_tiny_imagenet.R | 6 +- R/TorchOptimizer.R | 2 +- R/lazy_tensor.R | 28 +-- R/learner_torch_methods.R | 14 +- R/materialize.R | 1 + R/preprocess.R | 169 +++++++++------- R/shape.R | 14 +- R/zzz.R | 27 --- inst/col_info/mnist.rds | Bin 266 -> 276 bytes man/DataDescriptor.Rd | 16 +- man/TorchOptimizer.Rd | 2 +- man/materialize.Rd | 3 +- man/mlr_backends_lazy.Rd | 2 +- man/mlr_pipeops_module.Rd | 20 +- man/mlr_pipeops_preproc_torch.Rd | 67 +++---- man/mlr_tasks_tiny_imagenet.Rd | 4 + man/pipeop_preproc_torch.Rd | 8 +- man/pipeop_preproc_torch_class.Rd | 10 +- tests/testthat/helper_autotest.R | 57 ++++-- tests/testthat/helper_functions.R | 2 +- tests/testthat/test_LearnerTorch.R | 6 +- tests/testthat/test_PipeOpTaskPreprocTorch.R | 38 ++-- tests/testthat/test_TaskClassif_lazy_iris.R | 9 + tests/testthat/test_TaskClassif_mnist.R | 20 +- .../testthat/test_TaskClassif_tiny_imagenet.R | 26 ++- tests/testthat/test_autotests.R | 13 +- tests/testthat/test_lazy_tensor.R | 2 + tests/testthat/test_nn_graph.R | 2 +- tests/testthat/test_preprocess.R | 6 + tests/testthat/test_shape.R | 11 ++ 37 files changed, 429 insertions(+), 380 deletions(-) create mode 100644 tests/testthat/test_preprocess.R create mode 100644 tests/testthat/test_shape.R diff --git a/R/DataBackendLazy.R b/R/DataBackendLazy.R index ab1495cb..304b5576 100644 --- a/R/DataBackendLazy.R +++ b/R/DataBackendLazy.R @@ -22,7 +22,7 @@ #' Beware that accessing the backend's hash also contructs the backend. #' #' Note that while in most cases the data contains [`lazy_tensor`] columns, this is not necessary and the naming -#' of backend has nothing to do with the [`lazy_tensor`] datatype. +#' of this class has nothing to do with the [`lazy_tensor`] datatype. #' #' @param constructor (`function`)\cr #' A function with no arguments, whose return value must be the actual backend. diff --git a/R/LearnerTorch.R b/R/LearnerTorch.R index 18caa950..31ba888d 100644 --- a/R/LearnerTorch.R +++ b/R/LearnerTorch.R @@ -312,9 +312,6 @@ LearnerTorch = R6Class("LearnerTorch", if (!is_lazy_tensor(x)) return(NULL) predict_shape = x$.pointer_shape_predict train_shape = x$.pointer_shape - # If no information on hypothetical predict shape is available we continue training - # This is e.g. the case when a completely un-preprocessed lazy tensor is used - # Otherwise we expect the predict_shape to be equal to the train shape if (is.null(train_shape) || is.null(predict_shape)) { return(NULL) } @@ -328,6 +325,7 @@ LearnerTorch = R6Class("LearnerTorch", cols = c(task$feature_names, task$target_names) ci_predict = task$col_info[get("id") %in% cols, c("id", "type", "levels")] ci_train = self$model$task_col_info[get("id") %in% cols, c("id", "type", "levels")] + # permuted factor levels cause issues, because we are converting fct -> int if (!test_equal_col_info(ci_train, ci_predict)) { # nolint stopf(paste0( "Predict task's `$col_info` does not match the train task's column info.\n", diff --git a/R/PipeOpModule.R b/R/PipeOpModule.R index b11252c2..b07d8500 100644 --- a/R/PipeOpModule.R +++ b/R/PipeOpModule.R @@ -75,8 +75,7 @@ #' formalArgs(linear_module$module) #' linear_module$input$name #' -#' -# Constructing a PipeOpModule using a simple function +#' Constructing a PipeOpModule using a simple function #' po_add1 = po("module", #' id = "add_one", #' module = function(x) x + 1 @@ -85,6 +84,7 @@ #' po_add1$train(input)$output PipeOpModule = R6Class("PipeOpModule", inherit = PipeOp, + cloneable = FALSE, public = list( #' @field module ([`nn_module`])\cr #' The torch module that is called during the training phase. @@ -106,9 +106,6 @@ PipeOpModule = R6Class("PipeOpModule", private$.multi_output = length(outname) > 1L self$module = assert(check_class(module, "nn_module"), check_class(module, "function"), combine = "or") self$module = module - assert_names(inname, type = "strict") - assert_names(outname, type = "strict") - assert_character(packages, any.missing = FALSE) packages = union(c("mlr3torch", "torch"), packages) input = data.table(name = inname, train = "torch_tensor", predict = "NULL") @@ -147,14 +144,10 @@ PipeOpModule = R6Class("PipeOpModule", list(fn_input, self$input$name, self$output$name, self$packages) }, deep_clone = function(name, value) { - if (name != "fn") { - return(super$deep_clone(name, value)) - } - if (test_class(value, "nn_module")) { - value$clone(deep = TRUE) - } else { - value - } + # Waiting for R6 release: https://github.com/r-lib/R6/commit/6ba0dce26b1a7fc9b812bc4d92f09123d3b9648d + stopf("Cannot create a deep clone of PipeOpModule if it wraps an `nn_module`.") + # Note that we could allow to clone methods that wrap functions, but this should basically never be necessary, + # as this PipeOp has not state and just functions as a function } ) ) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 045638f0..543b2ebc 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -1,28 +1,30 @@ -#' @title Base Class for Torch Preprocessing +#' @title Base Class for Lazy Tensor Preprocessing #' @name mlr_pipeops_preproc_torch #' #' @description #' This `PipeOp` can be used to preprocess (one or more) [`lazy_tensor`] columns contained in an [`mlr3::Task`]. #' The preprocessing function is specified as construction argument `fn` and additional arguments to this #' function can be defined through the `PipeOp`'s parameter set. -#' The preprocessing is done per-column, i.e. the number lazy tensor output columns is equivalent +#' The preprocessing is done per column, i.e. the number of lazy tensor output columns is equal #' to the number of lazy tensor input columns. -#' The preprocessing that is applied during `$predict()` uses the parameters that were set during `$train()` and not -#' those that are set when performing the prediction. +#' +#' To create custom preprocessing `PipeOp`s you can use [`pipeop_preproc_torch`] / [`pipeop_preproc_torch_class`]. #' #' @section Inheriting: -#' In addition to specifying the construction arguments, you can overwrite the private `.shapes_out()` method: +#' In addition to specifying the construction arguments, you can overwrite the private `.shapes_out()` method. +#' If you don't overwrite it, the output shapes are assumed to be unknown (`NULL`). +#' #' * `.shapes_out(shapes_in, param_vals, task)`\cr #' (`list()`, `list(), `Task` or `NULL`) -> `list()`\cr #' This private method calculates the output shapes of the lazy tensor columns that are created from applying -#' the preprocessing. +#' the preprocessing function with the provided parameter values (`param_vals`). +#' The `task` is very rarely needed, but if it is it should be checked that it is not `NULL`. #' #' This private method only has the responsibility to calculate the output shapes for one input column, i.e. the #' input `shapes_in` can be assumed to have exactly one shape vector for which it must calculate the output shapes #' and return it as a `list()` of length 1. -#' It can also be assumed that the shape is not `NULL` (unknown). -#' It should also output a shape with exactly one NA in the first dimension or `NULL`if the output shape cannot be -#' determined (e.g. because it is random). +#' It can also be assumed that the shape is not `NULL` (i.e. unknown). +#' Also, the first dimension can be `NA`, i.e. is unknown (as for the batch dimension). #' #' @template param_id #' @template param_param_vals @@ -33,12 +35,9 @@ #' @param param_set ([`ParamSet`])\cr #' In case the function `fn` takes additional parameter besides a [`torch_tensor`] they can be #' specfied as parameters. None of the parameters can have the [`"predict"`] tag. -#' Pay attention to set the correct `tags` for the parameters: if tag `"train"` is present, -#' the preprocessing is applied during training and if tag `"predict"` is present, the preprocessing is applied -#' during prediction (if `augment` is set to `FALSE`). -#' @param augment_init (`logical(1)` or `NULL`)\cr -#' Initial value for the `augment` parameter. -#' If it is `NULL`, there is no `augment` parameter. +#' All tags should be set to `"train"`. +#' @param stages_init (`logical(1)`)\cr +#' Initial value for the `stages` parameter. #' @section Input and Output Channels: #' See [`PipeOpTaskPreproc`]. #' @section State: @@ -47,17 +46,23 @@ #' In addition to the parameters inherited from [`PipeOpTaskPreproc`] as well as those specified during construction #' as the argument `param_set` there are the following parameters: #' -#' * `augment` :: `logical(1)`\cr -#' (This parameter only exists of the `PipeOp`) is applied per column. -#' Whether the to apply the preprocessing only during training (`TRUE`) or also during prediction (`FALSE`). -#' This parameter is initialized to `FALSE`. +#' * `stages` :: `character()`\cr +#' The stages during which to apply the preprocessing. +#' Must be a subset of `"train"` and `"predict"`. +#' Note that the preprocessing that is applied during `$predict()` uses the parameters that were set during +#' `$train()` and not those that are set when performing the prediction. #' #' @section Internals: #' A [`PipeOpModule`] with one input and one output channel is created. #' The pipeop simply applies the function `fn` to the input tensor while additionally -#' passing the paramter values (minus `augment` and `affect_columns`) to `fn`. -#' Then [`transform_lazy_tensor`] is called with the created [`PipeOpModule`] and the shapes obtained from the -#' `$shapes_out()` method of this `PipeOp`. +#' passing the parameter values (minus `stages` and `affect_columns`) to `fn`. +#' In addition, the new shapes are calculates using the `$shapes_out()` method. +#' Then, new lazy tensor columns with updated preprocessing graphs and metadata are created. +#' This mechanism is very similar to the [`ModelDescriptor`] mechanism that is being used to construct +#' neural network architectures. Read the (Internals) documentation of [`PipeOpTorch`] for this. +#' +#' We also add the shape that would be present during a `$predict()` call, this information can later be used +#' to check whether the train-preprocessing and the predict-preprocessing are compatible. #' #' @include PipeOpTorch.R #' @export @@ -76,13 +81,13 @@ #' po_simple = po("preproc_torch", #' # use mlr3misc::crate to get rid of unnecessary environment baggage #' fn = mlr3misc::crate(function(x, a) x + a), -#' param_set = ps(a = p_int(tags = c("train", "predict", "required"))) +#' param_set = ps(a = p_int(tags = c("train", "required"))) #' ) #' #' po_simple$param_set$set_values( #' a = 100, #' affect_columns = selector_name(c("x1", "x2")), -#' augment = FALSE +#' stages = c("train", "predict") #' ) #' #' taskout_train = po_simple$train(list(taskin))[[1L]] @@ -92,7 +97,7 @@ #' materialize(taskout_predict_noaug$data(cols = c("x1", "x2")), rbind = TRUE) #' #' po_simple$param_set$set_values( -#' augment = TRUE +#' stages = "train" #' ) #' #' # transformation is not applied @@ -153,18 +158,14 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' @description #' Creates a new instance of this [`R6`][R6::R6Class] class. initialize = function(fn, id = "preproc_torch", param_vals = list(), param_set = ps(), packages = character(0), - augment_init = FALSE) { + stages_init = c("train", "predict")) { private$.fn = assert_function(fn) - assert_flag(augment_init, null.ok = TRUE) + assert_subset(stages_init, c("train", "predict")) param_set$add(ps( - augment = p_lgl(tags = c("train", "required")) + stages = p_uty(tags = c("train", "required"), custom_check = crate(function(x) check_subset(x, c("train", "predict")))) )) - param_set$set_values(augment = augment_init) - - if (some(param_set$tags, function(tags) "predict" %in% tags)) { - stopf("Parameter set cannot contain tags 'predict'.") - } + param_set$set_values(stages = stages_init) super$initialize( id = id, @@ -178,10 +179,11 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' Calculates the output shapes that would result in applying the preprocessing to one or more #' lazy tensor columns with the provided shape. #' Names are ignored and only order matters. - #' It uses the parameeter values that are currently set. + #' It uses the parameter values that are currently set. #' @param shapes_in (`list()` of (`integer()` or `NULL`))\cr #' The input input shapes of the lazy tensors. #' `NULL` indicates that the shape is unknown. + #' First dimension must be `NA`. #' @param stage (`character(1)`)\cr #' The stage: either `"train"` or `"predict"`. #' @param task ([`Task`] or `NULL`)\cr @@ -203,11 +205,11 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", self$state$param_vals } - augment = pv$augment - pv$augment = NULL + stages = pv$stages + pv$stages = NULL pv$affect_columns = NULL - if ((stage == "predict") && augment) { + if (stage %nin% stages) { return(shapes_in) } @@ -220,6 +222,14 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", return(shapes) } ), + active = list( + #' @description + #' The preprocessing function. + fn = function(rhs) { + assert_ro_binding(rhs) + private$.fn + } + ), private = list( .train_task = function(task) { dt_columns = private$.select_cols(task) @@ -255,11 +265,12 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", .transform = function(dt, task, param_vals, stage) { # stage is "train" or "predict" param_vals$affect_columns = NULL + stages = param_vals$stages + param_vals$stages = NULL trafo = private$.fn - if (stage == "train") { - param_vals$augment = NULL - fn = if (length(param_vals)) { + fn = if (stage %in% stages) { + if (length(param_vals)) { crate(function(x) { invoke(.f = trafo, x, .args = param_vals) }, param_vals, trafo, .parent = environment(trafo)) @@ -267,21 +278,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", trafo } } else { - augment = param_vals$augment - param_vals$augment = NULL - # augment can be NULL (in case the pipeop changes the output shape and hence augmentation is not supported) - # or a logical(1) - fn = if (isTRUE(augment)) { - # We cannot simple add no module to the graph as we need to maintain the same graph-structure - # as during training - identity - } else if (length(param_vals)) { - crate(function(x) { - invoke(.f = trafo, x, .args = param_vals) - }, param_vals, trafo, .parent = environment(trafo)) - } else { - trafo - } + identity } dt = map_dtc(dt, function(lt) { @@ -299,7 +296,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", shape_out_predict = if (stage == "train") { shape_in_predict = if (is.null(lt$.pointer_shape_predict)) shape_before - # during `$train()` we also keep track of the shapes that would arise during train + # during `$train()` we also keep track of the shapes that would arise during predict # This avoids that we first train a learner and then only notice during predict that the shapes # during the predict phase are wrong shape_out_predict = self$shapes_out(list(shape_before), stage = "predict", task = task)[[1L]] @@ -312,13 +309,16 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", # a `$predict()` call is possible later. x }) - names(dt) = uniqueify(names(dt), setdiff(task$col_info$id, names(dt))) + # no need to ensure uniqueness of names as we are just taking the names as they already are return(dt) }, .additional_phash_input = function() { - list(self$param_set$ids(), private$.fn, self$packages) + list( + self$param_set$ids(), self$packages, + formals(private$.fn), body(private$.fn), address(environment(private$.fn)) + ) }, - .shapes_out = function(shapes_in, param_vals, task) shapes_in, + .shapes_out = function(shapes_in, param_vals, task) list(NULL), .fn = NULL ) ) @@ -370,20 +370,21 @@ create_ps_call = function(fn) { #' @title Create Torch Preprocessing PipeOps #' @description -#' Convenience functions to create objects of class [`PipeOpTaskPreprocTorch`] in a slightly more convenient way. +#' Function to create objects of class [`PipeOpTaskPreprocTorch`] in a slightly more convenient way. #' Start by reading the documentation of [`PipeOpTaskPreprocTorch`]. #' @template param_id #' @param fn (`function`)\cr #' The preprocessing function. -#' @param shapes_out (`function` or `NULL` or "infer")\cr -#' The private `.shapes_out(shapes_in, param_vals, task)` method of [`PipeOpTaskPreprocTorch`]. -#' If `NULL`, the pipeop does not change the output shapes. -#' If `TRUE`, the output shape function is inferred and calculates the output shapes as follows: -#' a) The input shapes are known: -#' For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is -#' applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. -#' b) The input shapes are unknown (all NA): -#' The dimension is returned as is. +#' @param shapes_out (`function` or `NULL` or `"infer"` or `"unchanged"`)\cr +#' The private `.shapes_out(shapes_in, param_vals, task)` method of [`PipeOpTaskPreprocTorch`] +#' (see section Inheriting). +#' Special values are `NULL` and `infer`: +#' If `NULL`, the output shapes are unknown. +#' If "infer", the output shape function is inferred and calculates the output shapes as follows: +#' For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is +#' applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. +#' +#' This should be correct in most cases, but might fail in some edge cases. #' @param param_set ([`ParamSet`] or `NULL`)\cr #' The parameter set. #' If this is left as `NULL` (default) the parameter set is inferred in the following way: @@ -403,9 +404,10 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack assert_true(length(formals(fn)) >= 1L) assert( check_function(shapes_out, args = c("shapes_in", "param_vals", "task"), null.ok = TRUE), - check_choice(shapes_out, "infer") + check_choice(shapes_out, c("infer", "unknown", )) ) + if (!is.null(param_set)) { assert_param_set(eval(param_set)) } else { @@ -419,24 +421,28 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack if (identical(shapes_out, "infer")) { shapes_out = crate(function(shapes_in, param_vals, task) { sin = shapes_in[[1L]] - if (all(is.na(sin))) { - # This is only TRUE if the preprocessing pipeop does not change the number of dimensions. - return(list(sin)) - } - # set batch-dim to 1 - sin[1] = 1L + unknown_batch_dim = is.na(sin[1L]) + if (unknown_batch_dim) { + sin[1] = 1L + } tensor_in = invoke(torch_empty, .args = sin, device = torch_device("meta")) tensor_out = invoke(private$.fn, tensor_in, .args = param_vals) sout = dim(tensor_out) - sout[1] = NA + if (unknown_batch_dim) { + sout[1] = NA + } + list(sout) }) + } else if (identical(shapes_out, "unchanged")) { + shapes_out = crate(function(shapes_in, param_vals, task_in) shapes_in) } else { - assert_function(shapes_out, args = c("shapes_in", "param_vals", "task"), null.ok = TRUE) + stopf("Cannot happen") } + init_fun = crate(function(id = idname, param_vals = list()) { super$initialize( id = id, @@ -457,9 +463,7 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack public = list( initialize = init_fun ), - private = list( - .shapes_out = shapes_out - ) + private = if (!is.null(shapes_out)) list(.shapes_out = shapes_out) else list() ) return(Class) @@ -471,25 +475,4 @@ register_preproc = function(id, fn, param_set = NULL, shapes_out = NULL, package register_po(id, Class) } - -# Where I was: -# PipeOpTaskPreprocTorch and PipeOpTorchTrafo: -# their shapes_out method should be slightly different, i.e. -# --> How to implement this? -# 1. In register_lazy I want to specify the shapes_out method only once. -# 2. PipeOpTorch expects list()s but ...TaskPreproc should probably input and output shape -# vectors -# -# Other thigns: - # I want to provide helper functions to create these pipeops for: - # * preproc - # * trafo - # * pipeop torch -# Other things: - # * autotest for trafo and preproc - # * implement some common trafos and preprocs - # - # - - register_po("preproc_torch", PipeOpTaskPreprocTorch, metainf = list(fn = identity)) diff --git a/R/PipeOpTorch.R b/R/PipeOpTorch.R index 998151db..496eaaba 100644 --- a/R/PipeOpTorch.R +++ b/R/PipeOpTorch.R @@ -337,7 +337,7 @@ PipeOpTorch = R6Class("PipeOpTorch", ) # integrate the operation into the graph - result_template$graph$add_pipeop(module_op) + result_template$graph$add_pipeop(module_op, clone = FALSE) # All of the `inputs` contained possibly the same `graph`, but definitely had different `.pointer`s, # indicating the different channels from within the `graph` that should be connected to the new operation. vararg = "..." == module_op$input$name[[1L]] diff --git a/R/TaskClassif_lazy_iris.R b/R/TaskClassif_lazy_iris.R index cd14fd63..c271180c 100644 --- a/R/TaskClassif_lazy_iris.R +++ b/R/TaskClassif_lazy_iris.R @@ -16,7 +16,6 @@ #' @source #' \url{https://en.wikipedia.org/wiki/Iris_flower_data_set} #' -#' #' @section Meta Information: #' `r rd_info_task_torch("lazy_iris", missings = FALSE)` #' diff --git a/R/TaskClassif_mnist.R b/R/TaskClassif_mnist.R index b001ef4e..9b65c00a 100644 --- a/R/TaskClassif_mnist.R +++ b/R/TaskClassif_mnist.R @@ -48,9 +48,8 @@ constructor_mnist = function(path) { load_task_mnist = function(id = "mnist") { cached_constructor = function() { - # We need this as otherwise the factor level are differently ordered, - # which causes the hard-coded col-info to be wrong for some locales - # (whether a < A or A > a depends on the locale) + # factor level ordering can depend on locale + # in this case, nothing should go wrong but we keep it here as a reminder (is e.g. needed in tiny imagenet) withr::with_locale(c(LC_COLLATE = "C"), { data = cached(constructor_mnist, "datasets", "mnist")$data }) @@ -89,10 +88,10 @@ load_task_mnist = function(id = "mnist") { backend = backend, id = "mnist", target = "label", - label = "MNIST Image Classifiacation", + label = "MNIST Digit Classification", ) - backend$hash = task$man = "mlr3::mlr_tasks_mnist" + backend$hash = task$man = "mlr3torch::mlr_tasks_mnist" task$row_roles$use = seq_len(60000) task$row_roles$test = seq(from = 60001, 70000) diff --git a/R/TaskClassif_tiny_imagenet.R b/R/TaskClassif_tiny_imagenet.R index 3c85d282..1da683e8 100644 --- a/R/TaskClassif_tiny_imagenet.R +++ b/R/TaskClassif_tiny_imagenet.R @@ -24,7 +24,9 @@ #' #' @references #' `r format_bib("imagenet2009")` -#' +#' @examples +#' task = tsk("tiny_imagenet") +#' task NULL # @param path (`character(1)`)\cr @@ -102,6 +104,8 @@ load_task_tiny_imagenet = function(id = "tiny_imagenet") { label = "ImageNet Subset" ) + backend$hash = task$man = "mlr3torch::mlr_tasks_tiny_imagenet" + task$row_roles$use = seq_len(100000) task$row_roles$test = seq(from = 100001, 110000) task$row_roles$holdout = seq(from = 110001, 120000) diff --git a/R/TorchOptimizer.R b/R/TorchOptimizer.R index 5690df06..215dfe91 100644 --- a/R/TorchOptimizer.R +++ b/R/TorchOptimizer.R @@ -120,7 +120,7 @@ TorchOptimizer = R6::R6Class("TorchOptimizer", }, #' @description #' Instantiates the optimizer. - #' @param params (named `list()` of [`torch_tensor`])\cr + #' @param params (named `list()` of [`torch_tensor`]s)\cr #' The parameters of the network. #' @return `torch_optimizer` generate = function(params) { diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index 6391dd9c..7c04fc0e 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -1,17 +1,19 @@ #' @title Data Descriptor #' #' @description -#' A data descriptor is a rather internal structure used in the [`lazy_tensor`] data type. +#' A data descriptor is a rather internal data structure used in the [`lazy_tensor`] data type. #' In essence it is an annotated [`torch::dataset`] and a preprocessing graph (consisting mosty of [`PipeOpModule`] -#' operators). The additional meta data (e.g. shapes) allows to preprocess [`lazy_tensors`] in an +#' operators). The additional meta data (e.g. pointer, shapes) allows to preprocess [`lazy_tensors`] in an #' [`mlr3pipelines::Graph`] just like any (non-lazy) data types. +#' To observe the effect of such a preprocessing, [`materialize()`] can be used. #' #' @param dataset ([`torch::dataset`])\cr #' The torch dataset. -#' @param dataset_shapes (named `list()` of `integer()`s)\cr +#' @param dataset_shapes (named `list()` of (`integer()` or `NULL`))\cr #' The shapes of the output. #' Names are the elements of the list returned by the dataset. -#' First dimension must be `NA`. +#' If the shape is not `NULL` (unknown, e.g. for images of different sizes) the first dimension must be `NA` to +#' indicate the batch dimension. #' @param graph ([`Graph`])\cr #' The preprocessing graph. #' If left `NULL`, no preprocessing is applied to the data and `.input_map`, `.pointer` and `.pointer_shape` @@ -23,9 +25,7 @@ #' Indicating an element on which a model is. Points to an output channel within `graph`: #' Element 1 is the `PipeOp`'s id and element 2 is that `PipeOp`'s output channel. #' @param .pointer_shape (`integer` | `NULL`)\cr -#' Shape of the output indicated by `.pointer`. Note that this is **without** the batch dimension as opposed -#' to the [`ModelDescriptor`]. The reason is that the .pointer_shape refers to exactly one element and hence -#' has no batch dimension. +#' Shape of the output indicated by `.pointer`. #' @param clone_graph (`logical(1)`)\cr #' Whether to clone the preprocessing graph. #' @param .pointer_shape_predict (`integer()` or `NULL`)\cr @@ -80,10 +80,7 @@ DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NU .pointer = c(graph$output$op.id, graph$output$channel.name) .pointer_shape = dataset_shapes[[.input_map]] } else { - graph = as_graph(graph) - if (clone_graph) { - graph = graph$clone(deep = TRUE) - } + graph = as_graph(graph, clone = clone_graph) assert_true(length(graph$pipeops) >= 1L) if (any(is.null(.input_map), is.null(.pointer), is.null(.pointer_shape))) { @@ -99,6 +96,9 @@ DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NU assert_true(length(.input_map) == length(graph$input$name)) } + # We hash the address of the environment, because the hashes of an environment are not stable, + # even with a .dataset (that should usually not really have a state), hashes might change due to byte-code + # compilation dataset_hash = calculate_hash(address(dataset)) obj = structure( @@ -166,6 +166,9 @@ new_lazy_tensor = function(data_descriptor, ids) { # was a simple integer vector. (this caused stuff like PipeOpFeatureUnion to go havock and lead to bugs) # For this reason, we now also include the hash of the data_descriptor # We can then later also use this to support different DataDescriptors in a single lazy tensor column + + # Note that we just include the hash as an attribute, so c() does not allow to combine lazy tensors whose + # data descriptors have different hashes. vctrs::new_vctr(map(ids, function(id) list(id, data_descriptor)), hash = data_descriptor$.hash, class = "lazy_tensor") } @@ -256,6 +259,7 @@ is_lazy_tensor = function(x) { #' @param pipeop ([`PipeOpModule`])\cr #' The pipeop to be added to the preprocessing graph(s) of the lazy tensor. #' Must have one input and one output. +#' Is not cloned, so should be cloned beforehand. #' @param shape (`integer()`)\cr #' The shape of the lazy tensor. #' @param shape_predict (`integer()`)\cr @@ -299,7 +303,7 @@ transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { data_descriptor$graph = data_descriptor$graph$clone(deep = FALSE) data_descriptor$graph$edges = copy(data_descriptor$graph$edges) - data_descriptor$graph$add_pipeop(pipeop$clone(deep = TRUE)) + data_descriptor$graph$add_pipeop(pipeop, clone = FALSE) data_descriptor$graph$add_edge( src_id = data_descriptor$.pointer[1L], src_channel = data_descriptor$.pointer[2L], diff --git a/R/learner_torch_methods.R b/R/learner_torch_methods.R index 96a516da..a37ae29b 100644 --- a/R/learner_torch_methods.R +++ b/R/learner_torch_methods.R @@ -41,9 +41,6 @@ learner_torch_train = function(self, private, super, task, param_vals) { # Here, all param_vals (like seed = "random" or device = "auto") have already been resolved loader_train = private$.dataloader(task, param_vals) - task_valid = task$clone()$filter(integer(0)) - task_valid$set_row_roles(task$row_roles$test, "use") - loader_valid = if (task_valid$nrow) private$.dataloader_predict(task_valid, param_vals) network = private$.network(task, param_vals)$to(device = param_vals$device) optimizer = private$.optimizer$generate(network$parameters) @@ -52,6 +49,17 @@ learner_torch_train = function(self, private, super, task, param_vals) { measures_train = normalize_to_list(param_vals$measures_train) measures_valid = normalize_to_list(param_vals$measures_valid) + task_valid = task$clone()$filter(integer(0)) + task_valid$set_row_roles(task$row_roles$test, "use") + loader_valid = if (task_valid$nrow) { + private$.dataloader_predict(task_valid, param_vals) + } else { + if (length(measures_valid)) { + lg$warn("No validation set provided but measures for validation set specified.") + } + NULL + } + available_predict_types = mlr_reflections$learner_predict_types[[self$task_type]][[self$predict_type]] walk(c(measures_train, measures_valid), function(m) { diff --git a/R/materialize.R b/R/materialize.R index beabfc84..284f7105 100644 --- a/R/materialize.R +++ b/R/materialize.R @@ -26,6 +26,7 @@ #' Either a [`lazy_tensor`] or a `list()` / `data.frame()` containing [`lazy_tensor`] columns. #' @param rbind (`logical(1)`)\cr #' Whether to rbind the lazy tensor columns (`TRUE`) or return them as a list of tensors (`FALSE`). +#' In the second case, the batch dimension is present for all individual tensors. #' @return (`list()` of [`lazy_tensor`]s or a [`lazy_tensor`]) #' @export #' @examples diff --git a/R/preprocess.R b/R/preprocess.R index 4a200a02..a8733bcc 100644 --- a/R/preprocess.R +++ b/R/preprocess.R @@ -2,6 +2,10 @@ #' @description #' Overview over all implemented preprocessing methods. #' See [`PipeOpTaskPreprocTorch`] for more details on the class itself. +#' +#' `PipeOps` preproessed with the `"augment_"` prefix, have their stages parameter initialize to `"train"`, while +#' those with the `"trafo_"` prefix have it set to `c("train", "predict")`. +#' #' @usage NULL #' @format NULL #' @name mlr_pipeops_preproc_torch_overview @@ -9,143 +13,158 @@ #' @include PipeOpTaskPreprocTorch.R NULL - -#' @name PipeOpPreprocTorchTrafoResize -#' @rdname mlr_pipeops_preproc_torch_overview -#' @description -#' * `trafo_resize`: Calls [`torchvision::transform_resize`] -register_preproc("trafo_resize", torchvision::transform_resize, - packages = "torchvision", - param_set = ps( - size = p_uty(tags = c("train", "required")), - interpolation = p_fct(levels = magick::filter_types(), special_vals = list(0L, 2L, 3L), - tags = "train", default = 2L - ) - ), - shapes_out = function(shapes_in, param_vals, task) { - size = param_vals$size - shape = shapes_in[[1L]] - assert_true(length(shape) > 2) - height = shape[[length(shape) - 1L]] - width = shape[[length(shape)]] - s = torchvision::transform_resize(torch_ones(c(1, height, width), device = "meta"), size = size)$shape[2:3] - list(c(shape[seq_len(length(shape) - 2L)], s)) - } -) - -#' @name PipeOpPreprocTorchTrafoNop -#' @rdname mlr_pipeops_preproc_torch_overview -#' @description -#' * `trafo_nop`: Calls `identity()`. -register_preproc("trafo_nop", identity, shapes_out = NULL) - - - -## Preprocessing: +##' @name PipeOpPreprocTorchTrafoResize +##' @rdname mlr_pipeops_preproc_torch_overview +##' @description +##' * `trafo_resize`: Calls [`torchvision::transform_resize`] +#register_preproc("trafo_resize", torchvision::transform_resize, +# packages = "torchvision", +# param_set = ps( +# size = p_uty(tags = c("train", "required")), +# interpolation = p_fct(levels = magick::filter_types(), special_vals = list(0L, 2L, 3L), +# tags = "train", default = 2L +# ) +# ), +# shapes_out = function(shapes_in, param_vals, task) { +# size = param_vals$size +# shape = shapes_in[[1L]] +# assert_true(length(shape) > 2) +# height = shape[[length(shape) - 1L]] +# width = shape[[length(shape)]] +# s = torchvision::transform_resize(torch_ones(c(1, height, width), device = "meta"), size = size)$shape[2:3] +# list(c(shape[seq_len(length(shape) - 2L)], s)) +# } +#) +# +##' @name PipeOpPreprocTorchTrafoNop +##' @rdname mlr_pipeops_preproc_torch_overview +##' @description +##' * `trafo_nop`: Calls `identity()`. +#register_preproc("trafo_nop", identity, shapes_out = NULL) # ##' @name PipeOpPreprocTorchAdjustGamma ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("adjust_gamma", torchvision::transform_adjust_gamma, packages = "torchvision" -#) +#register_preproc("trafo_adjust_gamma", torchvision::transform_adjust_gamma, packages = "torchvision", shapes_out = NULL) # nolint # ##' @name PipeOpPreprocTorchAdjustBrightness ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("adjust_brightness", torchvision::transform_adjust_brightness, packages = "torchvision") +#register_preproc("trafo_adjust_brightness", torchvision::transform_adjust_brightness, packages = "torchvision") # nolint # ##' @name PipeOpPreprocTorchAdjustHue ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("adjust_hue", torchvision::transform_adjust_hue, packages = "torchvision") +#register_preproc("trafo_adjust_hue", torchvision::transform_adjust_hue, packages = "torchvision", shapes_out = "infer") +# # ##' @name PipeOpPreprocTorchRandomCrop ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("random_crop", torchvision::transform_random_crop, packages = "torchvision", -# shapes_out = TRUE -#) +#register_preproc("augment_random_crop", torchvision::transform_random_crop, packages = "torchvision", shapes_out = NULL) # ##' @name PipeOpPreprocTorchAdjustSaturation ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("adjust_saturation", torchvision::transform_adjust_saturation, packages = "torchvision") +#register_preproc("trafo_adjust_saturation", torchvision::transform_adjust_saturation, packages = "torchvision", shapes_out = "infer") # nolint # ##' @name PipeOpPreprocTorchGrayscale ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("grayscale", torchvision::transform_grayscale, packages = "torchvision") -##' @name PipeOpPreprocTorchRgdToGrayscale +#register_preproc("grayscale", torchvision::transform_grayscale, packages = "torchvision", shapes_out = "unchanged") # nolint +# +##' @name PipeOpPreprocTorchRgbToGrayscale ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("rgb_to_grayscale", torchvision::transform_rgb_to_grayscale, packages = "torchvision") +#register_preproc("rgb_to_grayscale", torchvision::transform_rgb_to_grayscale, packages = "torchvision", shapes_out = "unchanged") # nolint # ##' @name PipeOpPreprocTorchNormalize ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("normalize", torchvision::transform_normalize, packages = "torchvision") +#register_preproc("trafo_normalize", torchvision::transform_normalize, packages = "torchvision", shapes_out = "unchanged") # nolint # ##' @name PipeOpPreprocTorchPad ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("pad", torchvision::transform_pad, packages = "torchvision") +#register_preproc("trafo_pad", torchvision::transform_pad, packages = "torchvision", shapes_out = "infer") # nolint # -## Data Augmentation: +# +## Data Augmentation # ##' @name PipeOpPreprocTorchResizedCrop ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("resized_crop", torchvision::transform_resized_crop, packages = "torchvision") +#register_preproc("augment_resized_crop", torchvision::transform_resized_crop, packages = "torchvision", shapes_out = "infer") # nolint +# +# ##' @name PipeOpPreprocTorchColorJitter ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("color_jitter", torchvision::transform_color_jitter, torchvision::transform_color_jitter, packages = "torchvision") +#register_preproc("augment_color_jitter", torchvision::transform_color_jitter, packages = "torchvision", shapes_out = "unchanged") # nolint +# ##' @name PipeOpPreprocTorchRandomResizedCrop ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("random_resized_crop", torchvision::transform_random_resized_crop, packages = "torchvision") -##' @name PipeOpPreprocTorchFiveCrop -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("five_crop", torchvision::transform_five_crop, packages = "torchvision") +#register_preproc("augment_random_resized_crop", torchvision::transform_random_resized_crop, packages = "torchvision", shapes_out = NULL) # nolint +# ##' @name PipeOpPreprocTorchRandomOrder ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("random_order", torchvision::transform_random_order, packages = "torchvision") +#register_preproc("augment_random_order", torchvision::transform_random_order, packages = "torchvision", shapes_out = NULL) # nolint +# ##' @name PipeOpPreprocTorchHflip ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("hflip", torchvision::transform_hflip, packages = "torchvision") +#register_preproc("augment_hflip", torchvision::transform_hflip, packages = "torchvision", shapes_out = "unchanged") # nolint +# ##' @name PipeOpPreprocTorchRandomRotation ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("random_rotation", torchvision::transform_random_rotation, packages = "torchvision") +#register_preproc("augment_random_rotation", torchvision::transform_random_rotation, packages = "torchvision", shapes_out = NULL) # nolint +# ##' @name PipeOpPreprocTorchRandomHorizontalFlip ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("random_horizontal_flip", torchvision::transform_random_horizontal_flip, packages = "torchvision") -##' @name PipeOpPreprocTorchLinerTransformation +#register_preproc("augment_random_horizontal_flip", torchvision::transform_random_horizontal_flip, packages = "torchvision", shapes_out = NULL) # nolint +# +##' @name PipeOpPreprocTorchLinaerTransformation ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("linear_transformation", torchvision::transform_linear_transformation, packages = "torchvision") +#register_preproc("augment_linear_transformation", torchvision::transform_linear_transformation, packages = "torchvision", shapes_out = "infer") # nolint +# ##' @name PipeOpPreprocTorchCrop ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("crop", torchvision::transform_crop, packages = "torchvision") -##' @name PipeOpPreprocTorchTenCrop -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("ten_crop", torchvision::transform_ten_crop, packages = "torchvision") +#register_preproc("augment_crop", torchvision::transform_crop, packages = "torchvision", shapes_out = "infer") # nolint +# ##' @name PipeOpPreprocTorchRandomVerticalFlip -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("random_vertical_flip", torchvision::transform_random_vertical_flip, packages = "torchvision") +##' @rdname "unchanged" +#register_preproc("random_vertical_flip", torchvision::transform_random_vertical_flip, packages = "torchvision", shapes_out = "unchanged") # nolint +# ##' @name PipeOpPreprocTorchRandomGrayscale ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("random_grayscale", torchvision::transform_random_grayscale, packages = "torchvision") +#register_preproc("random_grayscale", torchvision::transform_random_grayscale, packages = "torchvision", shapes_out = "unchanged") # nolint +# ##' @name PipeOpPreprocTorchRandomAffine ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("random_affine", torchvision::transform_random_affine, packages = "torchvision") +#register_preproc("augment_random_affine", torchvision::transform_random_affine, packages = "torchvision", shapes_out = NULL) # nolint +# ##' @name PipeOpPreprocTorchRandomPerspective ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("random_perspective", torchvision::transform_random_perspective, packages = "torchvision") +#register_preproc("augment_random_perspective", torchvision::transform_random_perspective, packages = "torchvision", shapes_out = NULL) # nolint +# ##' @name PipeOpPreprocTorchVflip ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("vflip", torchvision::transform_vflip, packages = "torchvision") +#register_preproc("augment_vflip", torchvision::transform_vflip, packages = "torchvision", shapes_out = "unchanged") # nolint +# ##' @name PipeOpPreprocTorchRandomErasing ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("random_erasing", torchvision::transform_random_erasing, packages = "torchvision") +#register_preproc("augment_random_erasing", torchvision::transform_random_erasing, packages = "torchvision", shapes_out = "infer") +# ##' @name PipeOpPreprocTorchPerspective ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("perspective", torchvision::transform_perspective, packages = "torchvision") +#register_preproc("augment_perspective", torchvision::transform_perspective, packages = "torchvision", shapes_out = "infer") # nolint +# ##' @name PipeOpPreprocTorchRandomApply ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("random_apply", torchvision::transform_random_apply, packages = "torchvision") +#register_preproc("augment_random_apply", torchvision::transform_random_apply, packages = "torchvision", shapes_out = NULL) # nolint +# ##' @name PipeOpPreprocTorchRotate ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("rotate", torchvision::transform_rotate, packages = "torchvision") +#register_preproc("augment_rotate", torchvision::transform_rotate, packages = "torchvision", shapes_out = "infer") # nolint +# ##' @name PipeOpPreprocTorchCenterCrop ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("center_crop", torchvision::transform_center_crop, packages = "torchvision") +#register_preproc("augment_center_crop", torchvision::transform_center_crop, packages = "torchvision", shapes_out = "infer") # nolint +# ##' @name PipeOpPreprocTorchRandomChoice ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("random_choice", torchvision::transform_random_choice, packages = "torchvision") +#register_preproc("augment_random_choice", torchvision::transform_random_choice, packages = "torchvision", shapes_out = NULL) # nolint +# +# +##' @name PipeOpPreprocTorchRandomCrop +##' @rdname mlr_pipeops_preproc_torch_overview +#register_preproc("augment_random_crop", torchvision::transform_random_crop, packages = "torchvision", shapes_out = NULL) # nolint +# diff --git a/R/shape.R b/R/shape.R index be2bc6f1..d8911956 100644 --- a/R/shape.R +++ b/R/shape.R @@ -6,14 +6,16 @@ #' @param shape (`integer()`)\cr #' @param null_ok (`logical(1)`)\cr #' Whether `NULL` is a valid shape. -assert_shape = function(shape, null_ok = FALSE) { +#' @param coerce (`logical(1)`)\cr +#' Whether to coerce the input to an `integer()` if possible. +assert_shape = function(shape, null_ok = FALSE, coerce = TRUE) { if (!test_shape(shape, null_ok = null_ok)) { - stopf("Invalid shape.") + stopf("Invalid shape: %s.", paste0(format(shape), collapse = ", ")) } - if (is.null(shape)) { - return(NULL) + if (coerce && !is.null(shape)) { + return(as.integer(shape)) } - return(as.integer(shape)) + shape } test_shape = function(shape, null_ok = FALSE) { @@ -27,7 +29,7 @@ test_shape = function(shape, null_ok = FALSE) { } is_na = is.na(shape) - if (!is_na[[1L]] || anyNA(shape[-1L])) { + if (anyNA(shape[-1L])) { return(FALSE) } return(TRUE) diff --git a/R/zzz.R b/R/zzz.R index 75be0637..201011e9 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -130,33 +130,6 @@ register_mlr3pipelines = function() { if (Sys.getenv("IN_PKGDOWN") == "true") { lg$set_threshold("warn") } - - if (Sys.getenv("DEVTOOLS_LOAD", unset = "") == "mlr3torch") { - # When loading mlr3torch with devtools, we always get a warning when hashing lazy tensors. - # mlr3misc's calculate_hash function calls digest::digest which in turn serializes objects. - # When mlr3torch is loaded with devtools the `$initialize()` method of the dataset that underpins the lazy tensor - # behaves differently than when loaded with library() and always throws the warning: - # "package:mlr3torch" might not be avaiable when loading. - # - # Because this is quite annoying, we here suppress warnings that arise from the calculate_hash function. - - suppress = function(name, fn, env) { - fn = mlr3misc::crate(function(...) { - suppressWarnings(fn(...)) - }, .parent = parent.env(environment(fn)), fn) - - unlockBinding(name, env) - assign(name, fn, envir = env) - lockBinding(name, env) - } - - suppress("calculate_hash", mlr3misc::calculate_hash, parent.env(getNamespace("mlr3torch"))) - - suppress("calculate_hash", mlr3misc::calculate_hash, parent.env(getNamespace("mlr3"))) - suppress("calculate_hash", mlr3misc::calculate_hash, parent.env(getNamespace("mlr3pipelines"))) - suppress("digest", digest::digest, parent.env(getNamespace("mlr3pipelines"))) - } - } .onUnload = function(libPaths) { # nolint diff --git a/inst/col_info/mnist.rds b/inst/col_info/mnist.rds index f0f375d4329dbdbc56c5822f4977d77e426ce598..6f307c5040d1467abed8e2f6404c6819f18fda75 100644 GIT binary patch literal 276 zcmV+v0qg!BiwFP!000001D%oGN&_(vg{S+cT@jRmZ(;D?`T{e8-oNh%!9$*Bk%XE`Z9upQHqe3VBH-?uZSF09q6T3qlS1u)sA0DQ$Uq}FlO=tALA z;Y#6J;YQ(B;ZEURVXE*DcgUhqFa_3wu}9m9mkle`>~KXPR^`#me%e&eB@b>z0HHp!9mjF1AyNYYnC+!NCqygiM zI0Yxh`1R-1E;Jc7Y$Yo{W&GMsggDD?BJXDm*Dn6rK-WDUw(T1<}UDqjga$`r9fxTv13>WfF`1Fe=$@bZSGU58{v+ zjN}} \describe{ -\item{\code{params}}{(named \code{list()} of \code{\link{torch_tensor}})\cr +\item{\code{params}}{(named \code{list()} of \code{\link{torch_tensor}}s)\cr The parameters of the network.} } \if{html}{\out{}} diff --git a/man/materialize.Rd b/man/materialize.Rd index de791b89..303d52dc 100644 --- a/man/materialize.Rd +++ b/man/materialize.Rd @@ -15,7 +15,8 @@ The object to materialize. Either a \code{\link{lazy_tensor}} or a \code{list()} / \code{data.frame()} containing \code{\link{lazy_tensor}} columns.} \item{rbind}{(\code{logical(1)})\cr -Whether to rbind the lazy tensor columns (\code{TRUE}) or return them as a list of tensors (\code{FALSE}).} +Whether to rbind the lazy tensor columns (\code{TRUE}) or return them as a list of tensors (\code{FALSE}). +In the second case, the batch dimension is present for all individual tensors.} \item{cache}{(\code{character(1)} or \code{environment()} or \code{NULL})\cr Optional cache for (intermediate) materialization results. diff --git a/man/mlr_backends_lazy.Rd b/man/mlr_backends_lazy.Rd index 6fe50d79..1a8fe0cc 100644 --- a/man/mlr_backends_lazy.Rd +++ b/man/mlr_backends_lazy.Rd @@ -26,7 +26,7 @@ Information that is available before the backend is constructed is: Beware that accessing the backend's hash also contructs the backend. Note that while in most cases the data contains \code{\link{lazy_tensor}} columns, this is not necessary and the naming -of backend has nothing to do with the \code{\link{lazy_tensor}} datatype. +of this class has nothing to do with the \code{\link{lazy_tensor}} datatype. } \examples{ # We first define a backend constructor diff --git a/man/mlr_pipeops_module.Rd b/man/mlr_pipeops_module.Rd index 9361a48d..7a33da46 100644 --- a/man/mlr_pipeops_module.Rd +++ b/man/mlr_pipeops_module.Rd @@ -84,7 +84,7 @@ linear_module formalArgs(linear_module$module) linear_module$input$name - +Constructing a PipeOpModule using a simple function po_add1 = po("module", id = "add_one", module = function(x) x + 1 @@ -130,7 +130,6 @@ The torch module that is called during the training phase.} \subsection{Public methods}{ \itemize{ \item \href{#method-PipeOpModule-new}{\code{PipeOpModule$new()}} -\item \href{#method-PipeOpModule-clone}{\code{PipeOpModule$clone()}} } } \if{html}{\out{ @@ -184,21 +183,4 @@ The R packages this object depends on.} \if{html}{\out{}} } } -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpModule-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpModule$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} } diff --git a/man/mlr_pipeops_preproc_torch.Rd b/man/mlr_pipeops_preproc_torch.Rd index 0255b33f..0ef44712 100644 --- a/man/mlr_pipeops_preproc_torch.Rd +++ b/man/mlr_pipeops_preproc_torch.Rd @@ -3,49 +3,29 @@ \name{mlr_pipeops_preproc_torch} \alias{mlr_pipeops_preproc_torch} \alias{PipeOpTaskPreprocTorch} -\title{Base Class for Torch Preprocessing} +\title{Base Class for Lazy Tensor Preprocessing} \description{ This \code{PipeOp} can be used to preprocess (one or more) \code{\link{lazy_tensor}} columns contained in an \code{\link[mlr3:Task]{mlr3::Task}}. The preprocessing function is specified as construction argument \code{fn} and additional arguments to this function can be defined through the \code{PipeOp}'s parameter set. -The preprocessing is usually done per-column in which case the number lazy tensor output columns is equivalent +The preprocessing is done per column, i.e. the number of lazy tensor output columns is equal to the number of lazy tensor input columns. -It is also possible to implement preprocessing that is applied to all lazy tensor columns at once and returns -one or more (not necessarily the same number of) lazy tensor columns. -The preprocessing that is applied during \verb{$predict()} uses the parameters that were set during \verb{$train()} -and not those that are set when performing the prediction. + +To create custom preprocessing \code{PipeOp}s you can use \code{\link{pipeop_preproc_torch}} / \code{\link{pipeop_preproc_torch_class}}. } \section{Inheriting}{ -In addition to specifying the construction arguments, you can overwrite the private \code{.shapes_out()} or -\code{.tranform()} methods: +In addition to specifying the construction arguments, you can overwrite the private \code{.shapes_out()} method: \itemize{ \item \code{.shapes_out(shapes_in, param_vals, task)}\cr -(\code{list()}, \verb{list(), }Task\code{or}NULL\verb{) -> }list()`\cr -This private method calculates the output shapes of the lazy tensor columns that are created from applying -the preprocessing. +(\code{list()}, \verb{list(), }Task\code{or}NULL\verb{) -> }list()\verb{\\cr This private method calculates the output shapes of the lazy tensor columns that are created from applying the preprocessing function with the provided parameter values (}param_vals\verb{). The }task\verb{is very rarely needed, but if it is it should be checked that it is not}NULL`. This private method only has the responsibility to calculate the output shapes for one input column, i.e. the -input \code{shapes_in} can be assumed to have -exactly one shape vector for which it must calculate the output shapes and return it as a \code{list()} of length 1. -It can also be assumed, that the shape is not \code{NULL}. -It should also output a shape with exactly one NA in the first dimension. -It is also possible to output \code{NULL}, if the output shape cannot be determined (e.g. because it is random). - -Also see the documentation of \code{\link{PipeOpTorch}} how to implement this method. -\item \code{.transform(dt, task, param_vals, stage)}\cr -(\code{data.table()}, \code{Task}, \code{list()}, \code{character(1)}) -> \code{data.table()}\cr -This method must only be overwritten when the the \code{per_column} construction argument is \code{FALSE}. -It receives as inputs all selected lazy tensor columns, the input \code{Task} (already cloned), -the paramer values, and whether the preprocessing is applied during training (stage is \code{"train"}) -or prediction (stage is \code{"predict"}). One should not work with the parameters currently set in the paramet set, -only use those passed as argument \code{param_vals}. These are the parameters that were specified during the \verb{$train()} -call of the \code{\link{PipeOp}} (otherwise it cannot be ensured that the shapes encountered during \verb{$predict()} can actuallT -be processed by the neural network). -The method must return a \code{data.table} with lazy tensor columns. -The lazy tensor input columns should \strong{not} be modified in-place. -Overwriting this method (currently) requires a solid understanding of the \code{\link{lazy_tensor}} internals. -You also need to pay attention to avoid name conflicts with existing columns in the task. +input \code{shapes_in} can be assumed to have exactly one shape vector for which it must calculate the output shapes +and return it as a \code{list()} of length 1. +It can also be assumed that the shape is not \code{NULL} (i.e. unknown). +It should output a shape with exactly one NA in the first (batch) dimension or \code{NULL}if the output shape cannot be +determined (e.g. because it is random). } } @@ -69,15 +49,23 @@ as the argument \code{param_set} there are the following parameters: Whether the to apply the preprocessing only during training (\code{TRUE}) or also during prediction (\code{FALSE}). This parameter is initialized to \code{FALSE}. } + +Note that the preprocessing that is applied during \verb{$predict()} uses the parameters that were set during +\verb{$train()} and not those that are set when performing the prediction. } \section{Internals}{ A \code{\link{PipeOpModule}} with one input and one output channel is created. The pipeop simply applies the function \code{fn} to the input tensor while additionally -passing the paramter values (minus \code{augment} and \code{affect_columns}) to \code{fn}. -Then \code{\link{transform_lazy_tensor}} is called with the created \code{\link{PipeOpModule}} and the shapes obtained from the -\verb{$shapes_out()} method of this \code{PipeOp}. +passing the parameter values (minus \code{augment} and \code{affect_columns}) to \code{fn}. +In addition, the new shapes are calculates using the \verb{$shapes_out()} method. +Then, new lazy tensor columns with updated preprocessing graphs and metadata are created. +This mechanism is very similar to the \code{\link{ModelDescriptor}} mechanism that is being used to construct +neural network architectures. Read the (Internals) documentation of \code{\link{PipeOpTorch}} for this. + +We also add the shape that would be present during a \verb{$predict()} call, this information can later be used +to check whether the train-preprocessing and the predict-preprocessing are compatible. } \examples{ @@ -217,18 +205,15 @@ The id for of the new object.} Parameter values to be set after construction.} \item{\code{param_set}}{(\code{\link{ParamSet}})\cr -In case the function \code{fn} takes additional parameter besides a \code{\link[=torch_tensor]{torch_tensor()}} they can be +In case the function \code{fn} takes additional parameter besides a \code{\link{torch_tensor}} they can be specfied as parameters. None of the parameters can have the \code{\link{"predict"}} tag. -Pay attention to set the correct \code{tags} for the parameters: if tag \code{"train"} is present, -the preprocessing is applied during training and if tag \code{"predict"} is present, the preprocessing is applied -during prediction (if \code{augment} is set to \code{FALSE}).} +All tags should be set to \code{"train"}.} \item{\code{packages}}{(\code{character()})\cr The packages the preprocessing function depends on.} -\item{\code{augment_init}}{(\code{logical(1)} or \code{NULL})\cr -Initial value for the \code{augment} parameter. -If it is \code{NULL}, there is no \code{augment} parameter.} +\item{\code{augment_init}}{(\code{logical(1)})\cr +Initial value for the \code{augment} parameter.} } \if{html}{\out{}} } diff --git a/man/mlr_tasks_tiny_imagenet.Rd b/man/mlr_tasks_tiny_imagenet.Rd index 83f7be96..7a99bd6c 100644 --- a/man/mlr_tasks_tiny_imagenet.Rd +++ b/man/mlr_tasks_tiny_imagenet.Rd @@ -34,6 +34,10 @@ indicates whether the row belongs to the train, validation or test set. } } +\examples{ +task = tsk("tiny_imagenet") +task +} \references{ Deng, Jia, Dong, Wei, Socher, Richard, Li, Li-Jia, Li, Kai, Fei-Fei, Li (2009). \dQuote{Imagenet: A large-scale hierarchical image database.} diff --git a/man/pipeop_preproc_torch.Rd b/man/pipeop_preproc_torch.Rd index a0291eb0..eeeb815e 100644 --- a/man/pipeop_preproc_torch.Rd +++ b/man/pipeop_preproc_torch.Rd @@ -21,14 +21,14 @@ The id for of the new object.} The preprocessing function.} \item{shapes_out}{(\code{function} or \code{NULL} or "infer")\cr -The private \code{.shapes_out(shapes_in, param_vals, task)} method of \code{\link{PipeOpTaskPreprocTorch}}. +The private \code{.shapes_out(shapes_in, param_vals, task)} method of \code{\link{PipeOpTaskPreprocTorch}} +(see section Inheriting). If \code{NULL}, the pipeop does not change the output shapes. If \code{TRUE}, the output shape function is inferred and calculates the output shapes as follows: -a) The input shapes are known: For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. -b) The input shapes are unknown (all NA): -The dimension is returned as is.} + +This should be correct in most cases, but might fail in some edge cases.} \item{param_set}{(\code{\link{ParamSet}} or \code{NULL})\cr The parameter set. diff --git a/man/pipeop_preproc_torch_class.Rd b/man/pipeop_preproc_torch_class.Rd index da125330..f3039f01 100644 --- a/man/pipeop_preproc_torch_class.Rd +++ b/man/pipeop_preproc_torch_class.Rd @@ -20,14 +20,14 @@ The id for of the new object.} The preprocessing function.} \item{shapes_out}{(\code{function} or \code{NULL} or "infer")\cr -The private \code{.shapes_out(shapes_in, param_vals, task)} method of \code{\link{PipeOpTaskPreprocTorch}}. +The private \code{.shapes_out(shapes_in, param_vals, task)} method of \code{\link{PipeOpTaskPreprocTorch}} +(see section Inheriting). If \code{NULL}, the pipeop does not change the output shapes. If \code{TRUE}, the output shape function is inferred and calculates the output shapes as follows: -a) The input shapes are known: For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. -b) The input shapes are unknown (all NA): -The dimension is returned as is.} + +This should be correct in most cases, but might fail in some edge cases.} \item{param_set}{(\code{\link{ParamSet}} or \code{NULL})\cr The parameter set. @@ -46,7 +46,7 @@ Parameter values to be set after construction.} An \code{\link[R6:R6Class]{R6Class}} instance inheriting from \code{\link{PipeOpTaskPreprocTorch}} } \description{ -Convenience functions to create objects of class \code{\link{PipeOpTaskPreprocTorch}} in a slightly more convenient way. +Function to create objects of class \code{\link{PipeOpTaskPreprocTorch}} in a slightly more convenient way. Start by reading the documentation of \code{\link{PipeOpTaskPreprocTorch}}. } \examples{ diff --git a/tests/testthat/helper_autotest.R b/tests/testthat/helper_autotest.R index 6f663e39..266ebe44 100644 --- a/tests/testthat/helper_autotest.R +++ b/tests/testthat/helper_autotest.R @@ -92,7 +92,6 @@ autotest_pipeop_torch = function(graph, id, task, module_class = id, exclude_arg batch = ds$.getbatch(1) out = with_no_grad(invoke(net$forward, .args = batch$x)) - # TODO: Make this better understandable tmp = net$graph$output # outnamein are the output nodes that contain the tensors that are the input to the pipeop we are testing outnamein = tmp[get("op.id") != id, c("op.id", "channel.name")] @@ -169,7 +168,7 @@ collapse_char_list = function(x) { #' @title Parameter Test #' @description #' Tests that parameters are correctly implemented -#' +#'k #' @param x ([`ParamSet`] or object with field `$param_set`)\cr #' The parameter set to check. #' @param fns (`list()` of `function`s)\cr @@ -311,16 +310,52 @@ autotest_torch_callback = function(torch_callback, check_man = TRUE) { expect_error(cb_trained$clone(deep = TRUE), "must never be cloned unless") } -autotest_pipeop_torch_preprocess = function() { - # TODO: +#' @title Autotest for PipeOpTaskPreprocTorch +#' @description +#' Performs various sanity checks on a [`PipeOpTaskPreprocTorch`]. +#' @param obj ([`PipeOpTaskPreprocTorch`])\cr +#' The object to test. +#' @parm tnsr_in (`integer()`)\cr +autotest_pipeop_torch_preprocess = function(obj, shapes_in, exclude = character(0), exclude_defaults = character(0)) { + expect_pipeop(obj) expect_class(obj, "PipeOpTaskPreprocTorch") - # a) Check that all parameters but augment have tags train and predict (this should hold in basically all cases) + # a) Check that all parameters but stages have tags train and predict (this should hold in basically all cases) + # parameters must only ce active during training + walk(obj$param_set$params, function(p) { + if (!(("train" %in% p$tags) && !("predict" %in% p$tags))) { + stopf("Parameters of PipeOps inheriting from PipeOpTorch must only be active during training.") + } + }) + autotest_paramset(obj$param_set, obj$fn, exclude = exclude, exclude_defaults = exclude_defaults) # b) Check that the shape prediction is compatible (already done in autotest for pipeop torch) - # c) check that start with augment / trafo, depending on the initial value - #walk(po_test$param_set$params, function(p) { - # if (!(("train" %in% p$tags) && !("predict" %in% p$tags))) { - # stopf("Parameters of PipeOps inheriting from PipeOpTorch must only be active during training.") - # } - #}) + # c) check that start with stages / trafo, depending on the initial value + class = get(class(obj)[[1L]], envir = getNamespace("mlr3torch")) + instance = class$new() + + expect_true(grepl(instance$id, pattern = "^(trafo|augment)_")) + if (startsWith(instance$id, "augment")) { + expect_set_equal(instance$param_set$values$stages, "train") + } else { + expect_set_equal(instance$param_set$values$stages, c("train", "predict")) + } + + shapes_in = if (!test_list(shapes_in)) list(shapes_in) else shapes_in + + walk(shapes_in, function(shape_in) { + tnsr_in = torch_empty(shape_in) + shape_out = obj$shapes_out(list(shape_in), stage = "train")[[1L]] + taskin = as_task_regr(data.table( + y = rep(1, nrow(tnsr_in)), + x = as_lazy_tensor(tnsr_in) + ), target = "y") + + taskout = obj$train(list(taskin))[[1L]] + + tnsr_out = materialize(taskout$data(cols = "x")[[1L]], rbind = TRUE) + + expect_class(tnsr_out, "torch_tensor") + + expect_equal(tnsr_out$shape, shape_out) + }) } diff --git a/tests/testthat/helper_functions.R b/tests/testthat/helper_functions.R index 856969da..168e28c2 100644 --- a/tests/testthat/helper_functions.R +++ b/tests/testthat/helper_functions.R @@ -247,7 +247,7 @@ random_dataset = dataset("random_dataset", self$x = torch_randn(n, ...) }, .getbatch = function(i) { - list(x = self$x[i, ..,]) + list(x = self$x[i, .., drop = FALSE]) }, .length = function() { nrow(self$x) diff --git a/tests/testthat/test_LearnerTorch.R b/tests/testthat/test_LearnerTorch.R index 006896e0..89a964c5 100644 --- a/tests/testthat/test_LearnerTorch.R +++ b/tests/testthat/test_LearnerTorch.R @@ -383,8 +383,8 @@ test_that("resample() works", { test_that("Input verification works during `$train()` (train-predict shapes work together)", { task = nano_mnist() - task_invalid = po("trafo_resize", size = c(10, 10), augment = TRUE) $train(list(task))[[1L]] - task_valid = po("trafo_resize", size = c(10, 10), augment = FALSE) $train(list(task))[[1L]] + task_invalid = po("trafo_resize", size = c(10, 10), stages = "train") $train(list(task))[[1L]] + task_valid = po("trafo_resize", size = c(10, 10), stages = c("train", "predict")) $train(list(task))[[1L]] learner = lrn("classif.torch_featureless", batch_size = 1L, epochs = 0L @@ -402,7 +402,7 @@ test_that("Input verification works during `$train()` (train-predict shapes work NA ) - task_unknown = po("trafo_resize", size = c(10, 10), augment = TRUE) $train(list(nano_dogs_vs_cats()))[[1L]] + task_unknown = po("trafo_resize", size = c(10, 10), stages = "train") $train(list(nano_dogs_vs_cats()))[[1L]] expect_error( learner$train(task_unknown), diff --git a/tests/testthat/test_PipeOpTaskPreprocTorch.R b/tests/testthat/test_PipeOpTaskPreprocTorch.R index e560f831..181a3c9c 100644 --- a/tests/testthat/test_PipeOpTaskPreprocTorch.R +++ b/tests/testthat/test_PipeOpTaskPreprocTorch.R @@ -6,7 +6,7 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { expect_true(po_test$outnum == 1L) expect_class(po_test, "PipeOpTaskPreproc") expect_true("R6" %in% po_test$packages) - expect_set_equal(po_test$param_set$ids(), c("augment", "affect_columns")) + expect_set_equal(po_test$param_set$ids(), c("stages", "affect_columns")) expect_error(po("preproc_torch"), "is missing") PipeOpTaskPreprocTorchTest = R6Class("PipeOpTaskPreprocTorchTest", @@ -27,7 +27,7 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { ) po_test1 = PipeOpTaskPreprocTorchTest$new(id = "test1") - expect_true("augment" %in% po_test1$param_set$ids()) + expect_true("stages" %in% po_test1$param_set$ids()) shapes_in = list(c(NA, 1), c(NA, 1)) expect_identical(shapes_in, po_test1$shapes_out(shapes_in, stage = "train")) @@ -82,20 +82,32 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { torch_sum(materialize(po_test2$predict(list(task))[[1L]]$data(cols = "x1")[[1L]], rbind = TRUE))$item() == 0 ) - # augment parameter works as intended (above augment was FALSE) + # stages parameter works as intended (above stages was set to c("train", "predict")) po_test2$param_set$set_values( - augment = TRUE + stages = "train" ) - # augment is TRUE, but a is tagged "train" --> does not change the results + # stages is c("train", "predict"), but a is tagged "train" --> does not change the results expect_true( torch_sum(materialize(po_test2$predict(list(task))[[1L]]$data(cols = "x1")[[1L]], rbind = TRUE))$item() == 0 ) - # only if we re-train the augmentation is applied + # only if we re-train the transformatoin is applied during predict po_test2$train(list(task)) expect_true( torch_sum(materialize(po_test2$predict(list(task))[[1L]]$data(cols = "x1")[[1L]], rbind = TRUE))$item() == sum(1:10) ) + + # when stages is set to "predict", it onlu applied during prediction + po_test$param_set$set_values(stages = "predict") + expect_torch_equal( + materialize(task$data(cols = "x1")[[1L]], rbind = TRUE), + materialize(po_test$train(list(task))[[1L]]$data(cols = "x1")[[1L]], rbind = TRUE) + + ) + expet_identical) + u + materialie(task$data(cols = "x1")[[1L]] + }) test_that("PipeOptaskPreprocTorch: shapes_out() works", { @@ -105,14 +117,14 @@ test_that("PipeOptaskPreprocTorch: shapes_out() works", { expect_identical(po_resize$shapes_out(list(x = NULL, y = c(NA, 3, 5, 5)), stage = "train"), list(NULL, c(NA, 3, 10, 10))) expect_error(po_resize$shapes_out(list(x = c(NA, 1, 3)), stage = "predict"), "can only be calculated") - # predict when augment is TRUE - po_resize$param_set$set_values(augment = TRUE) + # predict when stages is "train" + po_resize$param_set$set_values(stages = "train") po_resize$train(list(task)) expect_identical(po_resize$shapes_out(list(x = NULL), stage = "predict"), list(NULL)) expect_identical(po_resize$shapes_out(list(x = NULL, y = c(NA, 3, 5, 5)), stage = "predict"), list(NULL, c(NA, 3, 5, 5))) - # predict when augment is FALSE - po_resize$param_set$set_values(augment = FALSE) + # predict when stages is c("train", "predict"") + po_resize$param_set$set_values(stages = c("train", "predict")) po_resize$train(list(task)) expect_identical(po_resize$shapes_out(list(x = NULL), stage = "predict"), list(NULL)) expect_identical(po_resize$shapes_out(list(x = NULL, y = c(NA, 3, 5, 5)), stage = "predict"), list(NULL, c(NA, 3, 10, 10))) @@ -131,7 +143,7 @@ test_that("PipeOpTaskPreprocTorch modifies the underlying lazy tensor columns co taskout_train = po_test$train(list(taskin))[[1L]] taskout_pred = po_test$predict(list(taskin))[[1L]] - po_test$param_set$set_values(augment = TRUE) + po_test$param_set$set_values(stages = "train") po_test$train(list(taskin))[[1L]] taskout_pred_aug = po_test$predict(list(taskin))[[1L]] @@ -152,7 +164,7 @@ test_that("PipeOpTaskPreprocTorch modifies the underlying lazy tensor columns co ) }) -test_that("pipeop_preproc_torch works", { +test_that("pipeop_preproc_torch", { expect_error( pipeop_preproc_torch("trafo_abc", function(x) NULL, shapes_out = function(shapes) NULL), "Must have formal arguments" @@ -170,7 +182,7 @@ test_that("pipeop_preproc_torch works", { expect_true("required" %in% po_test$param_set$tags$a) expect_class(po_test, "PipeOpPreprocTorchTrafoAbc") # parameter a was added - expect_set_equal(c("a", "affect_columns", "augment"), po_test$param_set$ids()) + expect_set_equal(c("a", "affect_columns", "stages"), po_test$param_set$ids()) task = as_task_regr(data.table( y = 2, diff --git a/tests/testthat/test_TaskClassif_lazy_iris.R b/tests/testthat/test_TaskClassif_lazy_iris.R index d8cb09f2..fea98f6b 100644 --- a/tests/testthat/test_TaskClassif_lazy_iris.R +++ b/tests/testthat/test_TaskClassif_lazy_iris.R @@ -1,3 +1,12 @@ test_that("tiny_imagenet task works", { task = tsk("lazy_iris") + expect_task(task) + expect_equal(task$id, "lazy_iris") + expect_equal(task$label, "Iris Flowers") + expect_equal(task$target_names, "Species") + expect_equal(task$feature_names, "x") + expect_equal(task$man, "mlr3torch::mlr_tasks_lazy_iris") + expect_equal(task$nrow, 150) + expect_equal(task$ncol, 2) }) + diff --git a/tests/testthat/test_TaskClassif_mnist.R b/tests/testthat/test_TaskClassif_mnist.R index c8c92e2e..2ac7ee4f 100644 --- a/tests/testthat/test_TaskClassif_mnist.R +++ b/tests/testthat/test_TaskClassif_mnist.R @@ -1,6 +1,16 @@ -test_that("tiny_imagenet task works", { - task = tsk("lazy_iris") - expect_task(task) - expect_equal(task$id == "lazy_iris") - expect_equal(task$man == "mlr3torch::mlr_tasks_lazy_iris") +skip_on_cran() + +test_that("mnist task works", { + withr::local_options(mlr3torch.cache = TRUE) + task = tsk("mnist") + expect_equal(task$row_roles$use, 1:60000) + expect_equal(task$row_roles$test, 60001:70000) + # this makes the test faster + task$row_roles$use = 1:10 + expect_equal(task$id, "mnist") + expect_equal(task$label, "MNIST Digit Classification") + expect_equal(task$feature_names, "image") + expect_equal(task$target_names, "label") + expect_equal(task$man, "mlr3torch::mlr_tasks_mnist") + expect_equal(task$properties, "multiclass") }) diff --git a/tests/testthat/test_TaskClassif_tiny_imagenet.R b/tests/testthat/test_TaskClassif_tiny_imagenet.R index 679e6864..3d4133ed 100644 --- a/tests/testthat/test_TaskClassif_tiny_imagenet.R +++ b/tests/testthat/test_TaskClassif_tiny_imagenet.R @@ -1,25 +1,21 @@ skip_on_cran() -test_that("tiny_imagenet task works", { +test_that("tiny_imagenet works", { withr::local_options(mlr3torch.cache = TRUE) task = tsk("tiny_imagenet") - dt = task$data() - - expect_true("tiny-imagenet-200" %in% list.files(file.path(get_cache_dir(), "datasets", "tiny_imagenet", "raw"))) - expect_true("data.rds" %in% list.files(file.path(get_cache_dir(), "datasets", "tiny_imagenet"))) - - - expect_equal(task$backend$nrow, 120000) - expect_equal(task$backend$ncol, 4) - expect_data_table(dt, ncols = 2, nrows = 100000) - expect_permutation(colnames(dt), c("class", "image")) - expect_class(task, "TaskClassif") expect_equal(length(task$row_roles$use), 100000) expect_equal(length(task$row_roles$test), 10000) expect_equal(length(task$row_roles$holdout), 10000) - expect_equal(task$feature_names, "image") - expect_equal(task$target_names, "class") - expect_equal(task$properties, "multiclass") + + # this makes the test faster + task$row_roles$use = 1:10 expect_equal(task$id, "tiny_imagenet") expect_equal(task$label, "ImageNet Subset") + expect_equal(task$feature_names, "image") + expect_equal(task$target_names, "class") + expect_equal(task$man, "mlr3torch::mlr_tasks_tiny_imagenet") + expect_true("tiny-imagenet-200" %in% list.files(file.path(get_cache_dir(), "datasets", "tiny_imagenet", "raw"))) + expect_true("data.rds" %in% list.files(file.path(get_cache_dir(), "datasets", "tiny_imagenet"))) + expect_equal(task$backend$nrow, 120000) + expect_equal(task$backend$ncol, 4) }) diff --git a/tests/testthat/test_autotests.R b/tests/testthat/test_autotests.R index 4141e19e..12b0771e 100644 --- a/tests/testthat/test_autotests.R +++ b/tests/testthat/test_autotests.R @@ -176,7 +176,18 @@ test_that("autotest_torch_callback works", { }) -test_that("autotest_pipeop_torch works", { +test_that("autotest_pipeop_torch", { # TODO: }) + +test_that("autotest_pipeop_torch_preproces", { + # test that: + # a) id * + + + + + autotest_pipeop_torch_preprocess + +}) diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index 96491384..a11916d5 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -74,6 +74,8 @@ test_that("lazy_tensor works", { expect_error(c(lt1, lt2), "attributes are incompatible") + expect_error({lt1[1] = lt2[1]}) # nolint + lt1_empty = lt1[integer(0)] expect_error(is.null(lt1_empty$data_descriptor)) expect_class(lt1_empty, "lazy_tensor") diff --git a/tests/testthat/test_nn_graph.R b/tests/testthat/test_nn_graph.R index 890a3c7d..6a0fe7ca 100644 --- a/tests/testthat/test_nn_graph.R +++ b/tests/testthat/test_nn_graph.R @@ -97,7 +97,7 @@ test_that("nn_graph can reset parameters", { } ) - network = nn_graph(as_graph(po("module", module = nn_lin())), + network = nn_graph(as_graph(po("module", module = nn_lin()), clone = FALSE), shapes_in = list(module.input = 1) ) diff --git a/tests/testthat/test_preprocess.R b/tests/testthat/test_preprocess.R new file mode 100644 index 00000000..11cb0c59 --- /dev/null +++ b/tests/testthat/test_preprocess.R @@ -0,0 +1,6 @@ +test_that("trafo_resize", { + autotest_pipeop_torch_preprocess( + obj = po("trafo_resize", size = c(3, 4)), + shapes_in = list(c(16, 10, 10, 4), c(3, 4, 8)) + ) +}) diff --git a/tests/testthat/test_shape.R b/tests/testthat/test_shape.R new file mode 100644 index 00000000..529571c3 --- /dev/null +++ b/tests/testthat/test_shape.R @@ -0,0 +1,11 @@ +test_that("assert_shape works", { + expect_error(assert_shape("1")) + expect_error(assert_shape(NULL, null_ok = FALSE)) + + expect_true(is.null(assert_shape(NULL, null_ok = TRUE))) + expect_integerish(assert_shape(c(1, 2))) + expect_integerish(assert_shape(c(NA, 2))) + expect_error(assert_shape(c(2, NA)), regexp = "Invalid") + expect_true(is.integer(assert_shape(c(1, 2), coerce = TRUE))) + expect_false(is.integer(assert_shape(c(1, 2), coerce = FALSE))) +}) From 3cfafdf99d49cdacc0de50d1ae816bf47c7bd865 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 5 Dec 2023 15:35:55 +0100 Subject: [PATCH 15/90] ... --- .github/workflows/r-cmd-check.yml | 2 + .lintr | 18 +- DESCRIPTION | 7 +- R/DataDescriptor.R | 140 ++++++++ R/ModelDescriptor.R | 2 +- R/PipeOpTaskPreprocTorch.R | 240 ++++++++----- R/PipeOpTorch.R | 10 +- R/PipeOpTorchIngress.R | 13 +- R/cache.R | 16 +- R/lazy_tensor.R | 165 +-------- R/preprocess.R | 317 +++++++++--------- R/shape.R | 44 ++- R/with_torch_settings.R | 15 +- R/zzz.R | 1 + man-roxygen/preprocess_torchvision.R | 13 + man/DataDescriptor.Rd | 16 +- man/PipeOpPreprocTorchAugmentCenterCrop.Rd | 21 ++ man/PipeOpPreprocTorchAugmentColorJitter.Rd | 24 ++ man/PipeOpPreprocTorchAugmentCrop.Rd | 24 ++ man/PipeOpPreprocTorchAugmentHflip.Rd | 20 ++ man/PipeOpPreprocTorchAugmentRandomAffine.Rd | 43 +++ man/PipeOpPreprocTorchAugmentRandomApply.Rd | 22 ++ man/PipeOpPreprocTorchAugmentRandomChoice.Rd | 21 ++ man/PipeOpPreprocTorchAugmentRandomCrop.Rd | 25 ++ ...PreprocTorchAugmentRandomHorizontalFlip.Rd | 21 ++ man/PipeOpPreprocTorchAugmentRandomOrder.Rd | 21 ++ ...eOpPreprocTorchAugmentRandomResizedCrop.Rd | 24 ++ ...OpPreprocTorchAugmentRandomVerticalFlip.Rd | 21 ++ man/PipeOpPreprocTorchAugmentResizedCrop.Rd | 26 ++ man/PipeOpPreprocTorchAugmentRotate.Rd | 25 ++ man/PipeOpPreprocTorchAugmentVflip.Rd | 20 ++ ...PipeOpPreprocTorchTrafoAdjustBrightness.Rd | 21 ++ man/PipeOpPreprocTorchTrafoAdjustGamma.Rd | 22 ++ man/PipeOpPreprocTorchTrafoAdjustHue.Rd | 21 ++ ...PipeOpPreprocTorchTrafoAdjustSaturation.Rd | 21 ++ man/PipeOpPreprocTorchTrafoGrayscale.Rd | 21 ++ man/PipeOpPreprocTorchTrafoNop.Rd | 11 + man/PipeOpPreprocTorchTrafoNormalize.Rd | 23 ++ man/PipeOpPreprocTorchTrafoPad.Rd | 23 ++ man/PipeOpPreprocTorchTrafoResize.Rd | 22 ++ man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd | 20 ++ man/assert_shape.Rd | 12 +- man/mlr_pipeops_preproc_torch.Rd | 156 +++++---- man/mlr_pipeops_preproc_torch_overview.Rd | 19 -- man/mlr_pipeops_torch_ingress_ltnsr.Rd | 4 +- man/pipeop_preproc_torch.Rd | 7 +- man/pipeop_preproc_torch_class.Rd | 11 +- tests/testthat/helper_autotest.R | 21 +- tests/testthat/helper_tasks.R | 4 +- tests/testthat/test_DataDescriptor.R | 36 ++ tests/testthat/test_LearnerTorch.R | 14 +- tests/testthat/test_ModelDescriptor.R | 2 +- tests/testthat/test_PipeOpTaskPreprocTorch.R | 18 +- tests/testthat/test_PipeOpTorch.R | 4 +- tests/testthat/test_PipeOpTorchIngress.R | 11 +- .../testthat/test_TaskClassif_tiny_imagenet.R | 1 + tests/testthat/test_autotests.R | 2 + tests/testthat/test_cache.R | 12 +- tests/testthat/test_imageuri.R | 2 +- tests/testthat/test_lazy_tensor.R | 44 +-- tests/testthat/test_materialize.R | 2 +- tests/testthat/test_preprocess.R | 229 +++++++++++++ tests/testthat/test_shape.R | 12 +- tests/testthat/test_with_torch_settings.R | 12 +- 64 files changed, 1576 insertions(+), 641 deletions(-) create mode 100644 R/DataDescriptor.R create mode 100644 man-roxygen/preprocess_torchvision.R create mode 100644 man/PipeOpPreprocTorchAugmentCenterCrop.Rd create mode 100644 man/PipeOpPreprocTorchAugmentColorJitter.Rd create mode 100644 man/PipeOpPreprocTorchAugmentCrop.Rd create mode 100644 man/PipeOpPreprocTorchAugmentHflip.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRandomAffine.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRandomApply.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRandomChoice.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRandomCrop.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRandomOrder.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd create mode 100644 man/PipeOpPreprocTorchAugmentResizedCrop.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRotate.Rd create mode 100644 man/PipeOpPreprocTorchAugmentVflip.Rd create mode 100644 man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd create mode 100644 man/PipeOpPreprocTorchTrafoAdjustGamma.Rd create mode 100644 man/PipeOpPreprocTorchTrafoAdjustHue.Rd create mode 100644 man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd create mode 100644 man/PipeOpPreprocTorchTrafoGrayscale.Rd create mode 100644 man/PipeOpPreprocTorchTrafoNop.Rd create mode 100644 man/PipeOpPreprocTorchTrafoNormalize.Rd create mode 100644 man/PipeOpPreprocTorchTrafoPad.Rd create mode 100644 man/PipeOpPreprocTorchTrafoResize.Rd create mode 100644 man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd delete mode 100644 man/mlr_pipeops_preproc_torch_overview.Rd create mode 100644 tests/testthat/test_DataDescriptor.R diff --git a/.github/workflows/r-cmd-check.yml b/.github/workflows/r-cmd-check.yml index fd033085..71f6708a 100644 --- a/.github/workflows/r-cmd-check.yml +++ b/.github/workflows/r-cmd-check.yml @@ -35,6 +35,8 @@ jobs: config: - {os: ubuntu-latest, r: 'devel'} - {os: ubuntu-latest, r: 'release'} + - {os: macos-latest, r: 'release'} + - {os: windows-latest, r: 'release'} steps: - uses: actions/checkout@v3 diff --git a/.lintr b/.lintr index 0f20f6c6..f4deef98 100644 --- a/.lintr +++ b/.lintr @@ -1,9 +1,9 @@ -linters: with_defaults( - # lintr defaults: https://github.com/jimhester/lintr#available-linters - # the following setup changes/removes certain linters - assignment_linter = NULL, # do not force using <- for assignments - object_name_linter = object_name_linter(c("snake_case", "CamelCase")), # only allow snake case and camel case object names - cyclocomp_linter = NULL, # do not check function complexity - commented_code_linter = NULL, # allow code in comments - line_length_linter = line_length_linter(180) - ) +linters: linters_with_defaults( + assignment_linter=NULL, + object_name_linter=NULL, + cyclocomp_linter=NULL, + commented_code_linter=NULL, + line_length_linter=line_length_linter(180), + indentation_linter=NULL, + object_length_linter=object_length_linter(40)) + diff --git a/DESCRIPTION b/DESCRIPTION index 7f2e0191..d1140427 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -41,6 +41,7 @@ Imports: backports, checkmate (>= 2.2.0), coro, + fs, lgr, mlr3misc (>= 0.13.0), methods, @@ -66,14 +67,15 @@ Suggests: Remotes: r-lib/zip, mlr-org/mlr3, - mlr-org/mlr3pipelines@feat/keep_results + mlr-org/mlr3pipelines@feat/keep_results, + mlverse/torchvision Config/testthat/edition: 3 NeedsCompilation: no ByteCompile: no VignetteBuilder: knitr Encoding: UTF-8 Roxygen: list(markdown = TRUE, r6 = TRUE) -RoxygenNote: 7.2.3 +RoxygenNote: 7.2.3.9000 Collate: 'CallbackSet.R' 'zzz.R' @@ -83,6 +85,7 @@ Collate: 'CallbackSetProgress.R' 'ContextTorch.R' 'DataBackendLazy.R' + 'DataDescriptor.R' 'LearnerTorch.R' 'LearnerTorchImage.R' 'LearnerTorchAlexNet.R' diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R new file mode 100644 index 00000000..bc4eee21 --- /dev/null +++ b/R/DataDescriptor.R @@ -0,0 +1,140 @@ +#' @title Data Descriptor +#' +#' @description +#' A data descriptor is a rather internal data structure used in the [`lazy_tensor`] data type. +#' In essence it is an annotated [`torch::dataset`] and a preprocessing graph (consisting mosty of [`PipeOpModule`] +#' operators). The additional meta data (e.g. pointer, shapes) allows to preprocess [`lazy_tensors`] in an +#' [`mlr3pipelines::Graph`] just like any (non-lazy) data types. +#' To observe the effect of such a preprocessing, [`materialize()`] can be used. +#' +#' @param dataset ([`torch::dataset`])\cr +#' The torch dataset. +#' @param dataset_shapes (named `list()` of (`integer()` or `NULL`))\cr +#' The shapes of the output. +#' Names are the elements of the list returned by the dataset. +#' If the shape is not `NULL` (unknown, e.g. for images of different sizes) the first dimension must be `NA` to +#' indicate the batch dimension. +#' @param graph ([`Graph`])\cr +#' The preprocessing graph. +#' If left `NULL`, no preprocessing is applied to the data and `.input_map`, `.pointer` and `.pointer_shape` +#' are inferred in case the dataset returns only one element. +#' @param .input_map (`character()`)\cr +#' Character vector that must have the same length as the input of the graph. +#' Specifies how the data from the `dataset` is fed into the preprocessing graph. +#' @param .pointer (`character(2)` | `NULL`)\cr +#' Indicating an element on which a model is. Points to an output channel within `graph`: +#' Element 1 is the `PipeOp`'s id and element 2 is that `PipeOp`'s output channel. +#' @param .pointer_shape (`integer` | `NULL`)\cr +#' Shape of the output indicated by `.pointer`. +#' @param clone_graph (`logical(1)`)\cr +#' Whether to clone the preprocessing graph. +#' @param .pointer_shape_predict (`integer()` or `NULL`)\cr +#' Internal use only. +#' Used in a [`Graph`] to anticipate possible mismatches between train and predict shapes. +#' +#' @export +#' @seealso ModelDescriptor, lazy_tensor +#' @examples +#' # Create a dataset +#' dsg = dataset( +#' initialize = function() self$x = torch_randn(10, 3, 3), +#' .getitem = function(i) self$x[i, ], +#' .length = function() nrow(self$x) +#' ) +#' ds = dsg() +#' +#' # Create the preprocessing graph +#' po_module = po("module", module = function(x) torch_reshape(x, c(-1, 9))) +#' po_module$output +#' graph = as_graph(po_module) +#' +#' # Create the data descriptor +#' +#' dd = DataDescriptor( +#' dataset = ds, +#' dataset_shapes = list(x = c(NA, 3, 3)), +#' graph = graph, +#' .input_map = "x", +#' .pointer = c("module", "output"), +#' .pointer_shape = c(NA, 9) +#' ) +#' +#' # with no preprocessing +#' dd1 = DataDescriptor(ds, list(x = c(NA, 3, 3))) +DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NULL, .pointer = NULL, + .pointer_shape = NULL, .pointer_shape_predict = NULL, clone_graph = TRUE) { + assert_class(dataset, "dataset") + + # If the dataset implements a .getbatch() method the shape must be specified, as it should be the same for + # all batches + # For simplicity we here require the first dimension of the shape to be NA so we don't have to deal with it, + # e.g. during subsetting + assert_shapes(dataset_shapes, null_ok = is.null(dataset$.getbatch), unknown_batch = TRUE, named = TRUE) + assert_shape(.pointer_shape_predict, null_ok = TRUE, unknown_batch = TRUE) + + if (is.null(graph)) { + if ((length(dataset_shapes) == 1L) && is.null(.input_map)) { + .input_map = names(dataset_shapes) + } + assert_true(length(.input_map) == 1L) + assert_subset(.input_map, names(dataset_shapes)) + + graph = as_graph(po("nop", id = paste0(class(dataset)[[1L]], "_", .input_map))) + .pointer = c(graph$output$op.id, graph$output$channel.name) + .pointer_shape = dataset_shapes[[.input_map]] + } else { + graph = as_graph(graph, clone = clone_graph) + assert_true(length(graph$pipeops) >= 1L) + + assert_true(!is.null(.input_map)) + assert_choice(.pointer[[1]], names(graph$pipeops)) + assert_choice(.pointer[[2]], graph$pipeops[[.pointer[[1]]]]$output$name) + assert_subset(paste0(.pointer, collapse = "."), graph$output$name) + assert_shape(.pointer_shape, null_ok = TRUE) + + assert_subset(.input_map, names(dataset_shapes)) + assert_true(length(.input_map) == length(graph$input$name)) + } + + # We hash the address of the environment, because the hashes of an environment are not stable, + # even with a .dataset (that should usually not really have a state), hashes might change due to byte-code + # compilation + dataset_hash = calculate_hash(address(dataset)) + + obj = structure( + list( + dataset = dataset, + graph = graph, + dataset_shapes = dataset_shapes, + .input_map = .input_map, + .pointer = .pointer, + .pointer_shape = .pointer_shape, + .dataset_hash = dataset_hash, + .hash = NULL, # is set below + # Once a DataDescriptor is created the input PipeOps are fix, we save them + # here because they can be costly to compute + .graph_input = graph$input$name, + .pointer_shape_predict = .pointer_shape_predict + ), + class = "DataDescriptor" + ) + + obj = set_data_descriptor_hash(obj) + + return(obj) +} + +# TODO: printer + +set_data_descriptor_hash = function(data_descriptor) { + # avoid partial argument m + data_descriptor$.hash = calculate_hash( + data_descriptor[[".dataset_hash"]], + data_descriptor[["graph"]][["hash"]], + data_descriptor[[".input_map"]], + data_descriptor[[".pointer"]], + data_descriptor[[".pointer_shape"]], + data_descriptor[[".pointer_shape_perdict"]] + ) + return(data_descriptor) +} diff --git a/R/ModelDescriptor.R b/R/ModelDescriptor.R index e3a9f6d1..f6c86bf3 100644 --- a/R/ModelDescriptor.R +++ b/R/ModelDescriptor.R @@ -65,7 +65,7 @@ ModelDescriptor = function(graph, ingress, task, optimizer = NULL, loss = NULL, callbacks = set_names(callbacks, assert_names(ids(callbacks), type = "unique")) if (!is.null(.pointer)) { - assert_integerish(.pointer_shape) + .pointer_shape = assert_shape(.pointer_shape, null_ok = FALSE, unknown_batch = TRUE) assert_choice(.pointer[[1]], names(graph$pipeops)) assert_choice(.pointer[[2]], graph$pipeops[[.pointer[[1]]]]$output$name) } diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 543b2ebc..e61dd088 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -38,6 +38,9 @@ #' All tags should be set to `"train"`. #' @param stages_init (`logical(1)`)\cr #' Initial value for the `stages` parameter. +#' @param rowwise (`logical(1)`)\cr +#' Whether the preprocessing function is applied rowwise (and then concatenated by row) or directly to the whole +#' tensor. #' @section Input and Output Channels: #' See [`PipeOpTaskPreproc`]. #' @section State: @@ -46,23 +49,36 @@ #' In addition to the parameters inherited from [`PipeOpTaskPreproc`] as well as those specified during construction #' as the argument `param_set` there are the following parameters: #' -#' * `stages` :: `character()`\cr +#' * `stages` :: `character(1)`\cr #' The stages during which to apply the preprocessing. -#' Must be a subset of `"train"` and `"predict"`. +#' Can be one of `"train"`, `"predict"` or `"both"`. +#' The initial value of this parameter is set to `"train"` when the `PipeOp`'s id starts with `"augment_"` and +#' to `"both"` otherwise. +#' o #' Note that the preprocessing that is applied during `$predict()` uses the parameters that were set during #' `$train()` and not those that are set when performing the prediction. #' #' @section Internals: -#' A [`PipeOpModule`] with one input and one output channel is created. -#' The pipeop simply applies the function `fn` to the input tensor while additionally +#' During `$train()` / `$predict()`, a [`PipeOpModule`] with one input and one output channel is created. +#' The pipeop applies the function `fn` to the input tensor while additionally #' passing the parameter values (minus `stages` and `affect_columns`) to `fn`. -#' In addition, the new shapes are calculates using the `$shapes_out()` method. -#' Then, new lazy tensor columns with updated preprocessing graphs and metadata are created. -#' This mechanism is very similar to the [`ModelDescriptor`] mechanism that is being used to construct -#' neural network architectures. Read the (Internals) documentation of [`PipeOpTorch`] for this. +#' The preprocessing graph of the lazy tensor columns is shallowly cloned and the `PipeOpModule` is added. +#' This is done to avoid modifying user input and means that identical `PipeOpModule`s can be part of different +#' preprocessing graphs. This is possible, because the created `PipeOpModule` is stateless. +#' At a later point, graphs will be merged if possible to avoid unnecessary computation. +#' This is best illustrated by example: +#' One lazy tensor column's preprocessing graph is `A -> B`. +#' Then, two branches are created `B -> C` and `B -> D`, creating two preprocessing graphs +#' `A -> B -> C` and `A -> B -> D`. When loading the data, we want to run the preprocessing only once, i.e. +#' the `A -> B` part. For this reason, [`task_dataset()`] will try to merge graphs and cache results from graphs. #' -#' We also add the shape that would be present during a `$predict()` call, this information can later be used -#' to check whether the train-preprocessing and the predict-preprocessing are compatible. +#' Also, the shapes created during `$train()` and `$predict()` might differ. +#' To avoid the creation of graphs where the predict shapes are incompatible with the train shapes, +#' the hypothetical predict shapes are already calculated during `$train()` (hence the parameters that are set during +#' train are also used during predict) and the [`PipeOpTorchModel`] will check the train and predict shapes for +#' compatibility before starting the training. +#' +#' Otherwise, this mechanism is very similar to the [`ModelDescriptor`] construct. #' #' @include PipeOpTorch.R #' @export @@ -79,7 +95,7 @@ #' #' # Creating a simple preprocessing pipeop #' po_simple = po("preproc_torch", -#' # use mlr3misc::crate to get rid of unnecessary environment baggage +#' # get rid of environment baggage #' fn = mlr3misc::crate(function(x, a) x + a), #' param_set = ps(a = p_int(tags = c("train", "required"))) #' ) @@ -87,7 +103,7 @@ #' po_simple$param_set$set_values( #' a = 100, #' affect_columns = selector_name(c("x1", "x2")), -#' stages = c("train", "predict") +#' stages = "both" # use during train and predict #' ) #' #' taskout_train = po_simple$train(list(taskin))[[1L]] @@ -105,65 +121,63 @@ #' materialize(taskout_predict_aug$data(cols = c("x1", "x2")), rbind = TRUE) #' #' # Creating a more complex preprocessing PipeOp +#'po_poly = pipeop_preproc_torch( +#' public = list( +#' initialize = function(id = "preproc_poly", param_vals = list()) { +#' param_set = paradox::ps( +#' n_degree = paradox::p_int(lower = 1L, tags = c("train", "required")) +#' ) +#' param_set$set_values( +#' n_degree = 1L +#' ) +#' fn = mlr3misc::crate(function(x, n_degree) { +#' torch::torch_cat( +#' lapply(seq_len(n_degree), function(d) torch_pow(x, d)), +#' dim = 2L +#' ) +#' }) #' -#' PipeOpPreprocTorchPoly = R6::R6Class("PipeOpPreprocTorchPoly", -#' inherit = PipeOpTaskPreprocTorch, -#' public = list( -#' initialize = function(id = "preproc_poly", param_vals = list()) { -#' param_set = paradox::ps( -#' n_degree = paradox::p_int(lower = 1L, tags = c("train", "required")) -#' ) -#' param_set$set_values( -#' n_degree = 1L -#' ) -#' fn = mlr3misc::crate(function(x, n_degree) { -#' torch::torch_cat( -#' lapply(seq_len(n_degree), function(d) torch_pow(x, d)), -#' dim = 2L -#' ) -#' }) +#' super$initialize( +#' fn = fn, +#' id = id, +#' packages = character(0), +#' param_vals = param_vals, +#' param_set = param_set +#' ) +#' } +#' ), +#' private = list( +#' .shapes_out = function(shapes_in, param_vals, task) { +#' # shapes_in is a list of length 1 containing the shapes +#' checkmate::assert_true(length(shapes_in[[1L]]) == 2L) +#' if (shapes_in[[1L]][2L] != 1L) { +#' stop("Input shape must be (NA, 1)") +#' } +#' list(c(NA, param_vals$n_degree)) +#' } +#' ) +#') #' -#' super$initialize( -#' fn = fn, -#' id = id, -#' packages = character(0), -#' param_vals = param_vals, -#' param_set = param_set -#' ) -#' } -#' ), -#' private = list( -#' .shapes_out = function(shapes_in, param_vals, task) { -#' # shapes_in is a list of length 1 containing the shapes -#' checkmate::assert_true(length(shapes_in[[1L]]) == 2L) -#' if (shapes_in[[1L]][2L] != 1L) { -#' stop("Input shape must be (NA, 1)") -#' } -#' list(c(NA, param_vals$n_degree)) -#' } -#' ) -#' ) +#'po_poly = PipeOpPreprocTorchPoly$new( +#' param_vals = list(n_degree = 3L, affect_columns = selector_name("x3")) +#') #' -#' po_poly = PipeOpPreprocTorchPoly$new( -#' param_vals = list(n_degree = 3L, affect_columns = selector_name("x3")) -#' ) +#'po_poly$shapes_out(list(c(NA, 1L))) #' -#' po_poly$shapes_out(list(c(NA, 1L))) -#' -#' taskout = po_poly$train(list(taskin))[[1L]] -#' materialize(taskout$data(cols = "x3"), rbind = TRUE) +#'taskout = po_poly$train(list(tasken))[[1L]] +#'materialize(taskout$data(cols = "x3"), rbind = TRUE) PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", inherit = PipeOpTaskPreproc, public = list( #' @description #' Creates a new instance of this [`R6`][R6::R6Class] class. initialize = function(fn, id = "preproc_torch", param_vals = list(), param_set = ps(), packages = character(0), - stages_init = c("train", "predict")) { + stages_init = "both", rowwise = FALSE) { # nolint private$.fn = assert_function(fn) - assert_subset(stages_init, c("train", "predict")) + private$.rowwise = assert_flag(rowwise) param_set$add(ps( - stages = p_uty(tags = c("train", "required"), custom_check = crate(function(x) check_subset(x, c("train", "predict")))) + stages = p_fct(c("train", "predict", "both"), tags = c("train", "required")) )) param_set$set_values(stages = stages_init) @@ -206,6 +220,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", } stages = pv$stages + if (identical(stages, "both")) stages = c("train", "predict") pv$stages = NULL pv$affect_columns = NULL @@ -223,7 +238,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", } ), active = list( - #' @description + #' @field fn #' The preprocessing function. fn = function(rhs) { assert_ro_binding(rhs) @@ -231,6 +246,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", } ), private = list( + .rowwise = NULL, .train_task = function(task) { dt_columns = private$.select_cols(task) cols = dt_columns @@ -269,13 +285,25 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", param_vals$stages = NULL trafo = private$.fn - fn = if (stage %in% stages) { + fn = if (identical(stages, "both") || stage %in% stages) { if (length(param_vals)) { - crate(function(x) { - invoke(.f = trafo, x, .args = param_vals) - }, param_vals, trafo, .parent = environment(trafo)) + if (private$.rowwise) { + trafo = crate(function(x) { + torch_cat(map(seq_len(nrow(x)), function(i) invoke(trafo, x[i, ..], .args = param_vals)$unsqueeze(1L)), dim = 1L) + }, param_vals, trafo, .parent = environment(trafo)) + } else { + crate(function(x) { + invoke(.f = trafo, x, .args = param_vals) + }, param_vals, trafo, .parent = environment(trafo)) + } } else { - trafo + if (private$.rowwise) { + crate(function(x) { + torch_cat(map(seq_len(nrow(x)), function(i) trafo(x[i, ..])$unsqueeze(1L)), dim = 1L) + }, trafo) + } else { + trafo + } } } else { identity @@ -330,14 +358,14 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' @param param_vals (`list()`)\cr #' The parameter values. #' @export -pipeop_preproc_torch = function(id, fn, shapes_out, param_set = NULL, param_vals = list(), - packages = character(0)) { +pipeop_preproc_torch = function(id, fn, shapes_out, param_set = NULL, param_vals = list(), packages = character(0)) { + pipeop_preproc_torch_class( id = id, - fn = fn, + fn = if (is.language(fn)) fn else substitute(fn), shapes_out = shapes_out, - param_set = param_set, - packages = packages + param_set = if (is.language(param_set)) param_set else substitute(param_set), + packages = if (is.language(packages)) packages else substitute(packages), )$new(param_vals = param_vals) } @@ -347,7 +375,7 @@ create_ps_call = function(fn) { param_names = names(fmls) param_names = setdiff(param_names[-1L], "...") fmls = fmls[param_names] - is_required = map(fmls, function(x) x == rlang::missing_arg()) + is_required = map(fmls, function(x) identical(x, rlang::missing_arg())) # Create an empty named list to store the arguments args = list() @@ -399,22 +427,25 @@ create_ps_call = function(fn) { #' po_example = pipeop_preproc_torch("preproc_example", function(x, a) x + a) #' po_example #' po_example$param_set -pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, packages = character(0)) { - assert_function(fn) - assert_true(length(formals(fn)) >= 1L) +pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, packages = character(0), init_params = list(), + rowwise = FALSE) { assert( check_function(shapes_out, args = c("shapes_in", "param_vals", "task"), null.ok = TRUE), - check_choice(shapes_out, c("infer", "unknown", )) + check_choice(shapes_out, c("infer", "unchanged")) ) - if (!is.null(param_set)) { - assert_param_set(eval(param_set)) + if (!is.language(param_set)) { + param_set = substitute(param_set) + } } else { # This should add required tags where it is applicable - param_set = create_ps_call(fn) + param_set = create_ps_call(eval(fn)) } + if (!is.language(init_params)) init_params = substitute(init_params) + if (!is.language(fn)) fn = substitute(fn) + classname = paste0("PipeOpPreprocTorch", paste0(capitalize(strsplit(id, split = "_")[[1L]]), collapse = "")) # Note that we don't set default values @@ -422,41 +453,65 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack shapes_out = crate(function(shapes_in, param_vals, task) { sin = shapes_in[[1L]] - unknown_batch_dim = is.na(sin[1L]) + batch_dim = sin[1L] + unknown_batch_dim = is.na(batch_dim) if (unknown_batch_dim) { sin[1] = 1L } + if (rowwise) { + sin = sin[-1L] + } tensor_in = invoke(torch_empty, .args = sin, device = torch_device("meta")) - tensor_out = invoke(private$.fn, tensor_in, .args = param_vals) + tensor_out = tryCatch(invoke(private$.fn, tensor_in, .args = param_vals), + error = function(e) { + stopf("Invalid input shape, error message: %s", e) + } + ) sout = dim(tensor_out) - if (unknown_batch_dim) { + if (rowwise) { + sout = c(batch_dim, sout) + } else if (unknown_batch_dim) { sout[1] = NA } list(sout) - }) + }, rowwise) } else if (identical(shapes_out, "unchanged")) { shapes_out = crate(function(shapes_in, param_vals, task_in) shapes_in) + } else if (is.function(shapes_out) || is.null(shapes_out)) { + # nothing to do } else { - stopf("Cannot happen") + stopf("unreachable") } - init_fun = crate(function(id = idname, param_vals = list()) { + param_set = x1 + param_set$values = x2 super$initialize( id = id, - packages = packages, - param_set = ps, + packages = x3, + param_set = param_set, param_vals = param_vals, - fn = fn + fn = x4, + rowwise = x5, + stages_init = x6 ) }) + stages_init = if (startsWith(id, "augment_")) { + "train" + } else { + "both" + } + formals(init_fun)$id = id # param_set is already an expression - body(init_fun)[[2]][[3]] = substitute(packages) - body(init_fun)[[2]][[4]] = param_set - body(init_fun)[[2]][[6]] = substitute(fn) + body(init_fun)[[2]][[3]] = param_set + body(init_fun)[[3]][[3]] = init_params + body(init_fun)[[4]][[3]] = packages + body(init_fun)[[4]][[6]] = fn + body(init_fun)[[4]][[7]] = rowwise + body(init_fun)[[4]][[8]] = stages_init Class = R6Class(classname, inherit = PipeOpTaskPreprocTorch, @@ -469,10 +524,11 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack return(Class) } -register_preproc = function(id, fn, param_set = NULL, shapes_out = NULL, packages = character(0)) { - Class = pipeop_preproc_torch_class(id, fn, param_set = substitute(param_set), shapes_out = shapes_out, packages = packages) +register_preproc = function(id, fn, param_set = NULL, shapes_out = NULL, packages = character(0), rowwise = FALSE) { + Class = pipeop_preproc_torch_class(id, substitute(fn), param_set = substitute(param_set), shapes_out = shapes_out, + packages = packages, rowwise = rowwise) assign(Class$classname, Class, parent.frame()) register_po(id, Class) } -register_po("preproc_torch", PipeOpTaskPreprocTorch, metainf = list(fn = identity)) +register_po("preproc_torch", PipeOpTaskPreprocTorch, metainf = list(fn = identity, rowwise = FALSE)) diff --git a/R/PipeOpTorch.R b/R/PipeOpTorch.R index 496eaaba..ad885513 100644 --- a/R/PipeOpTorch.R +++ b/R/PipeOpTorch.R @@ -284,10 +284,11 @@ PipeOpTorch = R6Class("PipeOpTorch", shapes_out = function(shapes_in, task = NULL) { assert_r6(task, "Task", null.ok = TRUE) if (is.numeric(shapes_in)) shapes_in = list(shapes_in) - if (identical(self$input$name, "...")) { - assert_list(shapes_in, min.len = 1, types = "numeric") - } else { - assert_list(shapes_in, len = nrow(self$input), types = "numeric") + # batch dimensionc can be known or unknown + assert_shapes(shapes_in, unknown_batch = NULL) + if ("..." %nin% self$input$name) { + assert_true(length(shapes_in) == nrow(self$input), + .var.name = "number of input shapes equal to number of input channels") } s = if (is.null(private$.shapes_out)) { @@ -313,7 +314,6 @@ PipeOpTorch = R6Class("PipeOpTorch", input_pointers = map(inputs, ".pointer") input_shapes = map(inputs, ".pointer_shape") - assert_shapes(input_shapes, named = FALSE, null_ok = FALSE) # Now begin creating the result-object: it contains a merged version of all `inputs`' $graph slots etc. # The only thing missing afterwards is (1) integrating module_op to the merged $graph, and adding `.pointer`s. result_template = Reduce(model_descriptor_union, inputs) diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index b2265f85..f297b59b 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -324,9 +324,8 @@ register_po("torch_ingress_img", PipeOpTorchIngressImage) #' #' @section Parameters: #' * `shape` :: `integer()`\cr -#' The shape of the tensor, excluding the batch dimension. +#' The shape of the tensor, where the first dimension (batch) must be `NA`. #' Whether it is necessary to specify the shape depends on whether the lazy tensor input column has a known shape. -#' If the input shape is known, this parameter can be set, but must match the input shape. #' #' @section Internals: #' The returned batchgetter materializes the lazy tensor column to a tensor. @@ -376,7 +375,6 @@ register_po("torch_ingress_img", PipeOpTorchIngressImage) #' ) #' #' x_batch2 -#' PipeOpTorchIngressLazyTensor = R6Class("PipeOpTorchIngressLazyTensor", inherit = PipeOpTorchIngress, public = list( @@ -385,8 +383,9 @@ PipeOpTorchIngressLazyTensor = R6Class("PipeOpTorchIngressLazyTensor", #' @template params_pipelines initialize = function(id = "torch_ingress_ltnsr", param_vals = list()) { param_set = ps( - shape = p_uty(tags = "train", custom_check = check_shape) - ) + shape = p_uty(tags = "train", custom_check = crate( + function(x) check_shape(x, null_ok = FALSE, unknown_batch = TRUE))) + ) super$initialize(id = id, param_vals = param_vals, feature_types = "lazy_tensor", param_set = param_set) } ), @@ -407,7 +406,7 @@ PipeOpTorchIngressLazyTensor = R6Class("PipeOpTorchIngressLazyTensor", return(pv_shape) } - if (!is.null(pv_shape) && isTRUE(all.equal(pv_shape, input_shape))) { + if (!is.null(pv_shape) && !isTRUE(all.equal(pv_shape, input_shape))) { stopf("Parameter 'shape' is set for PipeOp '%s', but differs from the (known) lazy tensor input shape.", self$id) # nolint } @@ -420,8 +419,6 @@ PipeOpTorchIngressLazyTensor = R6Class("PipeOpTorchIngressLazyTensor", ) batchgetter_lazy_tensor = function(data, device, cache) { - # FIXME: Should we here check for the shapes? - # If the user set them wrong, the network should fail anyway materialize_internal(x = data[[1L]], device = device, cache = cache, rbind = TRUE) } diff --git a/R/cache.R b/R/cache.R index 5fe26774..fb1678d7 100644 --- a/R/cache.R +++ b/R/cache.R @@ -25,7 +25,7 @@ get_cache_dir = function(cache = NULL) { } assert(check_directory_exists(cache), check_path_for_output(cache)) - normalizePath(cache, mustWork = FALSE) + fs::path_norm(cache) } #' Initializes the cache directory. @@ -37,7 +37,7 @@ get_cache_dir = function(cache = NULL) { #' #' @noRd initialize_cache = function(cache_dir) { - if (isFALSE(cache_dir) || cache_dir %in% CACHE$initialized) { + if (isFALSE(cache_dir) || (file.exists(cache_dir) && fs::path_real(cache_dir) %in% CACHE$initialized)) { lg$debug("Skipping initialization of cache", cache_dir = cache_dir) return(TRUE) } @@ -70,7 +70,7 @@ initialize_cache = function(cache_dir) { writeLines(jsonlite::toJSON(CACHE$versions, auto_unbox = TRUE), con = cache_file) } - CACHE$initialized = c(CACHE$initialized, cache_dir) + CACHE$initialized = c(CACHE$initialized, fs::path_real(cache_dir)) return(TRUE) } @@ -80,12 +80,12 @@ cached = function(constructor, type, name) { initialize_cache(cache_dir) assert_choice(type, names(CACHE$versions)) - cache = !isFALSE(cache_dir) + do_caching = !isFALSE(cache_dir) # Even when we don't cache, we need to store the data somewhere - path = if (cache) file.path(cache_dir, type, name) else tempfile() + path = fs::path_norm(if (do_caching) file.path(cache_dir, type, name) else tempfile()) - if (cache && dir.exists(path)) { + if (do_caching && dir.exists(path)) { # we cache and there is a cache hit data = readRDS(file.path(path, "data.rds")) output = list(data = data, path = path) @@ -109,7 +109,7 @@ cached = function(constructor, type, name) { # now path/raw exists - if (cache) { + if (do_caching) { # store the processed data in case there is a cache hit, so next time we don't need the postprocessing # that comes after downloading the data saveRDS(data, file = file.path(path, "data.rds")) @@ -123,6 +123,6 @@ clear_mlr3torch_cache = function() { return(FALSE) } unlink(get_cache_dir(), recursive = TRUE) - CACHE$initialized = setdiff(CACHE$initialized, get_cache_dir()) + CACHE$initialized = setdiff(CACHE$initialized, fs::path_norm(get_cache_dir())) return(TRUE) } diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index 7c04fc0e..da748451 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -1,141 +1,3 @@ -#' @title Data Descriptor -#' -#' @description -#' A data descriptor is a rather internal data structure used in the [`lazy_tensor`] data type. -#' In essence it is an annotated [`torch::dataset`] and a preprocessing graph (consisting mosty of [`PipeOpModule`] -#' operators). The additional meta data (e.g. pointer, shapes) allows to preprocess [`lazy_tensors`] in an -#' [`mlr3pipelines::Graph`] just like any (non-lazy) data types. -#' To observe the effect of such a preprocessing, [`materialize()`] can be used. -#' -#' @param dataset ([`torch::dataset`])\cr -#' The torch dataset. -#' @param dataset_shapes (named `list()` of (`integer()` or `NULL`))\cr -#' The shapes of the output. -#' Names are the elements of the list returned by the dataset. -#' If the shape is not `NULL` (unknown, e.g. for images of different sizes) the first dimension must be `NA` to -#' indicate the batch dimension. -#' @param graph ([`Graph`])\cr -#' The preprocessing graph. -#' If left `NULL`, no preprocessing is applied to the data and `.input_map`, `.pointer` and `.pointer_shape` -#' are inferred in case the dataset returns only one element. -#' @param .input_map (`character()`)\cr -#' Character vector that must have the same length as the input of the graph. -#' Specifies how the data from the `dataset` is fed into the preprocessing graph. -#' @param .pointer (`character(2)` | `NULL`)\cr -#' Indicating an element on which a model is. Points to an output channel within `graph`: -#' Element 1 is the `PipeOp`'s id and element 2 is that `PipeOp`'s output channel. -#' @param .pointer_shape (`integer` | `NULL`)\cr -#' Shape of the output indicated by `.pointer`. -#' @param clone_graph (`logical(1)`)\cr -#' Whether to clone the preprocessing graph. -#' @param .pointer_shape_predict (`integer()` or `NULL`)\cr -#' Internal use only. -#' Used in a [`Graph`] to anticipate possible mismatches between train and predict shapes. -#' -#' @export -#' @seealso ModelDescriptor, lazy_tensor -#' @examples -#' # Create a dataset -#' dsg = dataset( -#' initialize = function() self$x = torch_randn(10, 3, 3), -#' .getitem = function(i) self$x[i, ], -#' .length = function() nrow(self$x) -#' ) -#' ds = dsg() -#' -#' # Create the preprocessing graph -#' po_module = po("module", module = function(x) torch_reshape(x, c(-1, 9))) -#' po_module$output -#' graph = as_graph(po_module) -#' -#' # Create the data descriptor -#' -#' dd = DataDescriptor( -#' dataset = ds, -#' dataset_shapes = list(x = c(NA, 3, 3)), -#' graph = graph, -#' .input_map = "x", -#' .pointer = c("module", "output"), -#' .pointer_shape = c(NA, 9) -#' ) -#' -#' # with no preprocessing -#' dd1 = DataDescriptor(ds, list(x = c(NA, 3, 3))) -DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NULL, .pointer = NULL, - .pointer_shape = NULL, clone_graph = TRUE, .pointer_shape_predict = NULL) { - assert_class(dataset, "dataset") - - # If the dataset implements a .getbatch() method the shape must be specified. - assert_shapes(dataset_shapes, null_ok = is.null(dataset$.getbatch)) - assert_shape(.pointer_shape_predict, null_ok = TRUE) - - if (is.null(graph)) { - if ((length(dataset_shapes) == 1L) && is.null(.input_map)) { - .input_map = names(dataset_shapes) - } - assert_true(length(.input_map) == 1L) - assert_subset(.input_map, names(dataset_shapes)) - - graph = as_graph(po("nop", id = paste0(class(dataset)[[1L]], "_", .input_map))) - .pointer = c(graph$output$op.id, graph$output$channel.name) - .pointer_shape = dataset_shapes[[.input_map]] - } else { - graph = as_graph(graph, clone = clone_graph) - assert_true(length(graph$pipeops) >= 1L) - - if (any(is.null(.input_map), is.null(.pointer), is.null(.pointer_shape))) { - stopf("When passing a graph you need to specify .input_map, .pointer and .pointer_shape.") - } - - assert_choice(.pointer[[1]], names(graph$pipeops)) - assert_choice(.pointer[[2]], graph$pipeops[[.pointer[[1]]]]$output$name) - assert_subset(paste0(.pointer, collapse = "."), graph$output$name) - assert_shape(.pointer_shape, null_ok = TRUE) - - assert_subset(.input_map, names(dataset_shapes)) - assert_true(length(.input_map) == length(graph$input$name)) - } - - # We hash the address of the environment, because the hashes of an environment are not stable, - # even with a .dataset (that should usually not really have a state), hashes might change due to byte-code - # compilation - dataset_hash = calculate_hash(address(dataset)) - - obj = structure( - list( - dataset = dataset, - graph = graph, - dataset_shapes = dataset_shapes, - .input_map = .input_map, - .pointer = .pointer, - .pointer_shape = .pointer_shape, - .dataset_hash = dataset_hash, - .hash = NULL, # is set below - # Once a DataDescriptor is created the input PipeOps are fix, we save them - # here because they can be costly to compute - .graph_input = graph$input$name, - .pointer_shape_predict = .pointer_shape_predict - ), - class = "DataDescriptor" - ) - - obj = set_data_descriptor_hash(obj) - - return(obj) -} - -# TODO: printer - -set_data_descriptor_hash = function(data_descriptor) { - data_descriptor$.hash = calculate_hash( - data_descriptor$.dataset_hash, - data_descriptor$graph$hash, - data_descriptor$.input_map, - data_descriptor$.pointer, - data_descriptor$.pointer_shape - ) - return(data_descriptor) -} #' @title Create a lazy tesornsor #' #' @description @@ -144,6 +6,7 @@ set_data_descriptor_hash = function(data_descriptor) { #' The data descriptor or `NULL` for a lazy tensor of length 0. #' @param ids (`integer()`)\cr #' The elements of the `data_descriptor` that the created lazy tensor contains. +#' @include DataDescriptor.R #' @export lazy_tensor = function(data_descriptor = NULL, ids = NULL) { assert_class(data_descriptor, "DataDescriptor", null.ok = TRUE) @@ -294,27 +157,33 @@ transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { assert_class(pipeop, "PipeOpModule") assert_true(nrow(pipeop$input) == 1L) assert_true(nrow(pipeop$output) == 1L) - assert_shape(shape, null_ok = TRUE) + assert_shape(shape, null_ok = TRUE, unknown_batch = TRUE) # shape_predict can be NULL if we transform a tensor during `$predict()` in PipeOpTaskPreprocTorch - assert_shape(shape_predict, null_ok = TRUE) + assert_shape(shape_predict, null_ok = TRUE, unknown_batch = TRUE) data_descriptor = lt$data_descriptor - data_descriptor$graph = data_descriptor$graph$clone(deep = FALSE) - data_descriptor$graph$edges = copy(data_descriptor$graph$edges) + graph = data_descriptor$graph$clone(deep= FALSE) + graph$edges = copy(data_descriptor$graph$edges) - data_descriptor$graph$add_pipeop(pipeop, clone = FALSE) - data_descriptor$graph$add_edge( + graph$add_pipeop(pipeop, clone = FALSE) + graph$add_edge( src_id = data_descriptor$.pointer[1L], src_channel = data_descriptor$.pointer[2L], dst_id = pipeop$id, dst_channel = pipeop$input$name ) - data_descriptor$.pointer = c(pipeop$id, pipeop$output$name) - data_descriptor$.pointer_shape = shape - data_descriptor$.pointer_shape_predict = shape_predict - data_descriptor = set_data_descriptor_hash(data_descriptor) + data_descriptor = DataDescriptor( + data_descriptor$dataset, + dataset_shapes = data_descriptor$dataset_shapes, + graph = graph, + .input_map = data_descriptor$.input_map, + .pointer = c(pipeop$id, pipeop$output$name), + .pointer_shape = shape, + .pointer_shape_predict = shape_predict, + clone_graph = FALSE + ) new_lazy_tensor(data_descriptor, map_int(vec_data(lt), 1)) } diff --git a/R/preprocess.R b/R/preprocess.R index a8733bcc..f7cd7ea4 100644 --- a/R/preprocess.R +++ b/R/preprocess.R @@ -1,170 +1,163 @@ -#' @title Lazy Preprocessing and Transformations -#' @description -#' Overview over all implemented preprocessing methods. -#' See [`PipeOpTaskPreprocTorch`] for more details on the class itself. -#' -#' `PipeOps` preproessed with the `"augment_"` prefix, have their stages parameter initialize to `"train"`, while -#' those with the `"trafo_"` prefix have it set to `c("train", "predict")`. -#' -#' @usage NULL -#' @format NULL -#' @name mlr_pipeops_preproc_torch_overview #' @rawNamespace exportPattern("^PipeOpPreprocTorch") -#' @include PipeOpTaskPreprocTorch.R NULL -##' @name PipeOpPreprocTorchTrafoResize -##' @rdname mlr_pipeops_preproc_torch_overview -##' @description -##' * `trafo_resize`: Calls [`torchvision::transform_resize`] -#register_preproc("trafo_resize", torchvision::transform_resize, -# packages = "torchvision", -# param_set = ps( -# size = p_uty(tags = c("train", "required")), -# interpolation = p_fct(levels = magick::filter_types(), special_vals = list(0L, 2L, 3L), -# tags = "train", default = 2L -# ) -# ), -# shapes_out = function(shapes_in, param_vals, task) { -# size = param_vals$size -# shape = shapes_in[[1L]] -# assert_true(length(shape) > 2) -# height = shape[[length(shape) - 1L]] -# width = shape[[length(shape)]] -# s = torchvision::transform_resize(torch_ones(c(1, height, width), device = "meta"), size = size)$shape[2:3] -# list(c(shape[seq_len(length(shape) - 2L)], s)) -# } -#) -# -##' @name PipeOpPreprocTorchTrafoNop -##' @rdname mlr_pipeops_preproc_torch_overview -##' @description -##' * `trafo_nop`: Calls `identity()`. -#register_preproc("trafo_nop", identity, shapes_out = NULL) -# -##' @name PipeOpPreprocTorchAdjustGamma -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("trafo_adjust_gamma", torchvision::transform_adjust_gamma, packages = "torchvision", shapes_out = NULL) # nolint -# -##' @name PipeOpPreprocTorchAdjustBrightness -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("trafo_adjust_brightness", torchvision::transform_adjust_brightness, packages = "torchvision") # nolint -# -##' @name PipeOpPreprocTorchAdjustHue -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("trafo_adjust_hue", torchvision::transform_adjust_hue, packages = "torchvision", shapes_out = "infer") -# -# -##' @name PipeOpPreprocTorchRandomCrop -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_random_crop", torchvision::transform_random_crop, packages = "torchvision", shapes_out = NULL) -# -##' @name PipeOpPreprocTorchAdjustSaturation -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("trafo_adjust_saturation", torchvision::transform_adjust_saturation, packages = "torchvision", shapes_out = "infer") # nolint -# -##' @name PipeOpPreprocTorchGrayscale -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("grayscale", torchvision::transform_grayscale, packages = "torchvision", shapes_out = "unchanged") # nolint -# -##' @name PipeOpPreprocTorchRgbToGrayscale -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("rgb_to_grayscale", torchvision::transform_rgb_to_grayscale, packages = "torchvision", shapes_out = "unchanged") # nolint -# -##' @name PipeOpPreprocTorchNormalize -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("trafo_normalize", torchvision::transform_normalize, packages = "torchvision", shapes_out = "unchanged") # nolint -# -##' @name PipeOpPreprocTorchPad -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("trafo_pad", torchvision::transform_pad, packages = "torchvision", shapes_out = "infer") # nolint -# -# -## Data Augmentation -# -##' @name PipeOpPreprocTorchResizedCrop -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_resized_crop", torchvision::transform_resized_crop, packages = "torchvision", shapes_out = "infer") # nolint -# -# -##' @name PipeOpPreprocTorchColorJitter -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_color_jitter", torchvision::transform_color_jitter, packages = "torchvision", shapes_out = "unchanged") # nolint -# -##' @name PipeOpPreprocTorchRandomResizedCrop -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_random_resized_crop", torchvision::transform_random_resized_crop, packages = "torchvision", shapes_out = NULL) # nolint -# -##' @name PipeOpPreprocTorchRandomOrder -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_random_order", torchvision::transform_random_order, packages = "torchvision", shapes_out = NULL) # nolint -# -##' @name PipeOpPreprocTorchHflip -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_hflip", torchvision::transform_hflip, packages = "torchvision", shapes_out = "unchanged") # nolint -# -##' @name PipeOpPreprocTorchRandomRotation -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_random_rotation", torchvision::transform_random_rotation, packages = "torchvision", shapes_out = NULL) # nolint -# -##' @name PipeOpPreprocTorchRandomHorizontalFlip -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_random_horizontal_flip", torchvision::transform_random_horizontal_flip, packages = "torchvision", shapes_out = NULL) # nolint -# -##' @name PipeOpPreprocTorchLinaerTransformation -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_linear_transformation", torchvision::transform_linear_transformation, packages = "torchvision", shapes_out = "infer") # nolint -# -##' @name PipeOpPreprocTorchCrop -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_crop", torchvision::transform_crop, packages = "torchvision", shapes_out = "infer") # nolint -# -##' @name PipeOpPreprocTorchRandomVerticalFlip -##' @rdname "unchanged" -#register_preproc("random_vertical_flip", torchvision::transform_random_vertical_flip, packages = "torchvision", shapes_out = "unchanged") # nolint -# -##' @name PipeOpPreprocTorchRandomGrayscale -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("random_grayscale", torchvision::transform_random_grayscale, packages = "torchvision", shapes_out = "unchanged") # nolint -# -##' @name PipeOpPreprocTorchRandomAffine -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_random_affine", torchvision::transform_random_affine, packages = "torchvision", shapes_out = NULL) # nolint -# -##' @name PipeOpPreprocTorchRandomPerspective -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_random_perspective", torchvision::transform_random_perspective, packages = "torchvision", shapes_out = NULL) # nolint -# -##' @name PipeOpPreprocTorchVflip -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_vflip", torchvision::transform_vflip, packages = "torchvision", shapes_out = "unchanged") # nolint -# -##' @name PipeOpPreprocTorchRandomErasing -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_random_erasing", torchvision::transform_random_erasing, packages = "torchvision", shapes_out = "infer") -# -##' @name PipeOpPreprocTorchPerspective -##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_perspective", torchvision::transform_perspective, packages = "torchvision", shapes_out = "infer") # nolint -# -##' @name PipeOpPreprocTorchRandomApply +# FIXME: Better docs, not one for all + +#' @template preprocess_torchvision +#' @templateVar id trafo_resize +register_preproc("trafo_resize", torchvision::transform_resize, + packages = "torchvision", + param_set = ps( + size = p_uty(tags = c("train", "required")), + interpolation = p_fct(levels = c("Undefined", "Bartlett", "Blackman", "Bohman", "Box", "Catrom", "Cosine", "Cubic", + "Gaussian", "Hamming", "Hann", "Hanning", "Hermite", "Jinc", "Kaiser", "Lagrange", "Lanczos", "Lanczos2", + "Lanczos2Sharp", "LanczosRadius", "LanczosSharp", "Mitchell", "Parzen", "Point", "Quadratic", "Robidoux", + "RobidouxSharp", "Sinc", "SincFast", "Spline", "Triangle", "Welch", "Welsh", "Bessel") + , special_vals = list(0L, 2L, 3L), + tags = "train", default = 2L + ) + ), + shapes_out = function(shapes_in, param_vals, task) { + size = param_vals$size + shape = shapes_in[[1L]] + assert_true(length(shape) > 2) + height = shape[[length(shape) - 1L]] + width = shape[[length(shape)]] + s = torchvision::transform_resize(torch_ones(c(1, height, width), device = "meta"), size = size)$shape[2:3] + list(c(shape[seq_len(length(shape) - 2L)], s)) + }, + rowwise = FALSE +) + +#' @title PipeOpPreprocTorchTrafoNop +#' @usage NULL +#' @name mlr_pipeops_preproc_torch.trafo_nop +#' @rdname PipeOpPreprocTorchTrafoNop +#' @format [`R6Class`] inheriting from [`PipeOpTaskPreprocTorch`]. +#' +#' @description +#' Does nothing. +register_preproc("trafo_nop", identity, shapes_out = "unchanged", rowwise = FALSE) + +#' @template preprocess_torchvision +#' @templateVar id trafo_adjust_gamma +register_preproc("trafo_adjust_gamma", torchvision::transform_adjust_gamma, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id trafo_adjust_brightness +register_preproc("trafo_adjust_brightness", torchvision::transform_adjust_brightness, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id trafo_adjust_hue +register_preproc("trafo_adjust_hue", torchvision::transform_adjust_hue, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) + +#' @template preprocess_torchvision +#' @templateVar id trafo_adjust_saturation +register_preproc("trafo_adjust_saturation", torchvision::transform_adjust_saturation, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id trafo_grayscale +register_preproc("trafo_grayscale", torchvision::transform_grayscale, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id trafo_rgb_to_grayscale +register_preproc("trafo_rgb_to_grayscale", torchvision::transform_rgb_to_grayscale, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id trafo_normalize +register_preproc("trafo_normalize", torchvision::transform_normalize, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id trafo_pad +register_preproc("trafo_pad", torchvision::transform_pad, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint + +# Data Augmentation + +#' @template preprocess_torchvision +#' @templateVar id augment_resized_crop +register_preproc("augment_resized_crop", torchvision::transform_resized_crop, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id augment_color_jitter +register_preproc("augment_color_jitter", torchvision::transform_color_jitter, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id augment_random_resized_crop +register_preproc("augment_random_resized_crop", torchvision::transform_random_resized_crop, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id augment_random_order +register_preproc("augment_random_order", torchvision::transform_random_order, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id augment_hflip +register_preproc("augment_hflip", torchvision::transform_hflip, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id augment_random_horizontal_flip +register_preproc("augment_random_horizontal_flip", torchvision::transform_random_horizontal_flip, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint + + +#' @template preprocess_torchvision +#' @templateVar id augment_crop +register_preproc("augment_crop", torchvision::transform_crop, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id augment_random_vertical_flip +register_preproc("augment_random_vertical_flip", torchvision::transform_random_vertical_flip, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id augment_random_affine +register_preproc("augment_random_affine", torchvision::transform_random_affine, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id augment_random_affine +register_preproc("augment_random_perspective", torchvision::transform_random_perspective, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id augment_vflip +register_preproc("augment_vflip", torchvision::transform_vflip, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id augment_random_apply +register_preproc("augment_random_apply", torchvision::transform_random_apply, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id augment_rotate +register_preproc("augment_rotate", torchvision::transform_rotate, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id augment_center_crop +register_preproc("augment_center_crop", torchvision::transform_center_crop, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id augment_random_choice +register_preproc("augment_random_choice", torchvision::transform_random_choice, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint + +#' @template preprocess_torchvision +#' @templateVar id augment_random_crop +register_preproc("augment_random_crop", torchvision::transform_random_crop, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) + + +##' @name PipeOpPreprocTorchAugmentRandomRotation ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_random_apply", torchvision::transform_random_apply, packages = "torchvision", shapes_out = NULL) # nolint -# -##' @name PipeOpPreprocTorchRotate +#register_preproc("augment_random_rotation", torchvision::transform_random_rotation, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint + +##' @name PipeOpPreprocTorchAugmentRandomErasing ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_rotate", torchvision::transform_rotate, packages = "torchvision", shapes_out = "infer") # nolint -# -##' @name PipeOpPreprocTorchCenterCrop +#register_preproc("augment_random_erasing", torchvision::transform_random_erasing, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) + +# not implemented +##' @name PipeOpPreprocTorchAugmentPerspective ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_center_crop", torchvision::transform_center_crop, packages = "torchvision", shapes_out = "infer") # nolint -# -##' @name PipeOpPreprocTorchRandomChoice +#register_preproc("augment_perspective", torchvision::transform_perspective, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint + +# not implemented for tensor +##' @name PipeOpPreprocTorchAugmentRandomGrayscale ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_random_choice", torchvision::transform_random_choice, packages = "torchvision", shapes_out = NULL) # nolint -# -# -##' @name PipeOpPreprocTorchRandomCrop +#register_preproc("augment_random_grayscale", torchvision::transform_random_grayscale, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint + +# infering shape does not work, we could do it manually +##' @name PipeOpPreprocTorchAugmentLinearTransformation ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_random_crop", torchvision::transform_random_crop, packages = "torchvision", shapes_out = NULL) # nolint -# +#register_preproc("augment_linear_transformation", torchvision::transform_linear_transformation, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint diff --git a/R/shape.R b/R/shape.R index d8911956..ac9f7965 100644 --- a/R/shape.R +++ b/R/shape.R @@ -1,4 +1,3 @@ -#' Check Shape #' #' Checks whether an integer vector is a valid shape. #' Unknown shapes are represted as `NULL`. @@ -8,17 +7,27 @@ #' Whether `NULL` is a valid shape. #' @param coerce (`logical(1)`)\cr #' Whether to coerce the input to an `integer()` if possible. -assert_shape = function(shape, null_ok = FALSE, coerce = TRUE) { - if (!test_shape(shape, null_ok = null_ok)) { - stopf("Invalid shape: %s.", paste0(format(shape), collapse = ", ")) - } +#' @param unknown_batch (`logical(1)`)\cr +#' Whether the batch **must** be unknonw, i.e. `NA`. +#' If left `NULL` (default), the first dimension can be `NA` or not. +assert_shape = function(shape, null_ok = FALSE, coerce = TRUE, unknown_batch = NULL) { + result = check_shape(shape, null_ok = null_ok, unknown_batch = unknown_batch) + + if (!isTRUE(result)) stopf(result) + if (coerce && !is.null(shape)) { return(as.integer(shape)) } shape } -test_shape = function(shape, null_ok = FALSE) { + +#FIX SHAPE IN FIRST DIM: +# * should not happen for DataDescriptor (subsetting) +# * should not be possible in ModelDescriptor (makes no sense) +# * still, shapes_out() should also handle this case + +test_shape = function(shape, null_ok = FALSE, unknown_batch = NULL) { if (is.null(shape) && null_ok) { return(TRUE) } @@ -28,21 +37,26 @@ test_shape = function(shape, null_ok = FALSE) { return(FALSE) } - is_na = is.na(shape) if (anyNA(shape[-1L])) { return(FALSE) } - return(TRUE) + if (is.null(unknown_batch)) { + # first dim can be present or missing + return(TRUE) + } + return(is.na(shape[1L]) == unknown_batch) } -check_shape = function(x, null_ok = FALSE) { - if (test_shape(x, null_ok = null_ok)) { +check_shape = function(shape, null_ok = FALSE, unknown_batch = NULL) { + if (test_shape(shape, null_ok = null_ok, unknown_batch = unknown_batch)) { return(TRUE) } - "Must be a valid shape." + stopf("Invalid shape: %s.", paste0(format(shape), collapse = ", ")) } - -assert_shapes = function(shapes, named = TRUE, null_ok = FALSE) { # nolint - assert_list(shapes, names = if (named && !identical(unique(names(shapes)), "...")) "unique", min.len = 1L) - map(shapes, assert_shape, null_ok = null_ok) +assert_shapes = function(shapes, coerce = TRUE, named = FALSE, null_ok = FALSE, unknown_batch = NULL) { # nolint + ok = test_list(shapes, names = if (named && !identical(unique(names(shapes)), "...")) "unique", min.len = 1L) + if (!ok) { + stopf("Invalid shape") + } + map(shapes, assert_shape, coerce = coerce, null_ok = null_ok, unknown_batch = unknown_batch) } diff --git a/R/with_torch_settings.R b/R/with_torch_settings.R index 341043a8..c159915c 100644 --- a/R/with_torch_settings.R +++ b/R/with_torch_settings.R @@ -1,10 +1,15 @@ with_torch_settings = function(seed, num_threads, expr) { old_num_threads = torch_get_num_threads() - on.exit({torch_set_num_threads(old_num_threads)}, - add = TRUE - ) - - torch_set_num_threads(num_threads) + if (!running_on_mac()) { + 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.") + } + } # sets the seed back when exiting the function local_torch_manual_seed(seed) diff --git a/R/zzz.R b/R/zzz.R index 201011e9..c8c3949b 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -142,3 +142,4 @@ register_mlr3pipelines = function() { } leanify_package() + diff --git a/man-roxygen/preprocess_torchvision.R b/man-roxygen/preprocess_torchvision.R new file mode 100644 index 00000000..387f0c58 --- /dev/null +++ b/man-roxygen/preprocess_torchvision.R @@ -0,0 +1,13 @@ +#' <% pipeop = po(id) %> +#' @title <%= class(pipeop)[[1L]] %> +#' @usage NULL +#' @name mlr_pipeops_preproc_torch.<%= id %> +#' @rdname <%= class(pipeop)[[1L]] %> +#' @format [`R6Class`] inheriting from [`PipeOpTaskPreprocTorch`]. +#' +#' @description +#' Calls [`<%= paste0("torchvision::",gsub("^(augment|trafo)", "transform", id)) %>`], +#' see there for more information on the parameters. +#' +#' @section Parameters: +#' `r mlr3misc::rd_info(po("<%= id%>")$param_set)` diff --git a/man/DataDescriptor.Rd b/man/DataDescriptor.Rd index da1b4b5c..af55456d 100644 --- a/man/DataDescriptor.Rd +++ b/man/DataDescriptor.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/lazy_tensor.R +% Please edit documentation in R/DataDescriptor.R \name{DataDescriptor} \alias{DataDescriptor} \title{Data Descriptor} @@ -11,8 +11,8 @@ DataDescriptor( .input_map = NULL, .pointer = NULL, .pointer_shape = NULL, - clone_graph = TRUE, - .pointer_shape_predict = NULL + .pointer_shape_predict = NULL, + clone_graph = TRUE ) } \arguments{ @@ -41,21 +41,19 @@ Element 1 is the \code{PipeOp}'s id and element 2 is that \code{PipeOp}'s output \item{.pointer_shape}{(\code{integer} | \code{NULL})\cr Shape of the output indicated by \code{.pointer}.} -\item{clone_graph}{(\code{logical(1)})\cr -Whether to clone the preprocessing graph.} - \item{.pointer_shape_predict}{(\code{integer()} or \code{NULL})\cr Internal use only. Used in a \code{\link{Graph}} to anticipate possible mismatches between train and predict shapes.} + +\item{clone_graph}{(\code{logical(1)})\cr +Whether to clone the preprocessing graph.} } \description{ A data descriptor is a rather internal data structure used in the \code{\link{lazy_tensor}} data type. In essence it is an annotated \code{\link[torch:dataset]{torch::dataset}} and a preprocessing graph (consisting mosty of \code{\link{PipeOpModule}} operators). The additional meta data (e.g. pointer, shapes) allows to preprocess \code{\link{lazy_tensors}} in an \code{\link[mlr3pipelines:Graph]{mlr3pipelines::Graph}} just like any (non-lazy) data types. -To observe the effect of such a preprocessing, the \code{\link{materialize}} function can be used. - -This class is similar to the \code{\link{ModelDescriptor}} class, although there are some differences, see \emph{details}. +To observe the effect of such a preprocessing, \code{\link[=materialize]{materialize()}} can be used. } \examples{ # Create a dataset diff --git a/man/PipeOpPreprocTorchAugmentCenterCrop.Rd b/man/PipeOpPreprocTorchAugmentCenterCrop.Rd new file mode 100644 index 00000000..c4550367 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentCenterCrop.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_center_crop} +\alias{mlr_pipeops_preproc_torch.augment_center_crop} +\title{PipeOpPreprocTorchAugmentCenterCrop} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_center_crop]{torchvision::transform_center_crop}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + size \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentColorJitter.Rd b/man/PipeOpPreprocTorchAugmentColorJitter.Rd new file mode 100644 index 00000000..8c1aaa35 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentColorJitter.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_color_jitter} +\alias{mlr_pipeops_preproc_torch.augment_color_jitter} +\title{PipeOpPreprocTorchAugmentColorJitter} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_color_jitter]{torchvision::transform_color_jitter}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + brightness \tab untyped \tab - \tab \cr + contrast \tab untyped \tab - \tab \cr + saturation \tab untyped \tab - \tab \cr + hue \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentCrop.Rd b/man/PipeOpPreprocTorchAugmentCrop.Rd new file mode 100644 index 00000000..63bb990e --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentCrop.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_crop} +\alias{mlr_pipeops_preproc_torch.augment_crop} +\title{PipeOpPreprocTorchAugmentCrop} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_crop]{torchvision::transform_crop}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + top \tab untyped \tab - \tab \cr + left \tab untyped \tab - \tab \cr + height \tab untyped \tab - \tab \cr + width \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentHflip.Rd b/man/PipeOpPreprocTorchAugmentHflip.Rd new file mode 100644 index 00000000..0f2fa35f --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentHflip.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_hflip} +\alias{mlr_pipeops_preproc_torch.augment_hflip} +\title{PipeOpPreprocTorchAugmentHflip} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_hflip]{torchvision::transform_hflip}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRandomAffine.Rd b/man/PipeOpPreprocTorchAugmentRandomAffine.Rd new file mode 100644 index 00000000..a0cbdd60 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRandomAffine.Rd @@ -0,0 +1,43 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_random_affine} +\alias{mlr_pipeops_preproc_torch.augment_random_affine} +\title{PipeOpPreprocTorchAugmentRandomAffine} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. + +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_random_affine]{torchvision::transform_random_affine}}, +see there for more information on the parameters. + +Calls \code{\link[torchvision:transform_random_affine]{torchvision::transform_random_affine}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + degrees \tab untyped \tab - \tab \cr + translate \tab untyped \tab - \tab \cr + scale \tab untyped \tab - \tab \cr + shear \tab untyped \tab - \tab \cr + resample \tab untyped \tab - \tab \cr + fillcolor \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} + +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + degrees \tab untyped \tab - \tab \cr + translate \tab untyped \tab - \tab \cr + scale \tab untyped \tab - \tab \cr + shear \tab untyped \tab - \tab \cr + resample \tab untyped \tab - \tab \cr + fillcolor \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRandomApply.Rd b/man/PipeOpPreprocTorchAugmentRandomApply.Rd new file mode 100644 index 00000000..a4ed0276 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRandomApply.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_random_apply} +\alias{mlr_pipeops_preproc_torch.augment_random_apply} +\title{PipeOpPreprocTorchAugmentRandomApply} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_random_apply]{torchvision::transform_random_apply}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + transforms \tab untyped \tab - \tab \cr + p \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRandomChoice.Rd b/man/PipeOpPreprocTorchAugmentRandomChoice.Rd new file mode 100644 index 00000000..3cb74f9b --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRandomChoice.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_random_choice} +\alias{mlr_pipeops_preproc_torch.augment_random_choice} +\title{PipeOpPreprocTorchAugmentRandomChoice} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_random_choice]{torchvision::transform_random_choice}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + transforms \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRandomCrop.Rd b/man/PipeOpPreprocTorchAugmentRandomCrop.Rd new file mode 100644 index 00000000..80fb2806 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRandomCrop.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_random_crop} +\alias{mlr_pipeops_preproc_torch.augment_random_crop} +\title{PipeOpPreprocTorchAugmentRandomCrop} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_random_crop]{torchvision::transform_random_crop}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + size \tab untyped \tab - \tab \cr + padding \tab untyped \tab - \tab \cr + pad_if_needed \tab untyped \tab - \tab \cr + fill \tab untyped \tab - \tab \cr + padding_mode \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd b/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd new file mode 100644 index 00000000..f74fb02c --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_random_horizontal_flip} +\alias{mlr_pipeops_preproc_torch.augment_random_horizontal_flip} +\title{PipeOpPreprocTorchAugmentRandomHorizontalFlip} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_random_horizontal_flip]{torchvision::transform_random_horizontal_flip}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + p \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRandomOrder.Rd b/man/PipeOpPreprocTorchAugmentRandomOrder.Rd new file mode 100644 index 00000000..9c9f63ed --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRandomOrder.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_random_order} +\alias{mlr_pipeops_preproc_torch.augment_random_order} +\title{PipeOpPreprocTorchAugmentRandomOrder} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_random_order]{torchvision::transform_random_order}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + transforms \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd b/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd new file mode 100644 index 00000000..e1afb8c8 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_random_resized_crop} +\alias{mlr_pipeops_preproc_torch.augment_random_resized_crop} +\title{PipeOpPreprocTorchAugmentRandomResizedCrop} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_random_resized_crop]{torchvision::transform_random_resized_crop}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + size \tab untyped \tab - \tab \cr + scale \tab untyped \tab - \tab \cr + ratio \tab untyped \tab - \tab \cr + interpolation \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd b/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd new file mode 100644 index 00000000..64273352 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_random_vertical_flip} +\alias{mlr_pipeops_preproc_torch.augment_random_vertical_flip} +\title{PipeOpPreprocTorchAugmentRandomVerticalFlip} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_random_vertical_flip]{torchvision::transform_random_vertical_flip}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + p \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentResizedCrop.Rd b/man/PipeOpPreprocTorchAugmentResizedCrop.Rd new file mode 100644 index 00000000..a3f47126 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentResizedCrop.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_resized_crop} +\alias{mlr_pipeops_preproc_torch.augment_resized_crop} +\title{PipeOpPreprocTorchAugmentResizedCrop} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_resized_crop]{torchvision::transform_resized_crop}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + top \tab untyped \tab - \tab \cr + left \tab untyped \tab - \tab \cr + height \tab untyped \tab - \tab \cr + width \tab untyped \tab - \tab \cr + size \tab untyped \tab - \tab \cr + interpolation \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRotate.Rd b/man/PipeOpPreprocTorchAugmentRotate.Rd new file mode 100644 index 00000000..f1e9c90e --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRotate.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_rotate} +\alias{mlr_pipeops_preproc_torch.augment_rotate} +\title{PipeOpPreprocTorchAugmentRotate} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_rotate]{torchvision::transform_rotate}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + angle \tab untyped \tab - \tab \cr + resample \tab untyped \tab - \tab \cr + expand \tab untyped \tab - \tab \cr + center \tab untyped \tab - \tab \cr + fill \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentVflip.Rd b/man/PipeOpPreprocTorchAugmentVflip.Rd new file mode 100644 index 00000000..73a4b7ab --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentVflip.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_vflip} +\alias{mlr_pipeops_preproc_torch.augment_vflip} +\title{PipeOpPreprocTorchAugmentVflip} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_vflip]{torchvision::transform_vflip}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd b/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd new file mode 100644 index 00000000..7a7c0677 --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_adjust_brightness} +\alias{mlr_pipeops_preproc_torch.trafo_adjust_brightness} +\title{PipeOpPreprocTorchTrafoAdjustBrightness} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_adjust_brightness]{torchvision::transform_adjust_brightness}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + brightness_factor \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd b/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd new file mode 100644 index 00000000..129d03e7 --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_adjust_gamma} +\alias{mlr_pipeops_preproc_torch.trafo_adjust_gamma} +\title{PipeOpPreprocTorchTrafoAdjustGamma} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_adjust_gamma]{torchvision::transform_adjust_gamma}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + gamma \tab untyped \tab - \tab \cr + gain \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoAdjustHue.Rd b/man/PipeOpPreprocTorchTrafoAdjustHue.Rd new file mode 100644 index 00000000..0d035a21 --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoAdjustHue.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_adjust_hue} +\alias{mlr_pipeops_preproc_torch.trafo_adjust_hue} +\title{PipeOpPreprocTorchTrafoAdjustHue} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_adjust_hue]{torchvision::transform_adjust_hue}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + hue_factor \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd b/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd new file mode 100644 index 00000000..27cf36c3 --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_adjust_saturation} +\alias{mlr_pipeops_preproc_torch.trafo_adjust_saturation} +\title{PipeOpPreprocTorchTrafoAdjustSaturation} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_adjust_saturation]{torchvision::transform_adjust_saturation}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + saturation_factor \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoGrayscale.Rd b/man/PipeOpPreprocTorchTrafoGrayscale.Rd new file mode 100644 index 00000000..a438c1da --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoGrayscale.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_grayscale} +\alias{mlr_pipeops_preproc_torch.trafo_grayscale} +\title{PipeOpPreprocTorchTrafoGrayscale} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_grayscale]{torchvision::transform_grayscale}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + num_output_channels \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoNop.Rd b/man/PipeOpPreprocTorchTrafoNop.Rd new file mode 100644 index 00000000..f6a95fb8 --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoNop.Rd @@ -0,0 +1,11 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_nop} +\alias{mlr_pipeops_preproc_torch.trafo_nop} +\title{PipeOpPreprocTorchTrafoNop} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Does nothing. +} diff --git a/man/PipeOpPreprocTorchTrafoNormalize.Rd b/man/PipeOpPreprocTorchTrafoNormalize.Rd new file mode 100644 index 00000000..330789f7 --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoNormalize.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_normalize} +\alias{mlr_pipeops_preproc_torch.trafo_normalize} +\title{PipeOpPreprocTorchTrafoNormalize} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_normalize]{torchvision::transform_normalize}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + mean \tab untyped \tab - \tab \cr + std \tab untyped \tab - \tab \cr + inplace \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoPad.Rd b/man/PipeOpPreprocTorchTrafoPad.Rd new file mode 100644 index 00000000..a166c824 --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoPad.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_pad} +\alias{mlr_pipeops_preproc_torch.trafo_pad} +\title{PipeOpPreprocTorchTrafoPad} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_pad]{torchvision::transform_pad}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + padding \tab untyped \tab - \tab \cr + fill \tab untyped \tab - \tab \cr + padding_mode \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoResize.Rd b/man/PipeOpPreprocTorchTrafoResize.Rd new file mode 100644 index 00000000..6d2e4f40 --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoResize.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_resize} +\alias{mlr_pipeops_preproc_torch.trafo_resize} +\title{PipeOpPreprocTorchTrafoResize} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_resize]{torchvision::transform_resize}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + size \tab untyped \tab - \tab \cr + interpolation \tab character \tab 2 \tab Undefined, Bartlett, Blackman, Bohman, Box, Catrom, Cosine, Cubic, Gaussian, Hamming, \link{...} \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd b/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd new file mode 100644 index 00000000..4ec26426 --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_rgb_to_grayscale} +\alias{mlr_pipeops_preproc_torch.trafo_rgb_to_grayscale} +\title{PipeOpPreprocTorchTrafoRgbToGrayscale} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_rgb_to_grayscale]{torchvision::transform_rgb_to_grayscale}}, +see there for more information on the parameters. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/assert_shape.Rd b/man/assert_shape.Rd index 915869ad..8a8ebb07 100644 --- a/man/assert_shape.Rd +++ b/man/assert_shape.Rd @@ -2,15 +2,23 @@ % Please edit documentation in R/shape.R \name{assert_shape} \alias{assert_shape} -\title{Check Shape} +\title{Checks whether an integer vector is a valid shape. +Unknown shapes are represted as \code{NULL}.} \usage{ -assert_shape(shape, null_ok = FALSE) +assert_shape(shape, null_ok = FALSE, coerce = TRUE, unknown_batch = NULL) } \arguments{ \item{shape}{(\code{integer()})\cr} \item{null_ok}{(\code{logical(1)})\cr Whether \code{NULL} is a valid shape.} + +\item{coerce}{(\code{logical(1)})\cr +Whether to coerce the input to an \code{integer()} if possible.} + +\item{unknown_batch}{(\code{logical(1)})\cr +Whether the batch \strong{must} be unknonw, i.e. \code{NA}. +If left \code{NULL} (default), the first dimension can be \code{NA} or not.} } \description{ Checks whether an integer vector is a valid shape. diff --git a/man/mlr_pipeops_preproc_torch.Rd b/man/mlr_pipeops_preproc_torch.Rd index 0ef44712..338200bb 100644 --- a/man/mlr_pipeops_preproc_torch.Rd +++ b/man/mlr_pipeops_preproc_torch.Rd @@ -15,7 +15,8 @@ To create custom preprocessing \code{PipeOp}s you can use \code{\link{pipeop_pre } \section{Inheriting}{ -In addition to specifying the construction arguments, you can overwrite the private \code{.shapes_out()} method: +In addition to specifying the construction arguments, you can overwrite the private \code{.shapes_out()} method. +If you don't overwrite it, the output shapes are assumed to be unknown (\code{NULL}). \itemize{ \item \code{.shapes_out(shapes_in, param_vals, task)}\cr (\code{list()}, \verb{list(), }Task\code{or}NULL\verb{) -> }list()\verb{\\cr This private method calculates the output shapes of the lazy tensor columns that are created from applying the preprocessing function with the provided parameter values (}param_vals\verb{). The }task\verb{is very rarely needed, but if it is it should be checked that it is not}NULL`. @@ -24,8 +25,7 @@ This private method only has the responsibility to calculate the output shapes f input \code{shapes_in} can be assumed to have exactly one shape vector for which it must calculate the output shapes and return it as a \code{list()} of length 1. It can also be assumed that the shape is not \code{NULL} (i.e. unknown). -It should output a shape with exactly one NA in the first (batch) dimension or \code{NULL}if the output shape cannot be -determined (e.g. because it is random). +Also, the first dimension can be \code{NA}, i.e. is unknown (as for the batch dimension). } } @@ -44,28 +44,39 @@ TODO: In addition to the parameters inherited from \code{\link{PipeOpTaskPreproc}} as well as those specified during construction as the argument \code{param_set} there are the following parameters: \itemize{ -\item \code{augment} :: \code{logical(1)}\cr -(This parameter only exists of the \code{PipeOp}) is applied per column. -Whether the to apply the preprocessing only during training (\code{TRUE}) or also during prediction (\code{FALSE}). -This parameter is initialized to \code{FALSE}. -} - +\item \code{stages} :: \code{character(1)}\cr +The stages during which to apply the preprocessing. +Can be one of \code{"train"}, \code{"predict"} or \code{"both"}. +The initial value of this parameter is set to \code{"train"} when the \code{PipeOp}'s id starts with \code{"augment_"} and +to \code{"both"} otherwise. +o Note that the preprocessing that is applied during \verb{$predict()} uses the parameters that were set during \verb{$train()} and not those that are set when performing the prediction. } +} \section{Internals}{ -A \code{\link{PipeOpModule}} with one input and one output channel is created. -The pipeop simply applies the function \code{fn} to the input tensor while additionally -passing the parameter values (minus \code{augment} and \code{affect_columns}) to \code{fn}. -In addition, the new shapes are calculates using the \verb{$shapes_out()} method. -Then, new lazy tensor columns with updated preprocessing graphs and metadata are created. -This mechanism is very similar to the \code{\link{ModelDescriptor}} mechanism that is being used to construct -neural network architectures. Read the (Internals) documentation of \code{\link{PipeOpTorch}} for this. - -We also add the shape that would be present during a \verb{$predict()} call, this information can later be used -to check whether the train-preprocessing and the predict-preprocessing are compatible. +During \verb{$train()} / \verb{$predict()}, a \code{\link{PipeOpModule}} with one input and one output channel is created. +The pipeop applies the function \code{fn} to the input tensor while additionally +passing the parameter values (minus \code{stages} and \code{affect_columns}) to \code{fn}. +The preprocessing graph of the lazy tensor columns is shallowly cloned and the \code{PipeOpModule} is added. +This is done to avoid modifying user input and means that identical \code{PipeOpModule}s can be part of different +preprocessing graphs. This is possible, because the created \code{PipeOpModule} is stateless. +At a later point, graphs will be merged if possible to avoid unnecessary computation. +This is best illustrated by example: +One lazy tensor column's preprocessing graph is \code{A -> B}. +Then, two branches are created \code{B -> C} and \code{B -> D}, creating two preprocessing graphs +\code{A -> B -> C} and \code{A -> B -> D}. When loading the data, we want to run the preprocessing only once, i.e. +the \code{A -> B} part. For this reason, \code{\link[=task_dataset]{task_dataset()}} will try to merge graphs and cache results from graphs. + +Also, the shapes created during \verb{$train()} and \verb{$predict()} might differ. +To avoid the creation of graphs where the predict shapes are incompatible with the train shapes, +the hypothetical predict shapes are already calculated during \verb{$train()} (hence the parameters that are set during +train are also used during predict) and the \code{\link{PipeOpTorchModel}} will check the train and predict shapes for +compatibility before starting the training. + +Otherwise, this mechanism is very similar to the \code{\link{ModelDescriptor}} construct. } \examples{ @@ -81,15 +92,15 @@ taskin = as_task_regr(d, target = "y") # Creating a simple preprocessing pipeop po_simple = po("preproc_torch", - # use mlr3misc::crate to get rid of unnecessary environment baggage + # get rid of environment baggage fn = mlr3misc::crate(function(x, a) x + a), - param_set = ps(a = p_int(tags = c("train", "predict", "required"))) + param_set = ps(a = p_int(tags = c("train", "required"))) ) po_simple$param_set$set_values( a = 100, affect_columns = selector_name(c("x1", "x2")), - augment = FALSE + stages = "both" # use during train and predict ) taskout_train = po_simple$train(list(taskin))[[1L]] @@ -99,7 +110,7 @@ taskout_predict_noaug = po_simple$predict(list(taskin))[[1L]] materialize(taskout_predict_noaug$data(cols = c("x1", "x2")), rbind = TRUE) po_simple$param_set$set_values( - augment = TRUE + stages = "train" ) # transformation is not applied @@ -107,57 +118,62 @@ taskout_predict_aug = po_simple$predict(list(taskin))[[1L]] materialize(taskout_predict_aug$data(cols = c("x1", "x2")), rbind = TRUE) # Creating a more complex preprocessing PipeOp - -PipeOpPreprocTorchPoly = R6::R6Class("PipeOpPreprocTorchPoly", - inherit = PipeOpTaskPreprocTorch, - public = list( - initialize = function(id = "preproc_poly", param_vals = list()) { - param_set = paradox::ps( - n_degree = paradox::p_int(lower = 1L, tags = c("train", "required")) - ) - param_set$set_values( - n_degree = 1L - ) - fn = mlr3misc::crate(function(x, n_degree) { - torch::torch_cat( - lapply(seq_len(n_degree), function(d) torch_pow(x, d)), - dim = 2L - ) - }) - - super$initialize( - fn = fn, - id = id, - packages = character(0), - param_vals = param_vals, - param_set = param_set - ) - } - ), - private = list( - .shapes_out = function(shapes_in, param_vals, task) { - # shapes_in is a list of length 1 containing the shapes - checkmate::assert_true(length(shapes_in[[1L]]) == 2L) - if (shapes_in[[1L]][2L] != 1L) { - stop("Input shape must be (NA, 1)") - } - list(c(NA, param_vals$n_degree)) - } - ) +po_poly = pipeop_preproc_torch( + public = list( + initialize = function(id = "preproc_poly", param_vals = list()) { + param_set = paradox::ps( + n_degree = paradox::p_int(lower = 1L, tags = c("train", "required")) + ) + param_set$set_values( + n_degree = 1L + ) + fn = mlr3misc::crate(function(x, n_degree) { + torch::torch_cat( + lapply(seq_len(n_degree), function(d) torch_pow(x, d)), + dim = 2L + ) + }) + + super$initialize( + fn = fn, + id = id, + packages = character(0), + param_vals = param_vals, + param_set = param_set + ) + } + ), + private = list( + .shapes_out = function(shapes_in, param_vals, task) { + # shapes_in is a list of length 1 containing the shapes + checkmate::assert_true(length(shapes_in[[1L]]) == 2L) + if (shapes_in[[1L]][2L] != 1L) { + stop("Input shape must be (NA, 1)") + } + list(c(NA, param_vals$n_degree)) + } + ) ) po_poly = PipeOpPreprocTorchPoly$new( - param_vals = list(n_degree = 3L, affect_columns = selector_name("x3")) + param_vals = list(n_degree = 3L, affect_columns = selector_name("x3")) ) po_poly$shapes_out(list(c(NA, 1L))) -taskout = po_poly$train(list(taskin))[[1L]] +taskout = po_poly$train(list(tasken))[[1L]] materialize(taskout$data(cols = "x3"), rbind = TRUE) } \section{Super classes}{ \code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3pipelines:PipeOpTaskPreproc]{mlr3pipelines::PipeOpTaskPreproc}} -> \code{PipeOpTaskPreprocTorch} } +\section{Active bindings}{ +\if{html}{\out{
}} +\describe{ +\item{\code{fn}}{The preprocessing function.} +} +\if{html}{\out{
}} +} \section{Methods}{ \subsection{Public methods}{ \itemize{ @@ -188,7 +204,8 @@ Creates a new instance of this \code{\link[R6:R6Class]{R6}} class. param_vals = list(), param_set = ps(), packages = character(0), - augment_init = FALSE + stages_init = "both", + rowwise = FALSE )}\if{html}{\out{}} } @@ -212,8 +229,12 @@ All tags should be set to \code{"train"}.} \item{\code{packages}}{(\code{character()})\cr The packages the preprocessing function depends on.} -\item{\code{augment_init}}{(\code{logical(1)})\cr -Initial value for the \code{augment} parameter.} +\item{\code{stages_init}}{(\code{logical(1)})\cr +Initial value for the \code{stages} parameter.} + +\item{\code{rowwise}}{(\code{logical(1)})\cr +Whether the preprocessing function is applied rowwise (and then concatenated by row) or directly to the whole +tensor.} } \if{html}{\out{}} } @@ -225,7 +246,7 @@ Initial value for the \code{augment} parameter.} Calculates the output shapes that would result in applying the preprocessing to one or more lazy tensor columns with the provided shape. Names are ignored and only order matters. -It uses the parameeter values that are currently set. +It uses the parameter values that are currently set. \subsection{Usage}{ \if{html}{\out{
}}\preformatted{PipeOpTaskPreprocTorch$shapes_out(shapes_in, stage = NULL, task = NULL)}\if{html}{\out{
}} } @@ -235,7 +256,8 @@ It uses the parameeter values that are currently set. \describe{ \item{\code{shapes_in}}{(\code{list()} of (\code{integer()} or \code{NULL}))\cr The input input shapes of the lazy tensors. -\code{NULL} indicates that the shape is unknown.} +\code{NULL} indicates that the shape is unknown. +First dimension must be \code{NA}.} \item{\code{stage}}{(\code{character(1)})\cr The stage: either \code{"train"} or \code{"predict"}.} diff --git a/man/mlr_pipeops_preproc_torch_overview.Rd b/man/mlr_pipeops_preproc_torch_overview.Rd deleted file mode 100644 index 3f0c9fca..00000000 --- a/man/mlr_pipeops_preproc_torch_overview.Rd +++ /dev/null @@ -1,19 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch_overview} -\alias{mlr_pipeops_preproc_torch_overview} -\alias{PipeOpPreprocTorchTrafoResize} -\alias{PipeOpPreprocTorchTrafoNop} -\title{Lazy Preprocessing and Transformations} -\description{ -Overview over all implemented preprocessing methods. -See \code{\link{PipeOpTaskPreprocTorch}} for more details on the class itself. - -\itemize{ -\item \code{trafo_resize}: Calls \code{\link[torchvision:transform_resize]{torchvision::transform_resize}} -} - -\itemize{ -\item \code{trafo_nop}: Calls \code{identity()}. -} -} diff --git a/man/mlr_pipeops_torch_ingress_ltnsr.Rd b/man/mlr_pipeops_torch_ingress_ltnsr.Rd index a4863be4..bf83bb00 100644 --- a/man/mlr_pipeops_torch_ingress_ltnsr.Rd +++ b/man/mlr_pipeops_torch_ingress_ltnsr.Rd @@ -11,9 +11,8 @@ Ingress for a single \code{\link{lazy_tensor}} column. \itemize{ \item \code{shape} :: \code{integer()}\cr -The shape of the tensor, excluding the batch dimension. +The shape of the tensor, where the first dimension (batch) must be \code{NA}. Whether it is necessary to specify the shape depends on whether the lazy tensor input column has a known shape. -If the input shape is known, this parameter can be set, but must match the input shape. } } @@ -75,7 +74,6 @@ x_batch2 = ingress2[[1L]]$batchgetter( ) x_batch2 - } \seealso{ Other PipeOps: diff --git a/man/pipeop_preproc_torch.Rd b/man/pipeop_preproc_torch.Rd index eeeb815e..1bd767f8 100644 --- a/man/pipeop_preproc_torch.Rd +++ b/man/pipeop_preproc_torch.Rd @@ -20,11 +20,12 @@ The id for of the new object.} \item{fn}{(\code{function})\cr The preprocessing function.} -\item{shapes_out}{(\code{function} or \code{NULL} or "infer")\cr +\item{shapes_out}{(\code{function} or \code{NULL} or \code{"infer"} or \code{"unchanged"})\cr The private \code{.shapes_out(shapes_in, param_vals, task)} method of \code{\link{PipeOpTaskPreprocTorch}} (see section Inheriting). -If \code{NULL}, the pipeop does not change the output shapes. -If \code{TRUE}, the output shape function is inferred and calculates the output shapes as follows: +Special values are \code{NULL} and \code{infer}: +If \code{NULL}, the output shapes are unknown. +If "infer", the output shape function is inferred and calculates the output shapes as follows: For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. diff --git a/man/pipeop_preproc_torch_class.Rd b/man/pipeop_preproc_torch_class.Rd index f3039f01..0f0b3637 100644 --- a/man/pipeop_preproc_torch_class.Rd +++ b/man/pipeop_preproc_torch_class.Rd @@ -9,7 +9,9 @@ pipeop_preproc_torch_class( fn, shapes_out, param_set = NULL, - packages = character(0) + packages = character(0), + init_params = list(), + rowwise = FALSE ) } \arguments{ @@ -19,11 +21,12 @@ The id for of the new object.} \item{fn}{(\code{function})\cr The preprocessing function.} -\item{shapes_out}{(\code{function} or \code{NULL} or "infer")\cr +\item{shapes_out}{(\code{function} or \code{NULL} or \code{"infer"} or \code{"unchanged"})\cr The private \code{.shapes_out(shapes_in, param_vals, task)} method of \code{\link{PipeOpTaskPreprocTorch}} (see section Inheriting). -If \code{NULL}, the pipeop does not change the output shapes. -If \code{TRUE}, the output shape function is inferred and calculates the output shapes as follows: +Special values are \code{NULL} and \code{infer}: +If \code{NULL}, the output shapes are unknown. +If "infer", the output shape function is inferred and calculates the output shapes as follows: For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. diff --git a/tests/testthat/helper_autotest.R b/tests/testthat/helper_autotest.R index 266ebe44..3a6cfddc 100644 --- a/tests/testthat/helper_autotest.R +++ b/tests/testthat/helper_autotest.R @@ -117,10 +117,23 @@ autotest_pipeop_torch = function(graph, id, task, module_class = id, exclude_arg names(channels) = paste0("output", "_", tmp1$src_id, "_", tmp1$src_channel, ".", tmp1$src_channel) names(layerin) = channels[names(channels)] + # check that shapes are compatible when passing batch dimension predicted = po_test$shapes_out(map(layerin, dim), task) observed = map(layerout, dim) expect_compatible_shapes(predicted, observed) + # check that shapes are compatible without batch dimension as NA + predicted_unknown_batch = po_test$shapes_out(map(layerin, function(d) { + x = dim(d) + x[1L] = NA + x + }), task) + + expect_error(assert_shapes(predicted_unknown_batch, null_ok = FALSE, unknown_batch = TRUE), regexp = NA) + + expect_compatible_shapes(predicted_unknown_batch, observed) + + # parameters must only ce active during training walk(po_test$param_set$params, function(p) { if (!(("train" %in% p$tags) && !("predict" %in% p$tags))) { @@ -333,11 +346,11 @@ autotest_pipeop_torch_preprocess = function(obj, shapes_in, exclude = character( class = get(class(obj)[[1L]], envir = getNamespace("mlr3torch")) instance = class$new() - expect_true(grepl(instance$id, pattern = "^(trafo|augment)_")) + testthat::expect_true(grepl(instance$id, pattern = "^(trafo|augment)_")) if (startsWith(instance$id, "augment")) { expect_set_equal(instance$param_set$values$stages, "train") } else { - expect_set_equal(instance$param_set$values$stages, c("train", "predict")) + expect_set_equal(instance$param_set$values$stages, "both") } shapes_in = if (!test_list(shapes_in)) list(shapes_in) else shapes_in @@ -356,6 +369,8 @@ autotest_pipeop_torch_preprocess = function(obj, shapes_in, exclude = character( expect_class(tnsr_out, "torch_tensor") - expect_equal(tnsr_out$shape, shape_out) + if (!is.null(shape_out)) { + testthat::expect_equal(tnsr_out$shape, shape_out) + } }) } diff --git a/tests/testthat/helper_tasks.R b/tests/testthat/helper_tasks.R index 270055b7..9ea1eded 100644 --- a/tests/testthat/helper_tasks.R +++ b/tests/testthat/helper_tasks.R @@ -2,7 +2,7 @@ nano_dogs_vs_cats = function(id = "nano_dogs_vs_cats") { assert_string(id) path = testthat::test_path("assets", "nano_dogs_vs_cats") image_names = list.files(path) - uris = normalizePath(file.path(path, image_names)) + uris = fs::path_norm(file.path(path, image_names)) ds = dataset("dogs_vs_cats", initialize = function(uris) { @@ -79,7 +79,7 @@ nano_imagenet = function(id = "nano_imagenet") { path = testthat::test_path("assets", "nano_imagenet") image_names = list.files(path) - uris = normalizePath(file.path(path, image_names)) + uris = fs::path_norm(file.path(path, image_names)) images = imageuri(uris) diff --git a/tests/testthat/test_DataDescriptor.R b/tests/testthat/test_DataDescriptor.R new file mode 100644 index 00000000..a27eb6ea --- /dev/null +++ b/tests/testthat/test_DataDescriptor.R @@ -0,0 +1,36 @@ +test_that("DataDescriptor works", { + ds = dataset( + initialize = function() { + self$x = torch_randn(10, 5, 3) + }, + .getitem = function(i) { + list(x = self$x[i, ..]) + }, + .length = function() { + nrow(self$x) + } + )() + + dd = DataDescriptor(ds, dataset_shapes = list(x = c(NA, 5, 3))) + expect_class(dd, "DataDescriptor") + expect_equal(dd$.pointer_shape, c(NA, 5, 3)) + expect_class(dd$graph$pipeops[[1L]], "PipeOpNOP") + expect_true(length(dd$graph$pipeops) == 1L) + expect_equal(dd$.pointer, c(dd$graph$output$op.id, dd$graph$output$channel.name)) + expect_string(dd$.dataset_hash) + expect_string(dd$.hash) + expect_false(dd$.dataset_hash == dd$.hash) + + dd1 = DataDescriptor(ds, dataset_shapes = list(x = c(NA, 5, 3))) + expect_equal(dd$dataset_shapes, dd1$dataset_shapes) + + # dataset shapes must be provided + expect_error(DataDescriptor(ds), "missing") + # batch must always be NA + expect_error(DataDescriptor(ds, dataset_shapes = c(10, 5, 3))) + + graph = as_graph(po("nop", id = "nop")) + + expect_error(DataDescriptor(ds, dataset_shapes = list(x = c(NA, 5, 4)), "When passing a graph")) +}) + diff --git a/tests/testthat/test_LearnerTorch.R b/tests/testthat/test_LearnerTorch.R index 89a964c5..8fc74e95 100644 --- a/tests/testthat/test_LearnerTorch.R +++ b/tests/testthat/test_LearnerTorch.R @@ -200,7 +200,7 @@ test_that("train parameters do what they should: classification and regression", epochs = sample(3, 1) batch_size = sample(16, 1) shuffle = sample(c(TRUE, FALSE), 1) - num_threads = sample(2, 1) + num_threads = if (running_on_mac()) 1L else sample(2, 1) drop_last = sample(c(TRUE, FALSE), 1) seed = sample.int(10, 1) measures_train = msrs(paste0(measure_ids[sample(c(TRUE, FALSE, TRUE), 3, replace = FALSE)])) @@ -230,7 +230,9 @@ test_that("train parameters do what they should: classification and regression", internals = learner$model$callbacks$internals ctx = internals$ctx1 - expect_equal(num_threads, internals$num_threads) + if (!running_on_mac()) { + expect_equal(num_threads, internals$num_threads) + } expect_equal(ctx$loader_train$batch_size, batch_size) expect_equal(ctx$loader_valid$batch_size, batch_size) expect_equal(ctx$total_epochs, epochs) @@ -319,7 +321,7 @@ test_that("predict parameters do what they should: classification and regression ) f = function(task_type) { - num_threads = sample(2, 1) + num_threads = if (running_on_mac()) 1L else sample(2, 1) batch_size = sample(16, 1) learner = lrn(paste0(task_type, ".torch_featureless"), epochs = 1, callbacks = callback, num_threads = num_threads, @@ -330,7 +332,9 @@ test_that("predict parameters do what they should: classification and regression learner$train(task) internals = learner$model$callbacks$internals ctx = internals$ctx1 - expect_equal(num_threads, internals$num_threads) + if (!running_on_mac()) { + expect_equal(num_threads, internals$num_threads) + } learner$param_set$set_values(device = "meta") try(learner$predict(task), silent = TRUE) @@ -384,7 +388,7 @@ test_that("Input verification works during `$train()` (train-predict shapes work task = nano_mnist() task_invalid = po("trafo_resize", size = c(10, 10), stages = "train") $train(list(task))[[1L]] - task_valid = po("trafo_resize", size = c(10, 10), stages = c("train", "predict")) $train(list(task))[[1L]] + task_valid = po("trafo_resize", size = c(10, 10), stages = "both") $train(list(task))[[1L]] learner = lrn("classif.torch_featureless", batch_size = 1L, epochs = 0L diff --git a/tests/testthat/test_ModelDescriptor.R b/tests/testthat/test_ModelDescriptor.R index 76368145..cb81e1ec 100644 --- a/tests/testthat/test_ModelDescriptor.R +++ b/tests/testthat/test_ModelDescriptor.R @@ -33,7 +33,7 @@ test_that("ModelDescriptor basic checks", { expect_identical(md$ingress, ingresslist) expect_identical(md$callbacks, list(checkpoint = cb)) expect_identical(md$.pointer, pointer) - expect_identical(md$.pointer_shape, pointer_shape) + expect_equal(md$.pointer_shape, pointer_shape) repr = capture.output(md) expected = c( diff --git a/tests/testthat/test_PipeOpTaskPreprocTorch.R b/tests/testthat/test_PipeOpTaskPreprocTorch.R index 181a3c9c..203314c8 100644 --- a/tests/testthat/test_PipeOpTaskPreprocTorch.R +++ b/tests/testthat/test_PipeOpTaskPreprocTorch.R @@ -82,7 +82,7 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { torch_sum(materialize(po_test2$predict(list(task))[[1L]]$data(cols = "x1")[[1L]], rbind = TRUE))$item() == 0 ) - # stages parameter works as intended (above stages was set to c("train", "predict")) + # stages parameter works as intended (above stages was set to "both") po_test2$param_set$set_values( stages = "train" @@ -104,9 +104,11 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { materialize(po_test$train(list(task))[[1L]]$data(cols = "x1")[[1L]], rbind = TRUE) ) - expet_identical) - u - materialie(task$data(cols = "x1")[[1L]] + # TODO: + # need to finish the augment -> stages transition, i.e. add tests and "both", then finish the preprocess impmenetation. add the tests and test the preprocess autotest + # also test that the rowwise parameter works + + materialize(task$data(cols = "x1")[[1L]]) }) @@ -124,7 +126,7 @@ test_that("PipeOptaskPreprocTorch: shapes_out() works", { expect_identical(po_resize$shapes_out(list(x = NULL, y = c(NA, 3, 5, 5)), stage = "predict"), list(NULL, c(NA, 3, 5, 5))) # predict when stages is c("train", "predict"") - po_resize$param_set$set_values(stages = c("train", "predict")) + po_resize$param_set$set_values(stages = "both") po_resize$train(list(task)) expect_identical(po_resize$shapes_out(list(x = NULL), stage = "predict"), list(NULL)) expect_identical(po_resize$shapes_out(list(x = NULL, y = c(NA, 3, 5, 5)), stage = "predict"), list(NULL, c(NA, 3, 10, 10))) @@ -138,7 +140,8 @@ test_that("PipeOpTaskPreprocTorch modifies the underlying lazy tensor columns co taskin = as_task_regr(d, target = "y") - po_test = po("preproc_torch", fn = crate(function(x, a) x + a), param_set = ps(a = p_int(tags = c("train", ""))), a = -10) + po_test = po("preproc_torch", fn = crate(function(x, a) x + a), param_set = ps(a = p_int(tags = c("train", ""))), + a = -10, rowwise = FALSE) taskout_train = po_test$train(list(taskin))[[1L]] taskout_pred = po_test$predict(list(taskin))[[1L]] @@ -216,6 +219,5 @@ test_that("predict shapes are added during training", { taskout = po_test$train(list(task))[[1L]] - # TODO: - }) + diff --git a/tests/testthat/test_PipeOpTorch.R b/tests/testthat/test_PipeOpTorch.R index 50068ee6..0c52fbe7 100644 --- a/tests/testthat/test_PipeOpTorch.R +++ b/tests/testthat/test_PipeOpTorch.R @@ -111,7 +111,7 @@ test_that("train handles multiple input channels correctly", { expect_equal(mdout2$.pointer_shape, c(NA, 3)) }) -test_that("shapes_out works", { +test_that("shapes_out", { obj = po("nn_linear", out_features = 3) # single input @@ -125,7 +125,7 @@ test_that("shapes_out works", { obj1$param_set$set_values(d_out1 = 2, d_out2 = 3) expect_equal(obj1$shapes_out(list(c(NA, 99), c(NA, 3))), list(output1 = c(NA, 2), output2 = c(NA, 3))) - expect_error(obj1$shapes_out(list(c(NA, 99))), regexp = "Must have length 2") + expect_error(obj1$shapes_out(list(c(NA, 99))), regexp = "number of input") }) test_that("PipeOpTorch errs when there are unexpected NAs in the shape", { diff --git a/tests/testthat/test_PipeOpTorchIngress.R b/tests/testthat/test_PipeOpTorchIngress.R index f50f3d2f..2ffb1ca8 100644 --- a/tests/testthat/test_PipeOpTorchIngress.R +++ b/tests/testthat/test_PipeOpTorchIngress.R @@ -45,14 +45,5 @@ test_that("PipeOpTorchIngressLazyTensor", { task$cbind(data.frame(row_id = 1:10, x_num = 1:10)) expect_po_ingress(po_ingress, task) - graph = po("torch_ingress_ltnsr") %>>% - po("nn_flatten") %>>% - po("nn_linear", out_features = 10) %>>% - po("nn_relu") %>>% - po("nn_head") %>>% - po("torch_loss", "cross_entropy") %>>% - po("torch_optimizer") %>>% - po("torch_model_classif", epochs = 1L, device = "cpu", batch_size = 16) - - graph$train(task_old) + expect_error(po_ingress$param_set$set_values(shape = c(22, 4))) }) diff --git a/tests/testthat/test_TaskClassif_tiny_imagenet.R b/tests/testthat/test_TaskClassif_tiny_imagenet.R index 3d4133ed..4b3b1b84 100644 --- a/tests/testthat/test_TaskClassif_tiny_imagenet.R +++ b/tests/testthat/test_TaskClassif_tiny_imagenet.R @@ -14,6 +14,7 @@ test_that("tiny_imagenet works", { expect_equal(task$feature_names, "image") expect_equal(task$target_names, "class") expect_equal(task$man, "mlr3torch::mlr_tasks_tiny_imagenet") + task$data() expect_true("tiny-imagenet-200" %in% list.files(file.path(get_cache_dir(), "datasets", "tiny_imagenet", "raw"))) expect_true("data.rds" %in% list.files(file.path(get_cache_dir(), "datasets", "tiny_imagenet"))) expect_equal(task$backend$nrow, 120000) diff --git a/tests/testthat/test_autotests.R b/tests/testthat/test_autotests.R index 12b0771e..897f4aef 100644 --- a/tests/testthat/test_autotests.R +++ b/tests/testthat/test_autotests.R @@ -1,4 +1,6 @@ test_that("auto_paramtest works", { + # ficx + # captures missing parameters f1 = function(x, y) NULL ps1 = ps(x = p_uty()) diff --git a/tests/testthat/test_cache.R b/tests/testthat/test_cache.R index 126ca7c3..a6c7be98 100644 --- a/tests/testthat/test_cache.R +++ b/tests/testthat/test_cache.R @@ -1,4 +1,4 @@ -test_that("cache works if mlr3torch.cache is set to FALSE", { +test_that("cache works if mlr3torch.cache is set to false", { # if we disable caching, we expect the folder structure of the tempfile() to be: # raw: # - data.csv (the "downloaded" data) @@ -7,7 +7,7 @@ test_that("cache works if mlr3torch.cache is set to FALSE", { dat = data.table(x = rnorm(1)) test_constructor = function(path) { - fwrite(dat, file.path(path, "data.csv")) + fwrite(dat, fs::path_norm(file.path(path, "data.csv"))) return(dat) } @@ -21,7 +21,6 @@ test_that("cache works if mlr3torch.cache is set to FALSE", { expect_equal(dat, dat1$data) }) - test_that("cache works if mlr3torch.cache is set to a directory", { # If we enable caching, we expect the folder structure of cache_dir/datasets/test_data to be # raw: @@ -48,7 +47,9 @@ test_that("cache works if mlr3torch.cache is set to a directory", { expect_equal(dat, dat1$data) dat2 = cached(function(x) stop(), "datasets", "test_data") - expect_equal(dat1, dat2) + expect_equal(dat1$data, dat2$data) + # /private/var and /var are symlinked and somehow different paths are returned on macOS + expect_equal(fs::path_real(dat1$path), fs::path_real(dat2$path)) }) test_that("cache works if mlr3torch.cache is set to TRUE", { @@ -104,6 +105,7 @@ test_that("cache initialization and versioning are correct", { } dat1 = cached(test_constructor, name, "test_data") + cache_dir = fs::path_real(cache_dir) # here the version should be 5 cache_version = jsonlite::read_json(file.path(cache_dir, "version.json")) @@ -112,7 +114,7 @@ test_that("cache initialization and versioning are correct", { # the other cache version is left unchanged expect_true(cache_version$datasets == CACHE$versions$datasets) - expect_true(cache_dir %in% CACHE$initialized) + expect_true(fs::path_real(cache_dir) %in% CACHE$initialized) # the subfolder is created assert_true(name %in% list.files(cache_dir)) diff --git a/tests/testthat/test_imageuri.R b/tests/testthat/test_imageuri.R index d1c4de37..963e0926 100644 --- a/tests/testthat/test_imageuri.R +++ b/tests/testthat/test_imageuri.R @@ -2,7 +2,7 @@ test_that("imageuri works", { cls = c("imageuri", "character") path = testthat::test_path("assets", "nano_mnist") image_names = list.files(path) - uris = normalizePath(file.path(path, image_names)) + uris = fs::path_norm(file.path(path, image_names)) img1 = uris[[1]] img2 = uris[[2]] diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index a11916d5..a79d058f 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -1,36 +1,3 @@ -test_that("DataDescriptor works", { - ds = dataset( - initialize = function() { - self$x = torch_randn(10, 5, 3) - }, - .getitem = function(i) { - list(x = self$x[i, ..]) - }, - .length = function() { - nrow(self$x) - } - )() - - dd = DataDescriptor(ds, dataset_shapes = list(x = c(NA, 5, 3))) - expect_class(dd, "DataDescriptor") - expect_equal(dd$.pointer_shape, c(NA, 5, 3)) - expect_class(dd$graph$pipeops[[1L]], "PipeOpNOP") - expect_true(length(dd$graph$pipeops) == 1L) - expect_equal(dd$.pointer, c(dd$graph$output$op.id, dd$graph$output$channel.name)) - expect_string(dd$.dataset_hash) - expect_string(dd$.hash) - expect_false(dd$.dataset_hash == dd$.hash) - - dd1 = DataDescriptor(ds, dataset_shapes = list(x = c(NA, 5, 3))) - expect_equal(dd$dataset_shapes, dd1$dataset_shapes) - - expect_error(DataDescriptor(ds), "missing") - - graph = as_graph(po("nop", id = "nop")) - - expect_error(DataDescriptor(ds, dataset_shapes = list(x = c(5, 4)), "When passing a graph")) -}) - test_that("Unknown shapes work", { ds = dataset( initialize = function() { @@ -131,7 +98,16 @@ test_that("transform_lazy_tensor works", { expect_true(torch_equal(lt1_mat, lt_mat)) }) -test_that("unlist does not have any surprises", { +test_that("pofu identifies identical columns", { + dt = data.table( + y = 1:2, + z = as_lazy_tensor(1:2) + ) + + taskin = as_task_regr(dt, target = "y", id = "test") + po_fu = po("featureunion") + taskout = po_fu$train(list(taskin, taskin))[[1L]] + expect_set_equal(taskout$feature_names, "z") }) diff --git a/tests/testthat/test_materialize.R b/tests/testthat/test_materialize.R index 973c0950..f179b980 100644 --- a/tests/testthat/test_materialize.R +++ b/tests/testthat/test_materialize.R @@ -167,7 +167,7 @@ test_that("materialize_internal: set_keep_results works", { }) -test_that("PipeOpFeatureUnion can properly check whether to lazy tensors are identical", { +test_that("PipeOpFeatureUnion can properly check whether two lazy tensors are identical", { # when lazy_tensor only stored the integers in the vec_data() (and not integer + hash) this test failed task = tsk("lazy_iris") diff --git a/tests/testthat/test_preprocess.R b/tests/testthat/test_preprocess.R index 11cb0c59..ec0867c0 100644 --- a/tests/testthat/test_preprocess.R +++ b/tests/testthat/test_preprocess.R @@ -4,3 +4,232 @@ test_that("trafo_resize", { shapes_in = list(c(16, 10, 10, 4), c(3, 4, 8)) ) }) + +test_that("trafo_resize", { + autotest_pipeop_torch_preprocess( + obj = po("trafo_resize", size = c(3, 4)), + shapes_in = list(c(16, 10, 10, 4), c(3, 4, 8)) + ) +}) + +test_that("trafo_nop", { + autotest_pipeop_torch_preprocess( + obj = po("trafo_nop"), + shapes_in = list(c(1, 1)) + ) +}) + +test_that("trafo_adjust_gamma", { + autotest_pipeop_torch_preprocess( + obj = po("trafo_adjust_gamma", gamma = 0.2, gain = 2), + shapes_in = list(c(4, 3, 10, 10)) + ) +}) + +test_that("trafo_adjust_brightness", { + autotest_pipeop_torch_preprocess( + obj = po("trafo_adjust_brightness", brightness_factor = 0.2), + shapes_in = list(c(2, 3, 8, 8)) + ) +}) + +test_that("trafo_adjust_hue", { + autotest_pipeop_torch_preprocess( + obj = po("trafo_adjust_hue", hue_factor = 0.3), + shapes_in = list(c(5, 3, 8, 8)) + ) +}) + +test_that("trafo_adjust_saturation", { + autotest_pipeop_torch_preprocess( + obj = po("trafo_adjust_saturation", saturation_factor = 2), + shapes_in = list(c(2, 3, 8, 8)) + ) +}) + +# not implemented +#test_that("trafo_grayscale", { +# autotest_pipeop_torch_preprocess( +# obj = po("trafo_grayscale", num_output_channels = 3), +# shapes_in = list(c(2, 3, 8, 8)) +# ) +#}) + +test_that("trafo_rgb_to_grayscale", { + autotest_pipeop_torch_preprocess( + obj = po("trafo_rgb_to_grayscale"), + shapes_in = list(c(1, 3, 8, 8)) + ) +}) + +test_that("trafo_normalize", { + autotest_pipeop_torch_preprocess( + obj = po("trafo_normalize", mean = -2, std = 3), + shapes_in = list(c(1, 3, 8, 8)) + ) +}) + +test_that("trafo_pad", { + autotest_pipeop_torch_preprocess( + obj = po("trafo_pad", padding = c(2, 3)), + shapes_in = list(c(1, 3, 8, 8)) + ) +}) + +## Augmentation + +test_that("augment_resized_crop", { + autotest_pipeop_torch_preprocess( + obj = po("augment_resized_crop", top = 1, left = 2, height = 5, width = 6, size = c(10, 11)), + shapes_in = list(c(1, 3, 64, 64)) + ) +}) + +test_that("augment_color_jitter", { + autotest_pipeop_torch_preprocess( + obj = po("augment_color_jitter"), + shapes_in = list(c(1, 3, 8, 8)) + ) +}) + +test_that("augment_random_resized_crop", { + autotest_pipeop_torch_preprocess( + obj = po("augment_random_resized_crop"), + shapes_in = list(c(1, 3, 8, 8)) + ) +}) + +test_that("augment_random_order", { + autotest_pipeop_torch_preprocess( + obj = po("augment_random_order", transforms = list( + function(x) torchvision::transform_resize(x, c(4, 5)) + )), + shapes_in = list(c(1, 3, 8, 8)) + ) +}) + +test_that("augment_hflip", { + autotest_pipeop_torch_preprocess( + obj = po("augment_hflip"), + shapes_in = list(c(1, 3, 8, 8)) + ) +}) + +#test_that("augment_random_rotation", { +# autotest_pipeop_torch_preprocess( +# obj = po("augment_random_rotation", degrees = 20), +# shapes_in = list(c(1, 3, 8, 8)) +# ) +#}) + +test_that("augment_random_horizontal_flip", { + autotest_pipeop_torch_preprocess( + obj = po("augment_random_horizontal_flip"), + shapes_in = list(c(1, 3, 8, 8)) + ) +}) + +#test_that("augment_linear_transformation", { +# autotest_pipeop_torch_preprocess( +# obj = po("augment_linear_transformation", +# transformation_matrix = torch_randn(rep(3 * 8 * 7, 2)), mean_vector = torch_randn(3 * 8 * 7)), +# shapes_in = list(c(1, 3, 8, 7)) +# ) +#}) + +test_that("augment_crop", { + autotest_pipeop_torch_preprocess( + obj = po("augment_crop", top = 2, left = 3, height = 10, width = 9), + shapes_in = list(c(2, 3, 11, 9)) + ) +}) + +test_that("augment_random_vertical_flip", { + autotest_pipeop_torch_preprocess( + obj = po("augment_random_vertical_flip"), + shapes_in = list(c(3, 3, 8, 7)) + ) +}) + +# not implemented for torch_tensor +#test_that("augment_random_grayscale", { +# autotest_pipeop_torch_preprocess( +# obj = po("augment_random_vertical_flip"), +# shapes_in = list(c(1, 3, 8, 8)) +# ) +#}) + +test_that("augment_random_affine", { + autotest_pipeop_torch_preprocess( + obj = po("augment_random_affine", degrees = c(2, 70)), + shapes_in = list(c(1, 3, 8, 8)) + ) +}) + +test_that("augment_random_perspective", { + autotest_pipeop_torch_preprocess( + obj = po("augment_random_perspective"), + shapes_in = list(c(1, 3, 8, 8)) + ) +}) + +test_that("augment_vflip", { + autotest_pipeop_torch_preprocess( + obj = po("augment_vflip"), + shapes_in = list(c(1, 3, 8, 8)) + ) +}) + +#test_that("augment_random_erasing", { +# autotest_pipeop_torch_preprocess( +# obj = po("augment_random_erasing"), +# shapes_in = list(c(1, 3, 8, 8)) +# ) +#}) + +# not implemented +#test_that("augment_perspective", { +# autotest_pipeop_torch_preprocess( +# obj = po("augment_perspective", startpoints = 3, endpoints = 4), +# shapes_in = list(c(1, 3, 8, 8)) +# ) +#}) + +test_that("augment_random_apply", { + autotest_pipeop_torch_preprocess( + obj = po("augment_random_apply", transforms = list( + function(x) torchvision::transform_resize(x, c(4, 5)) + )), + shapes_in = list(c(1, 3, 9, 18)) + ) +}) + +test_that("augment_rotate", { + autotest_pipeop_torch_preprocess( + obj = po("augment_rotate", angle = 3), + shapes_in = list(c(1, 3, 8, 8)) + ) +}) + +test_that("augment_center_crop", { + autotest_pipeop_torch_preprocess( + obj = po("augment_center_crop", size = c(6, 5)), + shapes_in = list(c(6, 3, 10, 11)) + ) +}) + +test_that("augment_random_choice", { + autotest_pipeop_torch_preprocess( + obj = po("augment_random_choice", transforms = list( + identity, identity + )), + shapes_in = list(c(1, 3, 8, 8)) + ) +}) + +test_that("augment_random_crop", { + autotest_pipeop_torch_preprocess( + obj = po("augment_random_crop", size = c(4, 4)), + shapes_in = list(c(1, 3, 8, 8)) + ) +}) diff --git a/tests/testthat/test_shape.R b/tests/testthat/test_shape.R index 529571c3..73e30521 100644 --- a/tests/testthat/test_shape.R +++ b/tests/testthat/test_shape.R @@ -1,6 +1,9 @@ -test_that("assert_shape works", { +test_that("assert_shape and friends", { expect_error(assert_shape("1")) expect_error(assert_shape(NULL, null_ok = FALSE)) + expect_error(assert_shape(c(NA, 1), unknown_batch = FALSE)) + expect_integer(assert_shape(c(NA, 1), unknown_batch = TRUE)) + expect_integer(assert_shape(c(NA, 1), unknown_batch = NULL)) expect_true(is.null(assert_shape(NULL, null_ok = TRUE))) expect_integerish(assert_shape(c(1, 2))) @@ -8,4 +11,11 @@ test_that("assert_shape works", { expect_error(assert_shape(c(2, NA)), regexp = "Invalid") expect_true(is.integer(assert_shape(c(1, 2), coerce = TRUE))) expect_false(is.integer(assert_shape(c(1, 2), coerce = FALSE))) + + expect_error(assert_shapes(list(c(1, 2), c(2, 3)), named = FALSE, unknown_batch = NULL), regexp = NA) + expect_error(assert_shapes(list(NULL), null_ok = TRUE), regexp = NA) + expect_error(assert_shapes(list(NULL), null_ok = FALSE)) + expect_error(assert_shapes(list(c(1, 2), c(2, 3)), named = TRUE)) + expect_error(assert_shapes(list(c(1, 2), c(2, 3))), regexp = NA) + expect_error(assert_shapes(list(c(4, 5), c(2, 3)), unknown_batch = TRUE)) }) diff --git a/tests/testthat/test_with_torch_settings.R b/tests/testthat/test_with_torch_settings.R index 5e064ed4..8030cf2e 100644 --- a/tests/testthat/test_with_torch_settings.R +++ b/tests/testthat/test_with_torch_settings.R @@ -1,12 +1,12 @@ -skip_if(running_on_mac()) -# Threads must be 1 on macOS per ?torch_set_num_threads - test_that("with_torch_settings leaves global state untouched", { - # Function to reset the torch manual seed cannot yet be used (wait for release after 0.10.0) runif(1) - prev_num_threads = 10 - torch_set_num_threads(prev_num_threads) + if (!running_on_mac()) { + prev_num_threads = 10 + torch_set_num_threads(prev_num_threads) + } else { + prev_num_threads = 1 + } prev_seed = get0(".Random.seed", globalenv(), mode = "integer", inherits = FALSE) prev_torch_rng_state = torch_get_rng_state() From e57b3c0febf38cd4b56471e3de5e17a098324a11 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 6 Dec 2023 19:10:06 +0100 Subject: [PATCH 16/90] broken but almost working --- .DS_Store | Bin 0 -> 6148 bytes DESCRIPTION | 5 +- NAMESPACE | 10 +- R/DataBackendLazy.R | 2 +- R/DataDescriptor.R | 63 ++++++++- R/LearnerTorchImage.R | 20 +-- R/ModelDescriptor.R | 6 +- R/PipeOpModule.R | 1 + R/PipeOpTaskPreprocTorch.R | 82 ++++++----- R/PipeOpTorch.R | 2 + R/PipeOpTorchIngress.R | 59 +------- R/TaskClassif_tiny_imagenet.R | 3 +- R/imageuri.R | 76 ----------- R/lazy_tensor.R | 27 ++-- R/materialize.R | 75 +++------- R/merge_graphs.R | 15 +- R/preprocess.R | 7 +- R/task_dataset.R | 122 ++++++++++------- R/utils.R | 26 ++++ R/zzz.R | 2 +- .../image_classification.Rmd | 0 {vignettes => attic}/pipeop_torch.Rmd | 6 +- inst/col_info/tiny_imagenet.rds | Bin 2781 -> 2794 bytes man-roxygen/preprocess_torchvision.R | 1 + man/DataDescriptor.Rd | 5 +- man/ModelDescriptor.Rd | 1 - man/PipeOpPreprocTorchAugmentCenterCrop.Rd | 1 + man/PipeOpPreprocTorchAugmentColorJitter.Rd | 1 + man/PipeOpPreprocTorchAugmentCrop.Rd | 1 + man/PipeOpPreprocTorchAugmentHflip.Rd | 1 + man/PipeOpPreprocTorchAugmentRandomAffine.Rd | 18 +-- man/PipeOpPreprocTorchAugmentRandomApply.Rd | 1 + man/PipeOpPreprocTorchAugmentRandomChoice.Rd | 1 + man/PipeOpPreprocTorchAugmentRandomCrop.Rd | 1 + ...PreprocTorchAugmentRandomHorizontalFlip.Rd | 1 + man/PipeOpPreprocTorchAugmentRandomOrder.Rd | 1 + ...eOpPreprocTorchAugmentRandomResizedCrop.Rd | 1 + ...OpPreprocTorchAugmentRandomVerticalFlip.Rd | 1 + man/PipeOpPreprocTorchAugmentResizedCrop.Rd | 1 + man/PipeOpPreprocTorchAugmentRotate.Rd | 1 + man/PipeOpPreprocTorchAugmentVflip.Rd | 1 + ...PipeOpPreprocTorchTrafoAdjustBrightness.Rd | 1 + man/PipeOpPreprocTorchTrafoAdjustGamma.Rd | 1 + man/PipeOpPreprocTorchTrafoAdjustHue.Rd | 1 + ...PipeOpPreprocTorchTrafoAdjustSaturation.Rd | 1 + man/PipeOpPreprocTorchTrafoGrayscale.Rd | 1 + man/PipeOpPreprocTorchTrafoNormalize.Rd | 1 + man/PipeOpPreprocTorchTrafoPad.Rd | 1 + man/PipeOpPreprocTorchTrafoResize.Rd | 1 + man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd | 1 + man/TorchIngressToken.Rd | 1 - man/as_imageuri.Rd | 21 --- man/imageuri.Rd | 15 -- man/materialize_internal.Rd | 15 +- man/merge_graphs.Rd | 2 +- man/mlr_backends_lazy.Rd | 2 +- man/mlr_learners.alexnet.Rd | 2 +- man/mlr_learners_torch_model.Rd | 1 - man/mlr_pipeops_module.Rd | 2 - man/mlr_pipeops_preproc_torch.Rd | 23 ++-- man/mlr_pipeops_torch.Rd | 19 --- man/mlr_pipeops_torch_callbacks.Rd | 1 - man/mlr_pipeops_torch_ingress.Rd | 3 +- man/mlr_pipeops_torch_ingress_categ.Rd | 1 - man/mlr_pipeops_torch_ingress_img.Rd | 129 ------------------ man/mlr_pipeops_torch_ingress_ltnsr.Rd | 1 - man/mlr_pipeops_torch_ingress_num.Rd | 1 - man/mlr_pipeops_torch_optimizer.Rd | 3 +- man/model_descriptor_to_learner.Rd | 1 - man/model_descriptor_to_module.Rd | 1 - man/model_descriptor_union.Rd | 1 - man/nn_graph.Rd | 1 - man/pipeop_preproc_torch.Rd | 3 +- tests/testthat/helper_autotest.R | 7 +- tests/testthat/helper_learner.R | 9 +- tests/testthat/helper_tasks.R | 19 +-- tests/testthat/test_LearnerTorchAlexNet.R | 3 - tests/testthat/test_LearnerTorchImage.R | 7 +- tests/testthat/test_PipeOpTaskPreprocTorch.R | 61 ++++++--- tests/testthat/test_PipeOpTorchAvgPool.R | 4 +- tests/testthat/test_PipeOpTorchBatchNorm.R | 4 +- tests/testthat/test_PipeOpTorchConv.R | 4 +- .../testthat/test_PipeOpTorchConvTranspose.R | 4 +- tests/testthat/test_PipeOpTorchIngress.R | 2 +- tests/testthat/test_PipeOpTorchMaxPool.R | 4 +- tests/testthat/test_PipeOpTorchReshape.R | 2 +- tests/testthat/test_helper_tasks.R | 25 ++++ tests/testthat/test_imageuri.R | 55 -------- tests/testthat/test_materialize.R | 11 +- tests/testthat/test_preprocess.R | 15 +- tests/testthat/test_task_dataset.R | 67 ++++----- 91 files changed, 455 insertions(+), 754 deletions(-) create mode 100644 .DS_Store delete mode 100644 R/imageuri.R rename {vignettes/articles => attic}/image_classification.Rmd (100%) rename {vignettes => attic}/pipeop_torch.Rmd (99%) delete mode 100644 man/as_imageuri.Rd delete mode 100644 man/imageuri.Rd delete mode 100644 man/mlr_pipeops_torch_ingress_img.Rd create mode 100644 tests/testthat/test_helper_tasks.R delete mode 100644 tests/testthat/test_imageuri.R diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..19582aa423afc60ecf4884f412f52689a4e5081f GIT binary patch literal 6148 zcmeH~JqiLr422WjLa?#4oW=uqgF*BHdI1Z;Mph8Co}>Hnqu^>SA}=ucCfQ_{eZ|g3 zM09mMEJbD_GQl#+!rZ_VvC8(gyY#1XfAr{4GRjTV;2wkPk2;bHPys4H1*iZO_#Fl8 z+=fl2L3%1c1*pJN0sB4_EMrZ!pnp2xd;|bHq}{OhSpqDU0Bf=Zk%4Kng3+ozhFIR) z!IE_~*@Dq7n!|_Ylhvjem`1y3K>*Y0prZm*V4%P_;+dWQ8>~7tnC{X=;d%PKLH5rD4t`v;d-$RSd%S?42(YlE(0AE_^JYTP5utv literal 0 HcmV?d00001 diff --git a/DESCRIPTION b/DESCRIPTION index d1140427..343c864a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -48,6 +48,8 @@ Imports: data.table, paradox (>= 0.11.0), R6, + rlang, + vctrs, withr Suggests: callr, @@ -85,6 +87,7 @@ Collate: 'CallbackSetProgress.R' 'ContextTorch.R' 'DataBackendLazy.R' + 'utils.R' 'DataDescriptor.R' 'LearnerTorch.R' 'LearnerTorchImage.R' @@ -104,7 +107,6 @@ Collate: 'PipeOpTorchConvTranspose.R' 'PipeOpTorchDropout.R' 'PipeOpTorchHead.R' - 'utils.R' 'PipeOpTorchIngress.R' 'PipeOpTorchLayerNorm.R' 'PipeOpTorchLinear.R' @@ -124,7 +126,6 @@ Collate: 'TorchOptimizer.R' 'bibentries.R' 'cache.R' - 'imageuri.R' 'lazy_tensor.R' 'learner_torch_methods.R' 'materialize.R' diff --git a/NAMESPACE b/NAMESPACE index 008a9f7a..28e2f713 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,15 +1,9 @@ # Generated by roxygen2: do not edit by hand S3method("$",lazy_tensor) -S3method("[",imageuri) -S3method("[<-",imageuri) -S3method("[[",imageuri) -S3method("[[<-",imageuri) S3method(as.data.table,DictionaryMlr3torchCallbacks) S3method(as.data.table,DictionaryMlr3torchLosses) S3method(as.data.table,DictionaryMlr3torchOptimizers) -S3method(as_imageuri,character) -S3method(as_imageuri,imageuri) S3method(as_lazy_tensor,DataDescriptor) S3method(as_lazy_tensor,dataset) S3method(as_lazy_tensor,numeric) @@ -27,12 +21,12 @@ S3method(as_torch_loss,nn_loss) S3method(as_torch_optimizer,TorchOptimizer) S3method(as_torch_optimizer,character) S3method(as_torch_optimizer,torch_optimizer_generator) -S3method(c,imageuri) S3method(col_info,DataBackendLazy) S3method(format,lazy_tensor) S3method(materialize,data.frame) S3method(materialize,lazy_tensor) S3method(materialize,list) +S3method(print,DataDescriptor) S3method(print,ModelDescriptor) S3method(print,TorchIngressToken) S3method(reset_last_layer,AlexNet) @@ -92,7 +86,6 @@ export(PipeOpTorchHardTanh) export(PipeOpTorchHead) export(PipeOpTorchIngress) export(PipeOpTorchIngressCategorical) -export(PipeOpTorchIngressImage) export(PipeOpTorchIngressLazyTensor) export(PipeOpTorchIngressNumeric) export(PipeOpTorchLayerNorm) @@ -141,7 +134,6 @@ export(as_torch_optimizer) export(batchgetter_categ) export(batchgetter_num) export(callback_set) -export(imageuri) export(is_lazy_tensor) export(lazy_tensor) export(materialize) diff --git a/R/DataBackendLazy.R b/R/DataBackendLazy.R index 304b5576..93287598 100644 --- a/R/DataBackendLazy.R +++ b/R/DataBackendLazy.R @@ -22,7 +22,7 @@ #' Beware that accessing the backend's hash also contructs the backend. #' #' Note that while in most cases the data contains [`lazy_tensor`] columns, this is not necessary and the naming -#' of this class has nothing to do with the [`lazy_tensor`] datatype. +#' of this class has nothing to do with the [`lazy_tensor`] data type. #' #' @param constructor (`function`)\cr #' A function with no arguments, whose return value must be the actual backend. diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index bc4eee21..c3473992 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -5,7 +5,7 @@ #' In essence it is an annotated [`torch::dataset`] and a preprocessing graph (consisting mosty of [`PipeOpModule`] #' operators). The additional meta data (e.g. pointer, shapes) allows to preprocess [`lazy_tensors`] in an #' [`mlr3pipelines::Graph`] just like any (non-lazy) data types. -#' To observe the effect of such a preprocessing, [`materialize()`] can be used. +#' The preprocessing is applied when [`materialize()`] is called on the [`lazy_tensor`]. #' #' @param dataset ([`torch::dataset`])\cr #' The torch dataset. @@ -60,7 +60,8 @@ #' ) #' #' # with no preprocessing -#' dd1 = DataDescriptor(ds, list(x = c(NA, 3, 3))) +#' dd_no_preproc = DataDescriptor(ds, list(x = c(NA, 3, 3))) +#' dd_no_preproc DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NULL, .pointer = NULL, .pointer_shape = NULL, .pointer_shape_predict = NULL, clone_graph = TRUE) { assert_class(dataset, "dataset") @@ -72,6 +73,17 @@ DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NU assert_shapes(dataset_shapes, null_ok = is.null(dataset$.getbatch), unknown_batch = TRUE, named = TRUE) assert_shape(.pointer_shape_predict, null_ok = TRUE, unknown_batch = TRUE) + # not sure whether we should keep this? + #example = if (is.null(dataset$.getbatch)) dataset$.getitem(1L) else dataset$.getbatch(1L) + #if (!test_list(example, names = "unique") || !test_permutation(names(example), names(dataset_shapes))) { + # stopf("Dataset must return a list with named elements that are a permutation of the dataset_shapes names.") + # iwalk(dataset_shapes, function(dataset_shape, name) { + # if (!is.null(dataset_shape) && !test_equal(dataset_shapes[[name]][-1], example[[name]]$shape[-1L])) { + # stopf("First batch from dataset is incompatible with the provided dataset_shapes.") + # } + # }) + #} + if (is.null(graph)) { if ((length(dataset_shapes) == 1L) && is.null(.input_map)) { .input_map = names(dataset_shapes) @@ -124,17 +136,54 @@ DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NU return(obj) } +#' @include utils.R +data_descriptor_union = function(dd1, dd2) { + # Otherwise it is ugly to do the caching of the data loading + # and this is not really a strong restriction + assert_true(dd1$.dataset_hash == dd2$.dataset_hash) + g1 = dd1$graph + g2 = dd2$graph + + input_map = unique(c( + set_names(dd1$.input_map, g1$input$name), + set_names(dd2$.input_map, g2$input$name) + )) + + graph = merge_graphs(g1, g2) # shallow clone, g1 and g2 graphs (not pipeops) are unmodified + + DataDescriptor( + dataset = dd1$dataset, + dataset_shapes = dd1$dataset_shapes, + graph = graph, + .input_map = input_map, + .pointer = dd1$.pointer, + .pointer_shape = dd1$.pointer_shape, + .pointer_shape_predict = dd1$.pointer_shape_predict, + clone_graph = FALSE + ) +} + +#' @export +#' @include utils.R +print.DataDescriptor = function(x, ...) { + catn(sprintf("", length(x$graph$pipeops))) + catn(sprintf("* dataset_shapes: %s", shape_to_str(x$dataset_shapes))) + catn(sprintf("* .input_map: (%s) -> Graph", paste0(x$.input_map, collapse = ", "))) + catn(sprintf("* .pointer: %s", paste0(x$.pointer, collapse = "."))) + catn(str_indent("* .shape(train):", + if (is.null(x$.pointer_shape)) "" else shape_to_str(list(x$.pointer_shape)))) + catn(str_indent("* .shape(predict):", + if (is.null(x$.pointer_shape_predict)) "" else shape_to_str(list(x$.pointer_shape_predict)))) +} + # TODO: printer set_data_descriptor_hash = function(data_descriptor) { - # avoid partial argument m + # avoid partial argument matching data_descriptor$.hash = calculate_hash( data_descriptor[[".dataset_hash"]], data_descriptor[["graph"]][["hash"]], - data_descriptor[[".input_map"]], - data_descriptor[[".pointer"]], - data_descriptor[[".pointer_shape"]], - data_descriptor[[".pointer_shape_perdict"]] + data_descriptor[[".input_map"]] ) return(data_descriptor) } diff --git a/R/LearnerTorchImage.R b/R/LearnerTorchImage.R index de9b34c3..024c66b6 100644 --- a/R/LearnerTorchImage.R +++ b/R/LearnerTorchImage.R @@ -52,17 +52,6 @@ LearnerTorchImage = R6Class("LearnerTorchImage", classif = c("twoclass", "multiclass") ) assert_param_set(param_set) - predefined_set = ps( - channels = p_int(1, tags = c("train", "predict", "required")), - height = p_int(1, tags = c("train", "predict", "required")), - width = p_int(1, tags = c("train", "predict", "required")) - ) - - if (param_set$length) { - param_set$add(predefined_set) - } else { - param_set = predefined_set - } super$initialize( id = id, @@ -75,14 +64,19 @@ LearnerTorchImage = R6Class("LearnerTorchImage", packages = packages, callbacks = callbacks, predict_types = predict_types, - feature_types = "imageuri", + feature_types = "lazy_tensor", man = man ) } ), private = list( + .verify_train_task = function(task, row_ids) { + if (length(task$feature_names) != 1L || !identical(task$feature_types$type, "lazy_tensor")) { + stopf("Must have exactly one feature of type lazy_tensor.") + } + }, .dataset = function(task, param_vals) { - dataset_img(task, param_vals) + dataset_ltnsr(task, param_vals) } ) ) diff --git a/R/ModelDescriptor.R b/R/ModelDescriptor.R index f6c86bf3..2599d0e6 100644 --- a/R/ModelDescriptor.R +++ b/R/ModelDescriptor.R @@ -83,12 +83,8 @@ ModelDescriptor = function(graph, ingress, task, optimizer = NULL, loss = NULL, } #' @export +#' @include utils.R print.ModelDescriptor = function(x, ...) { - shape_to_str = function(x) { - shapedescs = map_chr(x, function(y) paste0("(", paste(y, collapse = ",", recycle0 = TRUE), ")")) - paste0("[", paste(shapedescs, collapse = ";", recycle0 = TRUE), "]") - } - ingress_shapes = imap(x$ingress, function(x, nm) { paste0(nm, ": ", shape_to_str(list(x$shape))) }) diff --git a/R/PipeOpModule.R b/R/PipeOpModule.R index b07d8500..7e0403be 100644 --- a/R/PipeOpModule.R +++ b/R/PipeOpModule.R @@ -84,6 +84,7 @@ #' po_add1$train(input)$output PipeOpModule = R6Class("PipeOpModule", inherit = PipeOp, + # this has no effect because parent class is cloneable, waiting for new R6 release cloneable = FALSE, public = list( #' @field module ([`nn_module`])\cr diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index e61dd088..a56f2c51 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -29,7 +29,7 @@ #' @template param_id #' @template param_param_vals #' @param fn (`function`)\cr -#' The preprocessing function. +#' The preprocessing function. Should not modify its input in-place. #' @param packages (`character()`)\cr #' The packages the preprocessing function depends on. #' @param param_set ([`ParamSet`])\cr @@ -40,11 +40,13 @@ #' Initial value for the `stages` parameter. #' @param rowwise (`logical(1)`)\cr #' Whether the preprocessing function is applied rowwise (and then concatenated by row) or directly to the whole -#' tensor. +#' tensor. In the first case there is no batch dimension. #' @section Input and Output Channels: #' See [`PipeOpTaskPreproc`]. #' @section State: -#' TODO: +#' In addition to state elements from [`PipeOpTaskPreprocSimple`], the state also contains the `$param_vals` that +#' were set during training. +#' #' @section Parameters: #' In addition to the parameters inherited from [`PipeOpTaskPreproc`] as well as those specified during construction #' as the argument `param_set` there are the following parameters: @@ -64,18 +66,20 @@ #' passing the parameter values (minus `stages` and `affect_columns`) to `fn`. #' The preprocessing graph of the lazy tensor columns is shallowly cloned and the `PipeOpModule` is added. #' This is done to avoid modifying user input and means that identical `PipeOpModule`s can be part of different -#' preprocessing graphs. This is possible, because the created `PipeOpModule` is stateless. -#' At a later point, graphs will be merged if possible to avoid unnecessary computation. +#' preprocessing graphs. This is only possible, because the created `PipeOpModule` is stateless. +#' +#' At a later point in the graph, preprocessing graphs will be merged if possible to avoid unnecessary computation. #' This is best illustrated by example: #' One lazy tensor column's preprocessing graph is `A -> B`. #' Then, two branches are created `B -> C` and `B -> D`, creating two preprocessing graphs -#' `A -> B -> C` and `A -> B -> D`. When loading the data, we want to run the preprocessing only once, i.e. -#' the `A -> B` part. For this reason, [`task_dataset()`] will try to merge graphs and cache results from graphs. +#' `A -> B -> C` and `A -> B -> D`. When loading the data, we want to run the preprocessing only once, i.e. we don't +#' want to run the `A -> B` part twice. For this reason, [`task_dataset()`] will try to merge graphs and cache +#' results from graphs. #' #' Also, the shapes created during `$train()` and `$predict()` might differ. #' To avoid the creation of graphs where the predict shapes are incompatible with the train shapes, -#' the hypothetical predict shapes are already calculated during `$train()` (hence the parameters that are set during -#' train are also used during predict) and the [`PipeOpTorchModel`] will check the train and predict shapes for +#' the hypothetical predict shapes are already calculated during `$train()` (this is why the parameters that are set +#' during train are also used during predict) and the [`PipeOpTorchModel`] will check the train and predict shapes for #' compatibility before starting the training. #' #' Otherwise, this mechanism is very similar to the [`ModelDescriptor`] construct. @@ -243,6 +247,12 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", fn = function(rhs) { assert_ro_binding(rhs) private$.fn + }, + #' @field rowwise + #' Whether the preprocessing is applied rowwise. + rowwise = function(rhs) { + assert_ro_binding(rhs) + private$.rowwise } ), private = list( @@ -309,21 +319,20 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", identity } - dt = map_dtc(dt, function(lt) { + dt = imap_dtc(dt, function(lt, nm) { po_fn = PipeOpModule$new( - # By randomizing the id we avoid ID clashes - id = paste0(self$id, sample.int(.Machine$integer.max, 1)), + id = paste0(self$id, ".", nm), module = fn, inname = self$input$name, outname = self$output$name, packages = self$packages ) - shape_before = lt$.pointer_shape + shape_before = dd(lt)$.pointer_shape shape_out = self$shapes_out(list(shape_before), stage = stage, task = task)[[1L]] shape_out_predict = if (stage == "train") { - shape_in_predict = if (is.null(lt$.pointer_shape_predict)) shape_before + shape_in_predict = if (is.null(dd(lt)$.pointer_shape_predict)) shape_before # during `$train()` we also keep track of the shapes that would arise during predict # This avoids that we first train a learner and then only notice during predict that the shapes # during the predict phase are wrong @@ -358,14 +367,15 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' @param param_vals (`list()`)\cr #' The parameter values. #' @export -pipeop_preproc_torch = function(id, fn, shapes_out, param_set = NULL, param_vals = list(), packages = character(0)) { - +pipeop_preproc_torch = function(id, fn, shapes_out, param_set = NULL, param_vals = list(), packages = character(0), + rowwise = FALSE) { pipeop_preproc_torch_class( id = id, - fn = if (is.language(fn)) fn else substitute(fn), + fn = if (is.language(fn)) fn else subs, shapes_out = shapes_out, param_set = if (is.language(param_set)) param_set else substitute(param_set), packages = if (is.language(packages)) packages else substitute(packages), + rowwise = rowwise )$new(param_vals = param_vals) } @@ -427,7 +437,8 @@ create_ps_call = function(fn) { #' po_example = pipeop_preproc_torch("preproc_example", function(x, a) x + a) #' po_example #' po_example$param_set -pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, packages = character(0), init_params = list(), +pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, packages = character(0), + init_params = list(), rowwise = FALSE) { assert( check_function(shapes_out, args = c("shapes_in", "param_vals", "task"), null.ok = TRUE), @@ -440,11 +451,11 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack } } else { # This should add required tags where it is applicable - param_set = create_ps_call(eval(fn)) + param_set = create_ps_call(rlang::eval_tidy(fn)) } if (!is.language(init_params)) init_params = substitute(init_params) - if (!is.language(fn)) fn = substitute(fn) + if (!rlang::is_quosure(fn)) fn = rlang::quo(fn) classname = paste0("PipeOpPreprocTorch", paste0(capitalize(strsplit(id, split = "_")[[1L]]), collapse = "")) # Note that we don't set default values @@ -452,10 +463,9 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack if (identical(shapes_out, "infer")) { shapes_out = crate(function(shapes_in, param_vals, task) { sin = shapes_in[[1L]] - batch_dim = sin[1L] - unknown_batch_dim = is.na(batch_dim) - if (unknown_batch_dim) { + batchdim_is_unknown = is.na(batch_dim) + if (batchdim_is_unknown) { sin[1] = 1L } if (rowwise) { @@ -464,19 +474,21 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack tensor_in = invoke(torch_empty, .args = sin, device = torch_device("meta")) tensor_out = tryCatch(invoke(private$.fn, tensor_in, .args = param_vals), error = function(e) { - stopf("Invalid input shape, error message: %s", e) + stopf("Failed to infer output shape, presumably invalid input shape; error message is: %s", e) } ) sout = dim(tensor_out) if (rowwise) { sout = c(batch_dim, sout) - } else if (unknown_batch_dim) { + } else if (batchdim_is_unknown) { sout[1] = NA } list(sout) - }, rowwise) + }, rowwise, .parent = environment(rlang::eval_tidy(fn))) + # FIXME: NSE issues, we need to evaluate fn in the proper environment, + # I guess we can use this quosure idea that } else if (identical(shapes_out, "unchanged")) { shapes_out = crate(function(shapes_in, param_vals, task_in) shapes_in) } else if (is.function(shapes_out) || is.null(shapes_out)) { @@ -485,17 +497,17 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack stopf("unreachable") } - init_fun = crate(function(id = idname, param_vals = list()) { - param_set = x1 - param_set$values = x2 + init_fun = crate(function(id = idname, param_vals = list()) { # nolint + param_set = x1 # nolint + param_set$values = x2 # nolint super$initialize( id = id, - packages = x3, + packages = x3, # nolint param_set = param_set, param_vals = param_vals, - fn = x4, - rowwise = x5, - stages_init = x6 + fn = x4, # nolint + rowwise = x5, # nolint + stages_init = x6 # nolint ) }) stages_init = if (startsWith(id, "augment_")) { @@ -509,7 +521,7 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack body(init_fun)[[2]][[3]] = param_set body(init_fun)[[3]][[3]] = init_params body(init_fun)[[4]][[3]] = packages - body(init_fun)[[4]][[6]] = fn + body(init_fun)[[4]][[6]] = as.expression(fn) body(init_fun)[[4]][[7]] = rowwise body(init_fun)[[4]][[8]] = stages_init @@ -525,7 +537,7 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack } register_preproc = function(id, fn, param_set = NULL, shapes_out = NULL, packages = character(0), rowwise = FALSE) { - Class = pipeop_preproc_torch_class(id, substitute(fn), param_set = substitute(param_set), shapes_out = shapes_out, + Class = pipeop_preproc_torch_class(id, rlang::quo(fn), param_set = substitute(param_set), shapes_out = shapes_out, packages = packages, rowwise = rowwise) assign(Class$classname, Class, parent.frame()) register_po(id, Class) diff --git a/R/PipeOpTorch.R b/R/PipeOpTorch.R index ad885513..45ccb5ac 100644 --- a/R/PipeOpTorch.R +++ b/R/PipeOpTorch.R @@ -221,6 +221,8 @@ #' identical(tasks_out[[1L]], tasks_out[[2L]]) PipeOpTorch = R6Class("PipeOpTorch", inherit = PipeOp, + # this has no effect because parent class is cloneable, waiting for new R6 release + cloneable = FALSE, public = list( #' @field module_generator (`nn_module_generator` or `NULL`)\cr #' The module generator wrapped by this `PipeOpTorch`. If `NULL`, the private method diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index f297b59b..5a14d493 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -5,7 +5,7 @@ #' @description #' Use this as entry-point to mlr3torch-networks. #' Unless you are an advanced user, you should not need to use this directly but [`PipeOpTorchIngressNumeric`], -#' [`PipeOpTorchIngressCategorical`] or [`PipeOpTorchIngressImage`]. +#' [`PipeOpTorchIngressCategorical`] or [`PipeOpTorchIngressLazyTensor`]. #' #' @template pipeop_torch_channels_default #' @section State: @@ -259,61 +259,6 @@ PipeOpTorchIngressCategorical = R6Class("PipeOpTorchIngressCategorical", register_po("torch_ingress_categ", PipeOpTorchIngressCategorical) -#' @title Torch Entry Point for Images -#' @name mlr_pipeops_torch_ingress_img -#' -#' @description -#' uses task with "imageuri" column and loads this as images. -#' doesn't do any preprocessing or so (image resizing) and instead just errors if images don't fit. -#' also no data augmentation etc. -#' -#' @inheritSection mlr_pipeops_torch_ingress Input and Output Channels -#' @inheritSection mlr_pipeops_torch_ingress State -#' -#' @section Parameters: -#' * `select` :: `logical(1)`\cr -#' Whether `PipeOp` should selected the supported feature types. Otherwise it will err, when receiving tasks -#' with unsupported feature types. -#' * `channels` :: `integer(1)`\cr -#' The number of input channels. -#' * `height` :: `integer(1)`\cr -#' The height of the pixels. -#' * `width` :: `integer(1)`\cr -#' The width of the pixels. -#' @section Internals: -#' Uses [`magick::image_read()`] to load the image. -#' -#' @family PipeOp -#' @family Graph Network -#' -#' @export -#' @examples -#' po_ingress = po("torch_ingress_img", channels = 3, height = 64, width = 64) -#' po_ingress -PipeOpTorchIngressImage = R6Class("PipeOpTorchIngressImage", - inherit = PipeOpTorchIngress, - public = list( - #' @description - #' Creates a new instance of this [R6][R6::R6Class] class. - #' @template params_pipelines - initialize = function(id = "torch_ingress_img", param_vals = list()) { - param_set = ps( - channels = p_int(1, tags = c("train", "predict", "required")), - height = p_int(1, tags = c("train", "predict", "required")), - width = p_int(1, tags = c("train", "predict", "required")) - ) - super$initialize(id = id, param_vals = param_vals, param_set = param_set, feature_types = "imageuri") - } - ), - private = list( - .shape = function(task, param_vals) c(NA, param_vals$channels, param_vals$height, param_vals$width), - .get_batchgetter = function(task, param_vals) { - get_batchgetter_img(c(param_vals$channels, param_vals$height, param_vals$width)) - } - ) -) -register_po("torch_ingress_img", PipeOpTorchIngressImage) - #' @title Ingress for Lazy Tensor #' @name mlr_pipeops_torch_ingress_ltnsr #' @description @@ -396,7 +341,7 @@ PipeOpTorchIngressLazyTensor = R6Class("PipeOpTorchIngressLazyTensor", stopf("PipeOpTorchIngressLazyTensor expects 1 'lazy_tensor' feature, but got %i.", length(lazy_cols)) } example = task$data(task$row_ids[1L], lazy_cols)[[1L]] - input_shape = example$.pointer_shape + input_shape = dd(example)$.pointer_shape pv_shape = param_vals$shape if (is.null(input_shape)) { diff --git a/R/TaskClassif_tiny_imagenet.R b/R/TaskClassif_tiny_imagenet.R index 1da683e8..4aedef6f 100644 --- a/R/TaskClassif_tiny_imagenet.R +++ b/R/TaskClassif_tiny_imagenet.R @@ -76,6 +76,7 @@ constructor_tiny_imagenet = function(path) { data.table(class = as.factor(classes), image = uris, split = factor(splits)) } +#' @include utils.R load_task_tiny_imagenet = function(id = "tiny_imagenet") { cached_constructor = crate(function() { # We need this as otherwise the factor level are differently ordered, @@ -84,7 +85,7 @@ load_task_tiny_imagenet = function(id = "tiny_imagenet") { withr::with_locale(c(LC_COLLATE = "C"), { dt = cached(constructor_tiny_imagenet, "datasets", "tiny_imagenet")$data }) - dt$image = imageuri(dt$image) + dt$image = as_lazy_tensor(dataset_image(dt$image), dataset_shapes = list(x = c(NA, 3, 64, 64))) dt$..row_id = seq_len(nrow(dt)) DataBackendDataTable$new(data = dt, primary_key = "..row_id") }) diff --git a/R/imageuri.R b/R/imageuri.R deleted file mode 100644 index 54c64952..00000000 --- a/R/imageuri.R +++ /dev/null @@ -1,76 +0,0 @@ -#' @title Create an object of class "imageuri" -#' @description -#' Creates an object of class `"imageuri"`, that contains the uris of images. -#' @param obj (`character()`)\cr -#' Character vector containing the paths to images. -#' @export -imageuri = function(obj) { - # TODO: examples - assert_character(obj) - structure( - obj, - class = c("imageuri", "character") - ) -} - -#' @export -`[.imageuri` = function(obj, ...) { - imageuri(unclass(obj)[...]) -} - -#' @export -`[[.imageuri` = function(obj, ...) { - imageuri(unclass(obj)[...]) -} - -#' @export -`[[<-.imageuri` = function(obj, ..., value) { - assert_character(value) - obj = unclass(obj) - obj[[...]] = value - imageuri(obj) -} - -#' @export -`[<-.imageuri` = function(obj, ..., value) { # nolint - # imageuri inherits from character - assert_character(value) - obj = unclass(obj) - obj[...] = value - imageuri(obj) -} - -#' @export -c.imageuri = function(...) { # nolint - dots = list(...) - if (!all(map_lgl(dots, function(x) test_character(x)))) { - stopf("To concatenate imageuri vectors, all objects must inherit from 'character'.") - } - imageuri(do.call(c, lapply(dots, unclass))) -} - -assert_imageuri = function(obj) { - assert_class(obj, c("imageuri", "list")) -} - -#' @title Conver to imageuri -#' @description -#' Converts an object to class [`imageuri`]. -#' @param obj (any)\cr -#' Object to convert. -#' @param ... (any)\cr -#' Additional arguments. -#' @return ([`imageuri`])\cr -as_imageuri = function(obj, ...) { - UseMethod("as_imageuri") -} - -#' @export -as_imageuri.imageuri = function(obj, ...) { # nolint - obj -} - -#' @export -as_imageuri.character = function(obj, ...) { # nolint - imageuri(obj) -} diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index da748451..d80bbc2e 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -38,17 +38,24 @@ new_lazy_tensor = function(data_descriptor, ids) { #' @export format.lazy_tensor = function(x, ...) { # nolint if (!length(x)) return(character(0)) - shape = x$data_descriptor$.pointer_shape + shape = dd(x)$.pointer_shape shape = if (is.null(shape)) { return(rep("", length(x))) } - shape = paste0(x$data_descriptor$.pointer_shape[-1L], collapse = "x") + shape = paste0(dd(x)$.pointer_shape[-1L], collapse = "x") map_chr(x, function(elt) { sprintf("", shape) }) } +dd = function(x) { + if (!length(x)) { + stopf("Cannot access data descriptor when lazy_tensor has length 0.") + } + x[[1L]][[2L]] +} + #' @title Convert to lazy tensor #' @description @@ -97,7 +104,6 @@ as_lazy_tensor.torch_tensor = function(x) { # nolint as_lazy_tensor(ds, dataset_shapes = list(x = c(NA, dim(x)[-1]))) } - #' @export vec_ptype_abbr.lazy_tensor <- function(x, ...) { # nolint "ltnsr" @@ -146,11 +152,11 @@ is_lazy_tensor = function(x) { #' lt_plus_five = transform_lazy_tensor(lt, add_five, c(NA, 1)) #' torch_cat(list(materialize(lt, rbind = TRUE), materialize(lt_plus_five, rbind = TRUE)), dim = 2) #' # graph is cloned -#' identical(lt$graph, lt_plus_five$graph) -#' lt$graph$edges -#' lt_plus_five$graph_edges +#' identical(lt[[1]][[2]]$graph, lt_plus_five[[1]][[2]]$graph) +#' lt[[1]][[2]]$graph$edges +#' lt_plus_five[[1]][[2]]$graph$edges #' # pipeops are not cloned -#' identical(lt$graph$pipeops[[1]], lt_plus_five$graph[[1]]) +#' identical(lt[[1]][[2]]$graph$pipeops[[1]], lt_plus_five[[1]][[2]]$graph[[1]]) #' @noRd transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { assert_lazy_tensor(lt) @@ -161,9 +167,9 @@ transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { # shape_predict can be NULL if we transform a tensor during `$predict()` in PipeOpTaskPreprocTorch assert_shape(shape_predict, null_ok = TRUE, unknown_batch = TRUE) - data_descriptor = lt$data_descriptor + data_descriptor = dd(lt) - graph = data_descriptor$graph$clone(deep= FALSE) + graph = data_descriptor$graph$clone(deep = FALSE) graph$edges = copy(data_descriptor$graph$edges) graph$add_pipeop(pipeop, clone = FALSE) @@ -190,9 +196,12 @@ transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { #' @export `$.lazy_tensor` = function(x, name) { + # FIXME: remove this method + #stop("Not supported anymore") if (!length(x)) { stop("lazy tensor has length 0.") } + dd = x[[1L]][[2L]] if (name == "data_descriptor") { return(dd) diff --git a/R/materialize.R b/R/materialize.R index 284f7105..9f9f0ffc 100644 --- a/R/materialize.R +++ b/R/materialize.R @@ -53,37 +53,15 @@ materialize.list = function(x, device = "cpu", rbind = FALSE, cache = "auto") { assert(check_choice(cache, "auto"), check_environment(cache, null.ok = TRUE)) if (identical(cache, "auto")) { - data_hashes = map_chr(x_lt, function(x) x$.dataset_hash) + data_hashes = map_chr(x_lt, function(x) dd(x)$.dataset_hash) hashes = map_chr(x_lt, function(x) x$.hash) cache = if (uniqueN(data_hashes) > 1L || uniqueN(hashes) > 1L) { new.env() } } - - # if we are materializing more than one lazy tensor, we must specify what we want to keep from the graph - # BEFORE calling materialize_internal because materialize_internal does not know about the other columns - keep_results_prev = list() - keep_results_prev = map(x_lt, function(x) { - graph = x$graph - keep_results = graph$keep_results - graph$keep_results = character(0) - return(keep_results) - }) - on.exit({ - walk(seq_along(x_lt), function(i) { - graph = x_lt[[i]]$graph - graph$keep_results = keep_results_prev[[i]] - }) - }, add = TRUE) - - walk(x_lt, function(col) { - graph = col$graph - graph$keep_results = union(graph$keep_results, col$.pointer[1L]) - }) - map(x, function(col) { if (is_lazy_tensor(col)) { - materialize_internal(col, device = device, cache = cache, set_keep_results = FALSE, rbind = rbind) + materialize_internal(col, device = device, cache = cache, rbind = rbind) } else { col } @@ -102,7 +80,7 @@ materialize.data.frame = function(x, device = "cpu", rbind = FALSE, cache = "aut #' @export materialize.lazy_tensor = function(x, device = "cpu", rbind = FALSE) { # nolint - materialize_internal(x = x, device = device, cache = NULL, set_keep_results = TRUE, rbind = rbind) + materialize_internal(x = x, device = device, cache = NULL, rbind = rbind) } #' @title Materialize a Lazy Tensor @@ -130,43 +108,32 @@ materialize.lazy_tensor = function(x, device = "cpu", rbind = FALSE) { # nolint #' @param cache (`NULL` or `environment()`)\cr #' Whether to cache the (intermediate) results of the materialization. #' This can make data loading faster when multiple `lazy_tensor`s reference the same dataset or graph. -#' @param set_keep_results (`logical(1)`)\cr -#' In some cases, the `.pointer` of a [`DataDescriptor`] might point to a non-terminal node in which case the -#' this result is not part of the output of the [`Graph`]. -#' Therefore we have to include this as part of the `keep_results` field of the [`Graph`]. -#' When caching is done, this should be set to `FALSE` as otherwise data will be discarded that might be relevant -#' for materializing other lazy tensor columns. #' @param rbind (`logical(1)`)\cr #' Whtether to rbind the resulting tensors (`TRUE`) or return them as a list of tensors (`FALSE`). #' @return [`lazy_tensor()`] #' @keywords internal -materialize_internal = function(x, device = "cpu", cache = NULL, set_keep_results = is.null(cache), rbind) { +materialize_internal = function(x, device = "cpu", cache = NULL, rbind) { if (!length(x)) { stopf("Cannot materialize lazy tensor of length 0.") } do_caching = !is.null(cache) ids = map_int(vec_data(x), 1) - data_descriptor = x$data_descriptor + data_descriptor = dd(x) ds = data_descriptor$dataset graph = data_descriptor$graph - varying_shapes = some(data_descriptor$dataset_shapes, function(shape) all(is.na(shape))) - - if (set_keep_results) { - prev_results = graph$keep_results - on.exit({graph$keep_results = prev_results}, add = TRUE) # nolint - graph$keep_results = data_descriptor$.pointer[1L] - } + varying_shapes = some(data_descriptor$dataset_shapes, is.null) + pointer_name = paste0(data_descriptor$.pointer, collapse = ".") if (do_caching) { output_hash = calculate_hash(ids, data_descriptor$.hash) output_hit = exists(output_hash, cache, inherits = FALSE) if (output_hit) { - return(cache[[output_hash]][[data_descriptor$.pointer]]) + return(cache[[output_hash]][[pointer_name]]) } - input_hash = calculate_hash(data_descriptor$.dataset_hash, ids) + input_hit = exists(input_hash, cache, inherits = FALSE) if (input_hit) { @@ -212,23 +179,15 @@ materialize_internal = function(x, device = "cpu", cache = NULL, set_keep_result output = if (rbind && !varying_shapes) { # tensor --graph--> tensor graph$train(input, single_input = FALSE) - out = map(data_descriptor$graph$keep_results, function(id) graph$pipeops[[id]]$.result) - set_names(out, data_descriptor$graph$keep_results) } else { # list --graph--> (list or tensor) - out = map(input, function(x) { - graph$train(x, single_input = FALSE) - out = map(data_descriptor$graph$keep_results, function(id) graph$pipeops[[id]]$.result) - set_names(out, data_descriptor$graph$keep_results) - }) + out = map(input, function(x) graph$train(x, single_input = FALSE)) + if (rbind) { # here, is a list with hierarchy: [id = [po_id = [ch_nm = ]]] # We want to obtain a list [po_id = [ch_nm = [...]]] where the [...] is the rbind over all ids - out = map(names(out[[1L]]), function(po_id) { - map(names(out[[1]][[po_id]]), function(ch_nm) { - torch_cat(map(seq_along(out), function(i) out[[i]][[po_id]][[ch_nm]]), dim = 1L) - }) - }) + rows = seq_along(out) + out = map(names(out[[1L]]), function(name) torch_cat(map(out[rows], name))) } out } @@ -237,13 +196,11 @@ materialize_internal = function(x, device = "cpu", cache = NULL, set_keep_result cache[[output_hash]] = output } - # discard the results - walk(data_descriptor$graph$pipeops[data_descriptor$graph$keep_results], function(x) x$.result = NULL) - + # put the tensor on the required device if (rbind) { - res = output[[data_descriptor$.pointer[1L]]][[data_descriptor$.pointer[2L]]]$to(device = device) + res = output[[pointer_name]]$to(device = device) } else { - res = map(output, function(o) o[[data_descriptor$.pointer[1L]]][[data_descriptor$.pointer[2L]]]$to(device = device)) + res = map(output, function(o) o[[pointer_name]]$to(device = device)) } return(res) diff --git a/R/merge_graphs.R b/R/merge_graphs.R index 19bf279a..d684dccf 100644 --- a/R/merge_graphs.R +++ b/R/merge_graphs.R @@ -1,19 +1,16 @@ #' note that this mo -merge_graphs = function(g1, g2, in_place = FALSE) { - if (in_place) { - graph = g1 - } else { - graph = g1$clone(deep = TRUE) - } +merge_graphs = function(g1, g2) { + graph = g1$clone(deep = FALSE) + # if graphs are identical, we don't need to worry about copying stuff if (!identical(g1, g2)) { # PipeOps that have the same ID that occur in both graphs must be identical. common_names = intersect(names(graph$pipeops), names(g2$pipeops)) - if (!identical(map(graph$pipeops[common_names], "hash"), map(g2$pipeops[common_names], "hash"))) { + if (!identical(graph$pipeops[common_names], g2$pipeops[common_names])) { not_identical = map_lgl(common_names, function(name) { - !identical(graph$pipeops[[name]]$hash, g2$pipeops[[name]]$hash) + !identical(graph$pipeops[[name]], g2$pipeops[[name]]) }) - stopf("Both graphs have PipeOps with ID(s) %s but they don't have the same hashes.", + stopf("Both graphs have PipeOps with ID(s) %s but they are not identical.", paste0("'", common_names[not_identical], "'", collapse = ", ") ) } diff --git a/R/preprocess.R b/R/preprocess.R index f7cd7ea4..0e3d2d3b 100644 --- a/R/preprocess.R +++ b/R/preprocess.R @@ -110,9 +110,6 @@ register_preproc("augment_random_vertical_flip", torchvision::transform_random_v #' @templateVar id augment_random_affine register_preproc("augment_random_affine", torchvision::transform_random_affine, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint -#' @template preprocess_torchvision -#' @templateVar id augment_random_affine -register_preproc("augment_random_perspective", torchvision::transform_random_perspective, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint #' @template preprocess_torchvision #' @templateVar id augment_vflip @@ -161,3 +158,7 @@ register_preproc("augment_random_crop", torchvision::transform_random_crop, pack ##' @name PipeOpPreprocTorchAugmentLinearTransformation ##' @rdname mlr_pipeops_preproc_torch_overview #register_preproc("augment_linear_transformation", torchvision::transform_linear_transformation, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint + +##' @template preprocess_torchvision +##' @templateVar id augment_random_perspective +#register_preproc("augment_random_perspective", torchvision::transform_random_perspective, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint diff --git a/R/task_dataset.R b/R/task_dataset.R index 4ae50aab..4854f67b 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -43,47 +43,36 @@ task_dataset = dataset( initialize = function(task, feature_ingress_tokens, target_batchgetter = NULL, device) { self$task = assert_r6(task$clone(deep = TRUE), "Task") + iwalk(feature_ingress_tokens, function(it, nm) { + if (length(it$features) == 0) { + stopf("Received ingress token '%s' with no features.", nm) + } + }) self$feature_ingress_tokens = assert_list(feature_ingress_tokens, types = "TorchIngressToken", names = "unique") + self$all_features = unique(c(unlist(map(feature_ingress_tokens, "features")), task$target_names)) + assert_subset(self$all_features, c(task$target_names, task$feature_names)) + self$target_batchgetter = assert_function(target_batchgetter, args = c("data", "device"), null.ok = TRUE) + self$device = assert_choice(device, mlr_reflections$torch$devices) lazy_tensor_features = self$task$feature_types[get("type") == "lazy_tensor"][[1L]] - self$cache_lazy_tensors = length(lazy_tensor_features) > 1L + data = self$task$data(cols = lazy_tensor_features) # Here, we could have multiple `lazy_tensor` columns that share parts of the graph # We try to merge those graphs if possible - - # FIXME: This must be tested, I don't think it works yet if (length(lazy_tensor_features) > 1L) { - stopf("Not working yet I think") - # TODO: Inspect hashes of data descriptors to check whether caching is possible - first_row = self$task$data(self$task$row_ids[1L], cols = lazy_tensor_features) - # attr no longer exists - # graphs = map(first_row, function(x) attr(x, "data_descriptor")$graph) - graphs = graphs[!duplicated(graphs)] - graphs[[1L]] = graphs[[1L]]$clone(deep = TRUE) - merged_graph = try(Reduce(function(x, y) merge_graphs(x, y, in_place = TRUE), graphs), silent = TRUE) - - if (!inherits(merged_graph, "try-error")) { - data = self$task$data(cols = lazy_tensor_features) - data = map_dtc(data, function(x) { - #attr(x, "data_descriptor")$graph = merged_graph - # attr no longer exists - x - }) - task$cbind(data) + merge_result = try(merge_lazy_tensor_graphs(data), silent = TRUE) + + if (inherits(merge_result, "try-error")) { + # This should basically never happen + lg$warn("Failed to merge data descriptor, this might leady to inefficient preprocessing.") + # TODO: test that is still works when this triggers + } else { + self$task$cbind(merge_result) } - } - iwalk(feature_ingress_tokens, function(it, nm) { - if (length(it$features) == 0) { - stopf("Received ingress token '%s' with no features.", nm) - } - }) - - self$all_features = unique(c(unlist(map(feature_ingress_tokens, "features")), task$target_names)) - assert_subset(self$all_features, c(task$target_names, task$feature_names)) - self$target_batchgetter = assert_function(target_batchgetter, args = c("data", "device"), null.ok = TRUE) - self$device = assert_choice(device, mlr_reflections$torch$devices) + } + self$cache_lazy_tensors = length(unique(map_chr(data, function(x) x$.hash))) > 1L }, .getbatch = function(index) { cache = if (self$cache_lazy_tensors) new.env() @@ -104,14 +93,61 @@ task_dataset = dataset( } ) -dataset_img = function(task, param_vals) { - # TODO: Maybe we want to be more careful here to avoid changing parameters between train and predict - # Instead use the param vals stored in the state? - imgshape = c(param_vals$channels, param_vals$height, param_vals$width) +merge_lazy_tensor_graphs = function(lts) { + # Otherwise it is ugly to do the caching of the data loading + # and this is not really a strong restriction + assert_true(length(unique(map_chr(lts, function(x) dd(x)$.dataset_hash))) == 1L) + + graph = Reduce(merge_graphs, map(lts, function(x) dd(x)$graph)) + input_map = Reduce(c, map(lts, function(lt) { + set_names(list(dd(lt)$.input_map), dd(lt)$graph$input$name) + })) + input_map = input_map[unique(names(input_map))] + + input_map = unname(unlist(input_map[graph$input$name])) + + + # some PipeOs that were previously terminal might not be anymore, + # for those we add nops and updaate the pointers for their data descriptors + map_dtc(lts, function(lt) { + pointer_name = paste0(lt$.pointer, collapse = ".") + + pointer = if (pointer_name %nin% graph$output$name) { + po_terminal = po("nop", id = uniqueify(pointer_name, graph$ids())) + graph$add_pipeop(po_terminal, clone = FALSE) + graph$add_pipeop( + src_id = lt$.pointer[1L], + dst_id = po_terminal$id, + src_channel = lt$.pointer[2L], + dst_channel = po_terminal$input$name + ) + + c(po_terminal$id, po_terminal$output$name) + } else { + lt$.pointer + } - batchgetter = get_batchgetter_img(imgshape) + data_descriptor = DataDescriptor( + dataset = dd(lts[[1]])$dataset, + dataset_shapes = dd(lts[[1L]])$dataset_shapes, + graph = graph, + .input_map = input_map, + .pointer = pointer, + .pointer_shape = lt$.pointer_shape, + .pointer_shape_predict = lt$.pointer_shape_predict, + clone_graph = FALSE + ) + new_lazy_tensor(data_descriptor, map_int(vec_data(lt), 1L)) + }) +} - ingress_tokens = list(image = TorchIngressToken(task$feature_names, batchgetter, imgshape)) +dataset_ltnsr = function(task, param_vals) { + assert_true(length(task$feature_names) == 1L) + shape = dd(task$data(cols = task$feature_names)[[1L]])$.pointer_shape + if (is.null(shape)) { + stopf("Each row element of the lazy tensor column must be of a known shape, please resize it accordingly.") + } + ingress_tokens = list(image = TorchIngressToken(task$feature_names, batchgetter_lazy_tensor, shape)) task_dataset( task, @@ -200,18 +236,6 @@ batchgetter_categ = function(data, device, ...) { ) } - -get_batchgetter_img = function(imgshape) { - crate(function(data, device, ...) { - tensors = lapply(data[[1]], function(uri) { - tnsr = torchvision::transform_to_tensor(magick::image_read(uri)) - assert_true(length(tnsr$shape) == length(imgshape) && all(tnsr$shape == imgshape)) - torch_reshape(tnsr, imgshape)$unsqueeze(1) - }) - torch_cat(tensors, dim = 1)$to(device = device) - }, imgshape, .parent = topenv()) -} - target_batchgetter_classif = function(data, device) { torch_tensor(data = as.integer(data[[1L]]), dtype = torch_long(), device = device) } diff --git a/R/utils.R b/R/utils.R index d6a4a613..9dfdfa25 100644 --- a/R/utils.R +++ b/R/utils.R @@ -176,3 +176,29 @@ assert_lazy_tensor = function(x) { uniqueify = function(new, existing) { make.unique(c(existing, new), sep = "_")[length(existing) + seq_along(new)] } + +shape_to_str = function(x) { + shapedescs = map_chr(x, function(y) paste0("(", paste(y, collapse = ",", recycle0 = TRUE), ")")) + if (test_named(x)) { + repr = paste0("[", names(x), ": ", paste(shapedescs, collapse = ";", recycle0 = TRUE), "]") + return(repr) + } + paste0("[", paste(shapedescs, collapse = ";", recycle0 = TRUE), "]") +} + +test_equal = function(x, y) { + isTRUE(all.equal(x, y)) +} + +dataset_image = dataset("image_dataset", + initialize = function(uris) { + self$uris = uris + }, + .getitem = function(x) { + list(x = torchvision::transform_to_tensor(magick::image_read(self$uris[x]))) + }, + .length = function() { + length(self$uris) + } +) + diff --git a/R/zzz.R b/R/zzz.R index c8c3949b..f66502a0 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -28,7 +28,7 @@ mlr3torch_tasks = new.env() mlr3torch_resamplings = new.env() mlr3torch_task_generators = new.env() mlr3torch_pipeop_tags = c("torch", "activation") -mlr3torch_feature_types = c(img = "imageuri", lt = "lazy_tensor") +mlr3torch_feature_types = c(lt = "lazy_tensor") register_po = function(name, constructor, metainf = NULL) { if (name %in% names(mlr3torch_pipeops)) stopf("pipeop %s registered twice", name) diff --git a/vignettes/articles/image_classification.Rmd b/attic/image_classification.Rmd similarity index 100% rename from vignettes/articles/image_classification.Rmd rename to attic/image_classification.Rmd diff --git a/vignettes/pipeop_torch.Rmd b/attic/pipeop_torch.Rmd similarity index 99% rename from vignettes/pipeop_torch.Rmd rename to attic/pipeop_torch.Rmd index 48b6b8b6..0d6c79ba 100644 --- a/vignettes/pipeop_torch.Rmd +++ b/attic/pipeop_torch.Rmd @@ -95,9 +95,9 @@ po_activation = po("module", id = "activation", activation) po_module_2 = po("module_2", module = module_2) po_softmax = po("module", id = "softmax", module = softmax) -module_graph = po_module_1 %>>% - po_activation %>>% - po_module_2 %>>% +module_graph = po_module_1 %>>!% + po_activation %>>!% + po_module_2 %>>!% po_softmax module_graph$plot(horizontal = TRUE) diff --git a/inst/col_info/tiny_imagenet.rds b/inst/col_info/tiny_imagenet.rds index 306f1a2c58072746764971cd6426922bef3b8a8a..40e0e9bf5a22425d691ec737b4cc5b2f421bdacd 100644 GIT binary patch literal 2794 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 diff --git a/man-roxygen/preprocess_torchvision.R b/man-roxygen/preprocess_torchvision.R index 387f0c58..60047437 100644 --- a/man-roxygen/preprocess_torchvision.R +++ b/man-roxygen/preprocess_torchvision.R @@ -8,6 +8,7 @@ #' @description #' Calls [`<%= paste0("torchvision::",gsub("^(augment|trafo)", "transform", id)) %>`], #' see there for more information on the parameters. +#' <%= if (pipeop$rowwise) "The preprocessing is applied row wise (no batch dimension)." else "The preprocessing is applied to the whole batch."%> #' #' @section Parameters: #' `r mlr3misc::rd_info(po("<%= id%>")$param_set)` diff --git a/man/DataDescriptor.Rd b/man/DataDescriptor.Rd index af55456d..5afc3182 100644 --- a/man/DataDescriptor.Rd +++ b/man/DataDescriptor.Rd @@ -53,7 +53,7 @@ A data descriptor is a rather internal data structure used in the \code{\link{la In essence it is an annotated \code{\link[torch:dataset]{torch::dataset}} and a preprocessing graph (consisting mosty of \code{\link{PipeOpModule}} operators). The additional meta data (e.g. pointer, shapes) allows to preprocess \code{\link{lazy_tensors}} in an \code{\link[mlr3pipelines:Graph]{mlr3pipelines::Graph}} just like any (non-lazy) data types. -To observe the effect of such a preprocessing, \code{\link[=materialize]{materialize()}} can be used. +The preprocessing is applied when \code{\link[=materialize]{materialize()}} is called on the \code{\link{lazy_tensor}}. } \examples{ # Create a dataset @@ -81,7 +81,8 @@ dd = DataDescriptor( ) # with no preprocessing -dd1 = DataDescriptor(ds, list(x = c(NA, 3, 3))) +dd_no_preproc = DataDescriptor(ds, list(x = c(NA, 3, 3))) +dd_no_preproc } \seealso{ ModelDescriptor, lazy_tensor diff --git a/man/ModelDescriptor.Rd b/man/ModelDescriptor.Rd index b5d55034..84814878 100644 --- a/man/ModelDescriptor.Rd +++ b/man/ModelDescriptor.Rd @@ -78,7 +78,6 @@ Other Graph Network: \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_img}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, diff --git a/man/PipeOpPreprocTorchAugmentCenterCrop.Rd b/man/PipeOpPreprocTorchAugmentCenterCrop.Rd index c4550367..2738c4d8 100644 --- a/man/PipeOpPreprocTorchAugmentCenterCrop.Rd +++ b/man/PipeOpPreprocTorchAugmentCenterCrop.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_center_crop]{torchvision::transform_center_crop}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchAugmentColorJitter.Rd b/man/PipeOpPreprocTorchAugmentColorJitter.Rd index 8c1aaa35..35af00ea 100644 --- a/man/PipeOpPreprocTorchAugmentColorJitter.Rd +++ b/man/PipeOpPreprocTorchAugmentColorJitter.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_color_jitter]{torchvision::transform_color_jitter}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchAugmentCrop.Rd b/man/PipeOpPreprocTorchAugmentCrop.Rd index 63bb990e..8f62d69f 100644 --- a/man/PipeOpPreprocTorchAugmentCrop.Rd +++ b/man/PipeOpPreprocTorchAugmentCrop.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_crop]{torchvision::transform_crop}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchAugmentHflip.Rd b/man/PipeOpPreprocTorchAugmentHflip.Rd index 0f2fa35f..18377dd8 100644 --- a/man/PipeOpPreprocTorchAugmentHflip.Rd +++ b/man/PipeOpPreprocTorchAugmentHflip.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_hflip]{torchvision::transform_hflip}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchAugmentRandomAffine.Rd b/man/PipeOpPreprocTorchAugmentRandomAffine.Rd index a0cbdd60..cf19cd40 100644 --- a/man/PipeOpPreprocTorchAugmentRandomAffine.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomAffine.Rd @@ -4,30 +4,14 @@ \alias{mlr_pipeops_preproc_torch.augment_random_affine} \title{PipeOpPreprocTorchAugmentRandomAffine} \format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. - \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. } \description{ Calls \code{\link[torchvision:transform_random_affine]{torchvision::transform_random_affine}}, see there for more information on the parameters. - -Calls \code{\link[torchvision:transform_random_affine]{torchvision::transform_random_affine}}, -see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - degrees \tab untyped \tab - \tab \cr - translate \tab untyped \tab - \tab \cr - scale \tab untyped \tab - \tab \cr - shear \tab untyped \tab - \tab \cr - resample \tab untyped \tab - \tab \cr - fillcolor \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr -} - \tabular{llll}{ Id \tab Type \tab Default \tab Levels \cr degrees \tab untyped \tab - \tab \cr diff --git a/man/PipeOpPreprocTorchAugmentRandomApply.Rd b/man/PipeOpPreprocTorchAugmentRandomApply.Rd index a4ed0276..ec68984b 100644 --- a/man/PipeOpPreprocTorchAugmentRandomApply.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomApply.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_random_apply]{torchvision::transform_random_apply}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchAugmentRandomChoice.Rd b/man/PipeOpPreprocTorchAugmentRandomChoice.Rd index 3cb74f9b..49775f5b 100644 --- a/man/PipeOpPreprocTorchAugmentRandomChoice.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomChoice.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_random_choice]{torchvision::transform_random_choice}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchAugmentRandomCrop.Rd b/man/PipeOpPreprocTorchAugmentRandomCrop.Rd index 80fb2806..d9de56df 100644 --- a/man/PipeOpPreprocTorchAugmentRandomCrop.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomCrop.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_random_crop]{torchvision::transform_random_crop}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd b/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd index f74fb02c..e32a9533 100644 --- a/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_random_horizontal_flip]{torchvision::transform_random_horizontal_flip}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchAugmentRandomOrder.Rd b/man/PipeOpPreprocTorchAugmentRandomOrder.Rd index 9c9f63ed..ec083c18 100644 --- a/man/PipeOpPreprocTorchAugmentRandomOrder.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomOrder.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_random_order]{torchvision::transform_random_order}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd b/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd index e1afb8c8..a77a68d9 100644 --- a/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_random_resized_crop]{torchvision::transform_random_resized_crop}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd b/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd index 64273352..a3889360 100644 --- a/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_random_vertical_flip]{torchvision::transform_random_vertical_flip}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchAugmentResizedCrop.Rd b/man/PipeOpPreprocTorchAugmentResizedCrop.Rd index a3f47126..c1ea919e 100644 --- a/man/PipeOpPreprocTorchAugmentResizedCrop.Rd +++ b/man/PipeOpPreprocTorchAugmentResizedCrop.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_resized_crop]{torchvision::transform_resized_crop}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchAugmentRotate.Rd b/man/PipeOpPreprocTorchAugmentRotate.Rd index f1e9c90e..fdef500c 100644 --- a/man/PipeOpPreprocTorchAugmentRotate.Rd +++ b/man/PipeOpPreprocTorchAugmentRotate.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_rotate]{torchvision::transform_rotate}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchAugmentVflip.Rd b/man/PipeOpPreprocTorchAugmentVflip.Rd index 73a4b7ab..673566f5 100644 --- a/man/PipeOpPreprocTorchAugmentVflip.Rd +++ b/man/PipeOpPreprocTorchAugmentVflip.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_vflip]{torchvision::transform_vflip}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd b/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd index 7a7c0677..cfe69c65 100644 --- a/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd +++ b/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_adjust_brightness]{torchvision::transform_adjust_brightness}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd b/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd index 129d03e7..35b647f0 100644 --- a/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd +++ b/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_adjust_gamma]{torchvision::transform_adjust_gamma}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchTrafoAdjustHue.Rd b/man/PipeOpPreprocTorchTrafoAdjustHue.Rd index 0d035a21..0e91d9e9 100644 --- a/man/PipeOpPreprocTorchTrafoAdjustHue.Rd +++ b/man/PipeOpPreprocTorchTrafoAdjustHue.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_adjust_hue]{torchvision::transform_adjust_hue}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd b/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd index 27cf36c3..afefab53 100644 --- a/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd +++ b/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_adjust_saturation]{torchvision::transform_adjust_saturation}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchTrafoGrayscale.Rd b/man/PipeOpPreprocTorchTrafoGrayscale.Rd index a438c1da..be42f698 100644 --- a/man/PipeOpPreprocTorchTrafoGrayscale.Rd +++ b/man/PipeOpPreprocTorchTrafoGrayscale.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_grayscale]{torchvision::transform_grayscale}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchTrafoNormalize.Rd b/man/PipeOpPreprocTorchTrafoNormalize.Rd index 330789f7..79dafb82 100644 --- a/man/PipeOpPreprocTorchTrafoNormalize.Rd +++ b/man/PipeOpPreprocTorchTrafoNormalize.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_normalize]{torchvision::transform_normalize}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchTrafoPad.Rd b/man/PipeOpPreprocTorchTrafoPad.Rd index a166c824..5c740b0a 100644 --- a/man/PipeOpPreprocTorchTrafoPad.Rd +++ b/man/PipeOpPreprocTorchTrafoPad.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_pad]{torchvision::transform_pad}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchTrafoResize.Rd b/man/PipeOpPreprocTorchTrafoResize.Rd index 6d2e4f40..f2816bd2 100644 --- a/man/PipeOpPreprocTorchTrafoResize.Rd +++ b/man/PipeOpPreprocTorchTrafoResize.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_resize]{torchvision::transform_resize}}, see there for more information on the parameters. +The preprocessing is applied to the whole batch. } \section{Parameters}{ \tabular{llll}{ diff --git a/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd b/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd index 4ec26426..b2509106 100644 --- a/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd +++ b/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd @@ -9,6 +9,7 @@ \description{ Calls \code{\link[torchvision:transform_rgb_to_grayscale]{torchvision::transform_rgb_to_grayscale}}, see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ \tabular{llll}{ diff --git a/man/TorchIngressToken.Rd b/man/TorchIngressToken.Rd index fee5554a..5a341e65 100644 --- a/man/TorchIngressToken.Rd +++ b/man/TorchIngressToken.Rd @@ -56,7 +56,6 @@ Other Graph Network: \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_img}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, diff --git a/man/as_imageuri.Rd b/man/as_imageuri.Rd deleted file mode 100644 index 9f6e752e..00000000 --- a/man/as_imageuri.Rd +++ /dev/null @@ -1,21 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/imageuri.R -\name{as_imageuri} -\alias{as_imageuri} -\title{Conver to imageuri} -\usage{ -as_imageuri(obj, ...) -} -\arguments{ -\item{obj}{(any)\cr -Object to convert.} - -\item{...}{(any)\cr -Additional arguments.} -} -\value{ -(\code{\link{imageuri}})\cr -} -\description{ -Converts an object to class \code{\link{imageuri}}. -} diff --git a/man/imageuri.Rd b/man/imageuri.Rd deleted file mode 100644 index f700301a..00000000 --- a/man/imageuri.Rd +++ /dev/null @@ -1,15 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/imageuri.R -\name{imageuri} -\alias{imageuri} -\title{Create an object of class "imageuri"} -\usage{ -imageuri(obj) -} -\arguments{ -\item{obj}{(\code{character()})\cr -Character vector containing the paths to images.} -} -\description{ -Creates an object of class \code{"imageuri"}, that contains the uris of images. -} diff --git a/man/materialize_internal.Rd b/man/materialize_internal.Rd index 261e2e76..e26bd856 100644 --- a/man/materialize_internal.Rd +++ b/man/materialize_internal.Rd @@ -4,13 +4,7 @@ \alias{materialize_internal} \title{Materialize a Lazy Tensor} \usage{ -materialize_internal( - x, - device = "cpu", - cache = NULL, - set_keep_results = is.null(cache), - rbind -) +materialize_internal(x, device = "cpu", cache = NULL, rbind) } \arguments{ \item{x}{(\code{\link[=lazy_tensor]{lazy_tensor()}})\cr @@ -23,13 +17,6 @@ The device to put the materialized tensor on (after running the preprocessing gr Whether to cache the (intermediate) results of the materialization. This can make data loading faster when multiple \code{lazy_tensor}s reference the same dataset or graph.} -\item{set_keep_results}{(\code{logical(1)})\cr -In some cases, the \code{.pointer} of a \code{\link{DataDescriptor}} might point to a non-terminal node in which case the -this result is not part of the output of the \code{\link{Graph}}. -Therefore we have to include this as part of the \code{keep_results} field of the \code{\link{Graph}}. -When caching is done, this should be set to \code{FALSE} as otherwise data will be discarded that might be relevant -for materializing other lazy tensor columns.} - \item{rbind}{(\code{logical(1)})\cr Whtether to rbind the resulting tensors (\code{TRUE}) or return them as a list of tensors (\code{FALSE}).} } diff --git a/man/merge_graphs.Rd b/man/merge_graphs.Rd index 1ecfac76..1327b0a5 100644 --- a/man/merge_graphs.Rd +++ b/man/merge_graphs.Rd @@ -4,7 +4,7 @@ \alias{merge_graphs} \title{note that this mo} \usage{ -merge_graphs(g1, g2, in_place = FALSE) +merge_graphs(g1, g2) } \description{ note that this mo diff --git a/man/mlr_backends_lazy.Rd b/man/mlr_backends_lazy.Rd index 1a8fe0cc..d89aaad7 100644 --- a/man/mlr_backends_lazy.Rd +++ b/man/mlr_backends_lazy.Rd @@ -26,7 +26,7 @@ Information that is available before the backend is constructed is: Beware that accessing the backend's hash also contructs the backend. Note that while in most cases the data contains \code{\link{lazy_tensor}} columns, this is not necessary and the naming -of this class has nothing to do with the \code{\link{lazy_tensor}} datatype. +of this class has nothing to do with the \code{\link{lazy_tensor}} data type. } \examples{ # We first define a backend constructor diff --git a/man/mlr_learners.alexnet.Rd b/man/mlr_learners.alexnet.Rd index 11fe5348..542b69ec 100644 --- a/man/mlr_learners.alexnet.Rd +++ b/man/mlr_learners.alexnet.Rd @@ -24,7 +24,7 @@ This \link{Learner} can be instantiated using the sugar function \code{\link[=lr \itemize{ \item classif: 'response', 'prob' } -\item Feature Types: \dQuote{imageuri} +\item Feature Types: \dQuote{lazy_tensor} \item Required Packages: \CRANpkg{mlr3}, \CRANpkg{mlr3torch}, \CRANpkg{torchvision}, \CRANpkg{magick}, \CRANpkg{torch} } } diff --git a/man/mlr_learners_torch_model.Rd b/man/mlr_learners_torch_model.Rd index 6e04627d..82732583 100644 --- a/man/mlr_learners_torch_model.Rd +++ b/man/mlr_learners_torch_model.Rd @@ -52,7 +52,6 @@ Other Graph Network: \code{\link{TorchIngressToken}()}, \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_img}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, diff --git a/man/mlr_pipeops_module.Rd b/man/mlr_pipeops_module.Rd index 7a33da46..1dac91b6 100644 --- a/man/mlr_pipeops_module.Rd +++ b/man/mlr_pipeops_module.Rd @@ -98,7 +98,6 @@ Other Graph Network: \code{\link{TorchIngressToken}()}, \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_img}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, @@ -110,7 +109,6 @@ Other Graph Network: Other PipeOp: \code{\link{mlr_pipeops_torch_callbacks}}, -\code{\link{mlr_pipeops_torch_ingress_img}}, \code{\link{mlr_pipeops_torch_optimizer}} } \concept{Graph Network} diff --git a/man/mlr_pipeops_preproc_torch.Rd b/man/mlr_pipeops_preproc_torch.Rd index 338200bb..f7f04dbd 100644 --- a/man/mlr_pipeops_preproc_torch.Rd +++ b/man/mlr_pipeops_preproc_torch.Rd @@ -36,7 +36,8 @@ See \code{\link{PipeOpTaskPreproc}}. \section{State}{ -TODO: +In addition to state elements from \code{\link{PipeOpTaskPreprocSimple}}, the state also contains the \verb{$param_vals} that +were set during training. } \section{Parameters}{ @@ -62,18 +63,20 @@ The pipeop applies the function \code{fn} to the input tensor while additionally passing the parameter values (minus \code{stages} and \code{affect_columns}) to \code{fn}. The preprocessing graph of the lazy tensor columns is shallowly cloned and the \code{PipeOpModule} is added. This is done to avoid modifying user input and means that identical \code{PipeOpModule}s can be part of different -preprocessing graphs. This is possible, because the created \code{PipeOpModule} is stateless. -At a later point, graphs will be merged if possible to avoid unnecessary computation. +preprocessing graphs. This is only possible, because the created \code{PipeOpModule} is stateless. + +At a later point in the graph, preprocessing graphs will be merged if possible to avoid unnecessary computation. This is best illustrated by example: One lazy tensor column's preprocessing graph is \code{A -> B}. Then, two branches are created \code{B -> C} and \code{B -> D}, creating two preprocessing graphs -\code{A -> B -> C} and \code{A -> B -> D}. When loading the data, we want to run the preprocessing only once, i.e. -the \code{A -> B} part. For this reason, \code{\link[=task_dataset]{task_dataset()}} will try to merge graphs and cache results from graphs. +\code{A -> B -> C} and \code{A -> B -> D}. When loading the data, we want to run the preprocessing only once, i.e. we don't +want to run the \code{A -> B} part twice. For this reason, \code{\link[=task_dataset]{task_dataset()}} will try to merge graphs and cache +results from graphs. Also, the shapes created during \verb{$train()} and \verb{$predict()} might differ. To avoid the creation of graphs where the predict shapes are incompatible with the train shapes, -the hypothetical predict shapes are already calculated during \verb{$train()} (hence the parameters that are set during -train are also used during predict) and the \code{\link{PipeOpTorchModel}} will check the train and predict shapes for +the hypothetical predict shapes are already calculated during \verb{$train()} (this is why the parameters that are set +during train are also used during predict) and the \code{\link{PipeOpTorchModel}} will check the train and predict shapes for compatibility before starting the training. Otherwise, this mechanism is very similar to the \code{\link{ModelDescriptor}} construct. @@ -171,6 +174,8 @@ materialize(taskout$data(cols = "x3"), rbind = TRUE) \if{html}{\out{
}} \describe{ \item{\code{fn}}{The preprocessing function.} + +\item{\code{rowwise}}{Whether the preprocessing is applied rowwise.} } \if{html}{\out{
}} } @@ -213,7 +218,7 @@ Creates a new instance of this \code{\link[R6:R6Class]{R6}} class. \if{html}{\out{
}} \describe{ \item{\code{fn}}{(\code{function})\cr -The preprocessing function.} +The preprocessing function. Should not modify its input in-place.} \item{\code{id}}{(\code{character(1)})\cr The id for of the new object.} @@ -234,7 +239,7 @@ Initial value for the \code{stages} parameter.} \item{\code{rowwise}}{(\code{logical(1)})\cr Whether the preprocessing function is applied rowwise (and then concatenated by row) or directly to the whole -tensor.} +tensor. In the first case there is no batch dimension.} } \if{html}{\out{
}} } diff --git a/man/mlr_pipeops_torch.Rd b/man/mlr_pipeops_torch.Rd index e90db5c3..da2de0f9 100644 --- a/man/mlr_pipeops_torch.Rd +++ b/man/mlr_pipeops_torch.Rd @@ -237,7 +237,6 @@ Other Graph Network: \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_img}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, @@ -265,7 +264,6 @@ Do not change this after construction.} \itemize{ \item \href{#method-PipeOpTorch-new}{\code{PipeOpTorch$new()}} \item \href{#method-PipeOpTorch-shapes_out}{\code{PipeOpTorch$shapes_out()}} -\item \href{#method-PipeOpTorch-clone}{\code{PipeOpTorch$clone()}} } } \if{html}{\out{ @@ -362,21 +360,4 @@ A named \code{list()} containing the output shapes. The names are the names of t the \code{PipeOp}. } } -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorch-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorch$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} } diff --git a/man/mlr_pipeops_torch_callbacks.Rd b/man/mlr_pipeops_torch_callbacks.Rd index 0035d57e..1c4e2b23 100644 --- a/man/mlr_pipeops_torch_callbacks.Rd +++ b/man/mlr_pipeops_torch_callbacks.Rd @@ -51,7 +51,6 @@ Other Model Configuration: Other PipeOp: \code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch_ingress_img}}, \code{\link{mlr_pipeops_torch_optimizer}} } \concept{Model Configuration} diff --git a/man/mlr_pipeops_torch_ingress.Rd b/man/mlr_pipeops_torch_ingress.Rd index 800061a9..b49151e4 100644 --- a/man/mlr_pipeops_torch_ingress.Rd +++ b/man/mlr_pipeops_torch_ingress.Rd @@ -7,7 +7,7 @@ \description{ Use this as entry-point to mlr3torch-networks. Unless you are an advanced user, you should not need to use this directly but \code{\link{PipeOpTorchIngressNumeric}}, -\code{\link{PipeOpTorchIngressCategorical}} or \code{\link{PipeOpTorchIngressImage}}. +\code{\link{PipeOpTorchIngressCategorical}} or \code{\link{PipeOpTorchIngressLazyTensor}}. } \section{Input and Output Channels}{ @@ -96,7 +96,6 @@ Other Graph Network: \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_img}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch}}, diff --git a/man/mlr_pipeops_torch_ingress_categ.Rd b/man/mlr_pipeops_torch_ingress_categ.Rd index c7ae7247..14d72a77 100644 --- a/man/mlr_pipeops_torch_ingress_categ.Rd +++ b/man/mlr_pipeops_torch_ingress_categ.Rd @@ -104,7 +104,6 @@ Other Graph Network: \code{\link{TorchIngressToken}()}, \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch_ingress_img}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, diff --git a/man/mlr_pipeops_torch_ingress_img.Rd b/man/mlr_pipeops_torch_ingress_img.Rd deleted file mode 100644 index 13f9cd7e..00000000 --- a/man/mlr_pipeops_torch_ingress_img.Rd +++ /dev/null @@ -1,129 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchIngress.R -\name{mlr_pipeops_torch_ingress_img} -\alias{mlr_pipeops_torch_ingress_img} -\alias{PipeOpTorchIngressImage} -\title{Torch Entry Point for Images} -\description{ -uses task with "imageuri" column and loads this as images. -doesn't do any preprocessing or so (image resizing) and instead just errors if images don't fit. -also no data augmentation etc. -} -\section{Parameters}{ - -\itemize{ -\item \code{select} :: \code{logical(1)}\cr -Whether \code{PipeOp} should selected the supported feature types. Otherwise it will err, when receiving tasks -with unsupported feature types. -\item \code{channels} :: \code{integer(1)}\cr -The number of input channels. -\item \code{height} :: \code{integer(1)}\cr -The height of the pixels. -\item \code{width} :: \code{integer(1)}\cr -The width of the pixels. -} -} - -\section{Internals}{ - -Uses \code{\link[magick:editing]{magick::image_read()}} to load the image. -} - -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is set to the input shape. -} - -\examples{ -po_ingress = po("torch_ingress_img", channels = 3, height = 64, width = 64) -po_ingress -} -\seealso{ -Other PipeOp: -\code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch_callbacks}}, -\code{\link{mlr_pipeops_torch_optimizer}} - -Other Graph Network: -\code{\link{ModelDescriptor}()}, -\code{\link{TorchIngressToken}()}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch}}, -\code{\link{model_descriptor_to_learner}()}, -\code{\link{model_descriptor_to_module}()}, -\code{\link{model_descriptor_union}()}, -\code{\link{nn_graph}()} -} -\concept{Graph Network} -\concept{PipeOp} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorchIngress]{mlr3torch::PipeOpTorchIngress}} -> \code{PipeOpTorchIngressImage} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchIngressImage-new}{\code{PipeOpTorchIngressImage$new()}} -\item \href{#method-PipeOpTorchIngressImage-clone}{\code{PipeOpTorchIngressImage$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchIngressImage-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchIngressImage$new(id = "torch_ingress_img", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchIngressImage-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchIngressImage$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_torch_ingress_ltnsr.Rd b/man/mlr_pipeops_torch_ingress_ltnsr.Rd index bf83bb00..2ab7da4b 100644 --- a/man/mlr_pipeops_torch_ingress_ltnsr.Rd +++ b/man/mlr_pipeops_torch_ingress_ltnsr.Rd @@ -139,7 +139,6 @@ Other Graph Network: \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_img}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch}}, diff --git a/man/mlr_pipeops_torch_ingress_num.Rd b/man/mlr_pipeops_torch_ingress_num.Rd index e83ae5ca..8a65e2d7 100644 --- a/man/mlr_pipeops_torch_ingress_num.Rd +++ b/man/mlr_pipeops_torch_ingress_num.Rd @@ -39,7 +39,6 @@ Other Graph Network: \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_img}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch}}, diff --git a/man/mlr_pipeops_torch_optimizer.Rd b/man/mlr_pipeops_torch_optimizer.Rd index e6ba98c1..673f7692 100644 --- a/man/mlr_pipeops_torch_optimizer.Rd +++ b/man/mlr_pipeops_torch_optimizer.Rd @@ -42,8 +42,7 @@ mdout[[1L]]$optimizer \seealso{ Other PipeOp: \code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch_callbacks}}, -\code{\link{mlr_pipeops_torch_ingress_img}} +\code{\link{mlr_pipeops_torch_callbacks}} Other Model Configuration: \code{\link{ModelDescriptor}()}, diff --git a/man/model_descriptor_to_learner.Rd b/man/model_descriptor_to_learner.Rd index 5a3b0103..7a739641 100644 --- a/man/model_descriptor_to_learner.Rd +++ b/man/model_descriptor_to_learner.Rd @@ -25,7 +25,6 @@ Other Graph Network: \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_img}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, diff --git a/man/model_descriptor_to_module.Rd b/man/model_descriptor_to_module.Rd index 35920f30..1da0e702 100644 --- a/man/model_descriptor_to_module.Rd +++ b/man/model_descriptor_to_module.Rd @@ -36,7 +36,6 @@ Other Graph Network: \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_img}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, diff --git a/man/model_descriptor_union.Rd b/man/model_descriptor_union.Rd index bfb1e4fd..73effd81 100644 --- a/man/model_descriptor_union.Rd +++ b/man/model_descriptor_union.Rd @@ -42,7 +42,6 @@ Other Graph Network: \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_img}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, diff --git a/man/nn_graph.Rd b/man/nn_graph.Rd index c8f53c8f..32e682ed 100644 --- a/man/nn_graph.Rd +++ b/man/nn_graph.Rd @@ -41,7 +41,6 @@ Other Graph Network: \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_img}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_ingress}}, diff --git a/man/pipeop_preproc_torch.Rd b/man/pipeop_preproc_torch.Rd index 1bd767f8..9195a029 100644 --- a/man/pipeop_preproc_torch.Rd +++ b/man/pipeop_preproc_torch.Rd @@ -10,7 +10,8 @@ pipeop_preproc_torch( shapes_out, param_set = NULL, param_vals = list(), - packages = character(0) + packages = character(0), + rowwise = FALSE ) } \arguments{ diff --git a/tests/testthat/helper_autotest.R b/tests/testthat/helper_autotest.R index 3a6cfddc..2b2a0f68 100644 --- a/tests/testthat/helper_autotest.R +++ b/tests/testthat/helper_autotest.R @@ -7,8 +7,6 @@ #' * the generated module has the intended class #' * the parameters are correctly implemented #' * Some other basic checks -#' @details -#' TODO #' @param graph ([`Graph`])\cr #' The graph that contains the [`PipeOpTorch`] to be tested. #' @param id (`character(1)`)\cr @@ -357,7 +355,10 @@ autotest_pipeop_torch_preprocess = function(obj, shapes_in, exclude = character( walk(shapes_in, function(shape_in) { tnsr_in = torch_empty(shape_in) + shape_in_unknown_batch = shape_in + shape_in_unknown_batch[1L] = NA shape_out = obj$shapes_out(list(shape_in), stage = "train")[[1L]] + shape_out_unknown_batch = obj$shapes_out(list(shape_in_unknown_batch), stage = "train")[[1L]] taskin = as_task_regr(data.table( y = rep(1, nrow(tnsr_in)), x = as_lazy_tensor(tnsr_in) @@ -371,6 +372,8 @@ autotest_pipeop_torch_preprocess = function(obj, shapes_in, exclude = character( if (!is.null(shape_out)) { testthat::expect_equal(tnsr_out$shape, shape_out) + testthat::expect_equal(tnsr_out$shape[-1L], shape_out_unknown_batch[-1L]) + expect_true(is.na(shape_out_unknown_batch[1L])) } }) } diff --git a/tests/testthat/helper_learner.R b/tests/testthat/helper_learner.R index 14c3fa29..ac7b016e 100644 --- a/tests/testthat/helper_learner.R +++ b/tests/testthat/helper_learner.R @@ -22,11 +22,11 @@ LearnerTorchTest1 = R6Class("LearnerTorchTest1", } ), private = list( - .network = function(task, param_vals, defaults) { + .network = function(task, param_vals) { nout = get_nout(task) nn_linear(length(task$feature_names), nout, bias = param_vals$bias) }, - .dataloader = function(task, param_vals, defaults) { + .dataloader = function(task, param_vals) { ingress_token = TorchIngressToken(task$feature_names, batchgetter_num, c(NA, length(task$feature_names))) dataset = task_dataset( task, @@ -69,8 +69,9 @@ LearnerTorchImageTest = R6Class("LearnerTorchImageTest", } ), private = list( - .network = function(task, param_vals, defaults) { - d = prod(param_vals$height, param_vals$width, param_vals$channels) + .network = function(task, param_vals) { + shape = dd(task$data(task$row_ids[1L], task$feature_names)[[1L]])$.pointer_shape + d = prod(shape[-1]) nout = get_nout(task) nn_sequential( nn_flatten(), diff --git a/tests/testthat/helper_tasks.R b/tests/testthat/helper_tasks.R index 9ea1eded..b420aa89 100644 --- a/tests/testthat/helper_tasks.R +++ b/tests/testthat/helper_tasks.R @@ -4,18 +4,7 @@ nano_dogs_vs_cats = function(id = "nano_dogs_vs_cats") { image_names = list.files(path) uris = fs::path_norm(file.path(path, image_names)) - ds = dataset("dogs_vs_cats", - initialize = function(uris) { - self$uris = uris - }, - .getitem = function(id) { - list(x = torchvision::transform_to_tensor(magick::image_read(self$uris[id]))$to(dtype = torch_float32())) - }, - .length = function() { - length(self$uris) - } - )(uris) - + ds = dataset_image(uris) images = as_lazy_tensor(ds, dataset_shapes = list(x = NULL)) @@ -81,10 +70,8 @@ nano_imagenet = function(id = "nano_imagenet") { image_names = list.files(path) uris = fs::path_norm(file.path(path, image_names)) - images = imageuri(uris) - - labels = map_chr(image_names, function(name) {strsplit(name, split = "_")[[1L]][1L]}) - + images = as_lazy_tensor(dataset_image(uris), list(x = c(NA, 3, 64, 64))) + labels = map_chr(image_names, function(name) strsplit(name, split = "_")[[1L]][1L]) dat = data.table(image = images, class = labels) task = as_task_classif(dat, id = "nano_imagenet", label = "Nano Imagenet", target = "class") diff --git a/tests/testthat/test_LearnerTorchAlexNet.R b/tests/testthat/test_LearnerTorchAlexNet.R index e8d44517..1c9b6785 100644 --- a/tests/testthat/test_LearnerTorchAlexNet.R +++ b/tests/testthat/test_LearnerTorchAlexNet.R @@ -5,9 +5,6 @@ test_that("LearnerAlexnet runs", { callbacks = list(), optimizer = "adam", loss = "cross_entropy", - channels = 3, - height = 64, - width = 64, pretrained = FALSE ) task = nano_imagenet() diff --git a/tests/testthat/test_LearnerTorchImage.R b/tests/testthat/test_LearnerTorchImage.R index aff1414d..3d2ba7af 100644 --- a/tests/testthat/test_LearnerTorchImage.R +++ b/tests/testthat/test_LearnerTorchImage.R @@ -1,9 +1,6 @@ test_that("LearnerTorchImage works", { learner = LearnerTorchImageTest$new(task_type = "classif") learner$param_set$set_values( - height = 64, - width = 64, - channels = 3, epochs = 1, batch_size = 1 ) @@ -12,10 +9,12 @@ test_that("LearnerTorchImage works", { expect_equal(learner$man, "mlr3torch::mlr_learners.test") expect_r6(learner, c("Learner", "LearnerTorchImage", "LearnerTorch")) expect_true(learner$label == "Test Learner Image") - expect_identical(learner$feature_types, "imageuri") + expect_identical(learner$feature_types, "lazy_tensor") expect_set_equal(learner$predict_types, c("response", "prob")) expect_subset("R6", learner$packages) + task = po("trafo_resize", size = c(64, 64))$train(list(task))[[1L]] + learner$train(task) expect_class(learner$network, "nn_module") expect_true(is.null(learner$network$modules$`1`$bias)) diff --git a/tests/testthat/test_PipeOpTaskPreprocTorch.R b/tests/testthat/test_PipeOpTaskPreprocTorch.R index 203314c8..0b39731e 100644 --- a/tests/testthat/test_PipeOpTaskPreprocTorch.R +++ b/tests/testthat/test_PipeOpTaskPreprocTorch.R @@ -67,12 +67,12 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { param_vals = param_vals, fn = function(x, a = 2) x * a ) - } ) ) - po_test2 = PipeOpTaskPreprocTorchTest2$new(param_vals = list(affect_columns = selector_name("x1"), a = 0)) + po_test2 = PipeOpTaskPreprocTorchTest2$new(param_vals = list( + affect_columns = selector_name("x1"), a = 0, stages = "both")) expect_true( torch_sum(materialize(po_test2$train(list(task))[[1L]]$data(cols = "x1")[[1L]], rbind = TRUE))$item() == 0 @@ -91,25 +91,39 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { expect_true( torch_sum(materialize(po_test2$predict(list(task))[[1L]]$data(cols = "x1")[[1L]], rbind = TRUE))$item() == 0 ) - # only if we re-train the transformatoin is applied during predict + # only if we re-train the transformation is applied during predict po_test2$train(list(task)) expect_true( torch_sum(materialize(po_test2$predict(list(task))[[1L]]$data(cols = "x1")[[1L]], rbind = TRUE))$item() == sum(1:10) ) - # when stages is set to "predict", it onlu applied during prediction + # when stages is set to "predict", it is only applied during prediction po_test$param_set$set_values(stages = "predict") expect_torch_equal( materialize(task$data(cols = "x1")[[1L]], rbind = TRUE), materialize(po_test$train(list(task))[[1L]]$data(cols = "x1")[[1L]], rbind = TRUE) - ) + # TODO: - # need to finish the augment -> stages transition, i.e. add tests and "both", then finish the preprocess impmenetation. add the tests and test the preprocess autotest + # need to finish the augment -> stages transition, i.e. add tests and "both", then finish the preprocess implementation add the tests and test the preprocess autotest # also test that the rowwise parameter works - materialize(task$data(cols = "x1")[[1L]]) + po_test3 = pipeop_preproc_torch("test3", rowwise = FALSE, fn = function(x) x$reshape(-1), shapes_out = NULL) + po_test4 = pipeop_preproc_torch("test4", rowwise = TRUE, fn = function(x) x$reshape(-1), shapes_out = NULL) + + expect_equal( + materialize(po_test3$train(list(task))[[1L]]$data(cols = "x1")$x1, rbind = TRUE)$shape, + 10 + ) + expect_equal( + materialize(po_test4$train(list(task))[[1L]]$data(cols = "x1")$x1, rbind = TRUE)$shape, + c(10, 1) + ) + + expect_true(pipeop_preproc_torch("test3", identity, rowwise = TRUE, shapes_out = NULL)$rowwise) + expect_false(pipeop_preproc_torch("test3", identity, rowwise = FALSE, shapes_out = NULL)$rowwise) + # stages_init works }) test_that("PipeOptaskPreprocTorch: shapes_out() works", { @@ -140,7 +154,7 @@ test_that("PipeOpTaskPreprocTorch modifies the underlying lazy tensor columns co taskin = as_task_regr(d, target = "y") - po_test = po("preproc_torch", fn = crate(function(x, a) x + a), param_set = ps(a = p_int(tags = c("train", ""))), + po_test = po("preproc_torch", fn = crate(function(x, a) x + a), param_set = ps(a = p_int(tags = c("train", "required"))), a = -10, rowwise = FALSE) taskout_train = po_test$train(list(taskin))[[1L]] @@ -150,15 +164,15 @@ test_that("PipeOpTaskPreprocTorch modifies the underlying lazy tensor columns co po_test$train(list(taskin))[[1L]] taskout_pred_aug = po_test$predict(list(taskin))[[1L]] - expect_true(length(taskin$data(cols = "x")[[1]]$graph$pipeops) == 1L) + expect_true(length(dd(taskin$data(cols = "x")[[1]])$graph$pipeops) == 1L) - expect_true(length(taskout_pred$data(cols = "x")[[1]]$graph$pipeops) == 2L) - expect_true(length(taskout_pred_aug$data(cols = "x")[[1]]$graph$pipeops) == 2L) + expect_true(length(dd(taskout_pred$data(cols = "x")[[1]])$graph$pipeops) == 2L) + expect_true(length(dd(taskout_pred_aug$data(cols = "x")[[1]])$graph$pipeops) == 2L) - expect_true(identical(taskout_pred_aug$data(cols = "x")[[1]]$graph$pipeops[[2]]$module, identity)) - expect_false(identical(taskout_pred$data(cols = "x")[[1]]$graph$pipeops[[2]]$module, identity)) + expect_true(identical(dd(taskout_pred_aug$data(cols = "x")[[1]])$graph$pipeops[[2]]$module, identity)) + expect_false(identical(dd(taskout_pred$data(cols = "x")[[1]])$graph$pipeops[[2]]$module, identity)) - taskout_pred$data(cols = "x")[[1]]$graph + dd(taskout_pred$data(cols = "x")[[1]])$graph expect_equal( as_array(materialize(taskin$data(cols = "x")[[1L]], rbind = TRUE)), @@ -173,6 +187,7 @@ test_that("pipeop_preproc_torch", { "Must have formal arguments" ) + rowwise = sample(c(TRUE, FALSE), 1L) po_test = pipeop_preproc_torch("trafo_abc", function(x, a) torch_cat(list(x, torch_pow(x, a)), dim = 2), shapes_out = function(shapes_in, param_vals, task) { s = shapes_in[[1L]] @@ -212,12 +227,18 @@ test_that("pipeop_preproc_torch", { test_that("predict shapes are added during training", { po_test = pipeop_preproc_torch("test", function(x) torch_cat(list(x, x * 2), dim = 2), shapes_out = "infer") - task = as_task_regr(data.table( - y = 1, - x = as_lazy_tensor(1) - ), target = "y") - taskout = po_test$train(list(task))[[1L]] + po_test$param_set$set_values( + stages = "train" + ) -}) + task = tsk("lazy_iris") + graph = po_test %>>% + po("torch_ingress_ltnsr") %>>% + po("nn_head") %>>% + po("torch_optimizer") %>>% + po("torch_loss", "cross_entropy") %>>% + po("torch_model_classif", batch_size = 150L, epochs = 1L) + expect_error(graph$train(task), "would have a different shape") +}) diff --git a/tests/testthat/test_PipeOpTorchAvgPool.R b/tests/testthat/test_PipeOpTorchAvgPool.R index 95bd4851..aa0c0176 100644 --- a/tests/testthat/test_PipeOpTorchAvgPool.R +++ b/tests/testthat/test_PipeOpTorchAvgPool.R @@ -15,7 +15,7 @@ test_that("PipeOpTorchAvgPool1D paramtest", { test_that("PipeOpTorchAvgPool2D autotest", { po_test = po("nn_avg_pool2d", kernel_size = 3) task = nano_imagenet() - graph = po("torch_ingress_img", channels = 3, width = 64, height = 64) %>>% po_test + graph = po("torch_ingress_ltnsr") %>>% po_test autotest_pipeop_torch(graph, "nn_avg_pool2d", task) }) @@ -28,7 +28,7 @@ test_that("PipeOpTorchAvgPool2D paramtest", { test_that("PipeOpTorchAvgPool3D autotest", { po_test = po("nn_avg_pool3d", kernel_size = c(2, 3, 4)) task = nano_imagenet() - graph = po("torch_ingress_img", channels = 3, width = 64, height = 64) %>>% + graph = po("torch_ingress_ltnsr") %>>% po("nn_reshape", shape = c(NA, 3, 64, 8, 8)) %>>% po_test diff --git a/tests/testthat/test_PipeOpTorchBatchNorm.R b/tests/testthat/test_PipeOpTorchBatchNorm.R index 32b1baaf..2a057d2a 100644 --- a/tests/testthat/test_PipeOpTorchBatchNorm.R +++ b/tests/testthat/test_PipeOpTorchBatchNorm.R @@ -16,7 +16,7 @@ test_that("PipeOpTorchBatchNorm1D paramtest", { test_that("PipeOpTorchBatchNorm2D autotest", { po_test = po("nn_batch_norm2d") task = nano_imagenet() - graph = po("torch_ingress_img", channels = 3, width = 64, height = 64) %>>% po_test + graph = po("torch_ingress_ltnsr") %>>% po_test autotest_pipeop_torch(graph, "nn_batch_norm2d", task) }) @@ -29,7 +29,7 @@ test_that("PipeOpTorchBatchNorm2D paramtest", { test_that("PipeOpTorchBatchNorm3D autotest", { po_test = po("nn_batch_norm3d") task = nano_imagenet() - graph = po("torch_ingress_img", channels = 3, width = 64, height = 64) %>>% + graph = po("torch_ingress_ltnsr") %>>% po("nn_reshape", shape = c(NA, 3, 64, 8, 8)) %>>% po_test diff --git a/tests/testthat/test_PipeOpTorchConv.R b/tests/testthat/test_PipeOpTorchConv.R index eb7c9e55..2b11737c 100644 --- a/tests/testthat/test_PipeOpTorchConv.R +++ b/tests/testthat/test_PipeOpTorchConv.R @@ -14,7 +14,7 @@ test_that("PipeOpTorchConv1d paramtest", { test_that("PipeOpTorchConv2 autotest", { po_conv = po("nn_conv2d", kernel_size = 2, out_channels = 2) task = nano_imagenet() - graph = po("torch_ingress_img", channels = 3, height = 64, width = 64) %>>% po_conv + graph = po("torch_ingress_ltnsr") %>>% po_conv autotest_pipeop_torch(graph, "nn_conv2d", task) }) @@ -27,7 +27,7 @@ test_that("PipeOpTorchConv2d paramtest", { test_that("PipeOpTorchConv3 autotest", { po_conv = po("nn_conv3d", kernel_size = 2, out_channels = 2) task = nano_imagenet() - graph = po("torch_ingress_img", channels = 3, height = 64, width = 64) %>>% + graph = po("torch_ingress_ltnsr") %>>% po("nn_unsqueeze", dim = 5) %>>% po("nn_reshape", shape = c(-1, 3, 64, 8, 8)) %>>% po_conv diff --git a/tests/testthat/test_PipeOpTorchConvTranspose.R b/tests/testthat/test_PipeOpTorchConvTranspose.R index cf09ca0a..d880b3d4 100644 --- a/tests/testthat/test_PipeOpTorchConvTranspose.R +++ b/tests/testthat/test_PipeOpTorchConvTranspose.R @@ -24,7 +24,7 @@ test_that("PipeOpTorchConvTranspose1D paramtest", { test_that("PipeOpTorchConvTranspose2D autotest", { po_conv = po("nn_conv_transpose2d", kernel_size = 2, out_channels = 4) task = nano_imagenet() - graph = po("torch_ingress_img", channels = 3L, height = 64L, width = 64L) %>>% po_conv + graph = po("torch_ingress_ltnsr") %>>% po_conv autotest_pipeop_torch(graph, "nn_conv_transpose2d", task) }) @@ -37,7 +37,7 @@ test_that("PipeOpTorchConvTranspose2D paramtest", { test_that("PipeOpTorchConvTranspose3D autotest", { po_conv = po("nn_conv_transpose3d", kernel_size = 2, out_channels = 4) task = nano_imagenet() - graph = po("torch_ingress_img", channels = 3L, height = 64L, width = 64L) %>>% + graph = po("torch_ingress_ltnsr") %>>% po("nn_reshape", shape = c(-1, 3, 64, 8, 8)) %>>% po_conv diff --git a/tests/testthat/test_PipeOpTorchIngress.R b/tests/testthat/test_PipeOpTorchIngress.R index 2ffb1ca8..6834af15 100644 --- a/tests/testthat/test_PipeOpTorchIngress.R +++ b/tests/testthat/test_PipeOpTorchIngress.R @@ -17,7 +17,7 @@ test_that("PipeOpTorchIngressCategorical", { }) test_that("PipeOpTorchIngressImage", { - po_ingress = po("torch_ingress_img", channels = 3, width = 64, height = 64) + po_ingress = po("torch_ingress_ltnsr") task = nano_imagenet()$cbind(data.frame(x1 = 1:10)) expect_po_ingress(po_ingress, task) }) diff --git a/tests/testthat/test_PipeOpTorchMaxPool.R b/tests/testthat/test_PipeOpTorchMaxPool.R index 2420f87b..cfece7a6 100644 --- a/tests/testthat/test_PipeOpTorchMaxPool.R +++ b/tests/testthat/test_PipeOpTorchMaxPool.R @@ -16,7 +16,7 @@ test_that("PipeOpTorchMaxPool1D paramtest", { test_that("PipeOpTorchMaxPool2D autotest", { po_test = po("nn_max_pool2d", kernel_size = 3) task = nano_imagenet() - graph = po("torch_ingress_img", channels = 3, width = 64, height = 64) %>>% po_test + graph = po("torch_ingress_ltnsr") %>>% po_test autotest_pipeop_torch(graph, "nn_max_pool2d", task) }) @@ -30,7 +30,7 @@ test_that("PipeOpTorchMaxPool2D paramtest", { test_that("PipeOpTorchMaxPool3D autotest", { po_test = po("nn_max_pool3d", kernel_size = c(2, 3, 4)) task = nano_imagenet() - graph = po("torch_ingress_img", channels = 3, width = 64, height = 64) %>>% + graph = po("torch_ingress_ltnsr") %>>% po("nn_reshape", shape = c(NA, 3, 64, 8, 8)) %>>% po_test diff --git a/tests/testthat/test_PipeOpTorchReshape.R b/tests/testthat/test_PipeOpTorchReshape.R index f99bfeca..82c9bc57 100644 --- a/tests/testthat/test_PipeOpTorchReshape.R +++ b/tests/testthat/test_PipeOpTorchReshape.R @@ -46,7 +46,7 @@ test_that("PipeOpTorchSqueeze paramtest", { test_that("PipeOpTorchFlatten autotest", { obj = po("nn_flatten", start_dim = 2, end_dim = 4) task = nano_imagenet() - graph = po("torch_ingress_img", channels = 3, height = 64, width = 64) %>>% obj + graph = po("torch_ingress_ltnsr") %>>% obj autotest_pipeop_torch(graph, "nn_flatten", task) }) diff --git a/tests/testthat/test_helper_tasks.R b/tests/testthat/test_helper_tasks.R new file mode 100644 index 00000000..4ac0a22a --- /dev/null +++ b/tests/testthat/test_helper_tasks.R @@ -0,0 +1,25 @@ +test_that("nano_mnist", { + task = nano_mnist() + x = materialize(task$data(cols = task$feature_names)[[1L]], rbind = TRUE) + expect_equal(x$shape, c(10, 1, 28, 28)) + + xout = materialize(po("augment_vflip")$train(list(task))[[1L]]$data(cols = "image")[[1L]], rbind = TRUE) + expect_equal(xout$shape, c(10, 1, 28, 28)) +}) + +test_that("nano_imagenet", { + task = nano_imagenet() + task$row_roles$use = c(2, 3) + x = materialize(task$data(cols = task$feature_names)[[1L]], rbind = TRUE) + expect_equal(x$shape, c(2, 3, 64, 64)) + + xout = materialize(po("augment_vflip")$train(list(task))[[1L]]$data(cols = "image")[[1L]], rbind = TRUE) + expect_equal(xout$shape, c(2, 3, 64, 64)) +}) + +test_that("nano_dogs_vs_cats", { + task = nano_dogs_vs_cats() + task$row_roles$use = c(2, 3) + x = materialize(task$data(cols = task$feature_names)[[1L]], rbind = FALSE) + expect_list(x, types = "torch_tensor") +}) diff --git a/tests/testthat/test_imageuri.R b/tests/testthat/test_imageuri.R deleted file mode 100644 index 963e0926..00000000 --- a/tests/testthat/test_imageuri.R +++ /dev/null @@ -1,55 +0,0 @@ -test_that("imageuri works", { - cls = c("imageuri", "character") - path = testthat::test_path("assets", "nano_mnist") - image_names = list.files(path) - uris = fs::path_norm(file.path(path, image_names)) - - img1 = uris[[1]] - img2 = uris[[2]] - - images = imageuri(uris) - - # class is correct - expect_class(images, cls) - - # object is invariant under the constructor - expect_equal(imageuri(images), images) - - # subsetting works - expect_equal(imageuri(img1), images[[1]]) - expect_equal(imageuri(img2), images[[2]]) - expect_class(images[1:2], cls) - expect_equal(images[1], images[[1]]) - expect_equal(images[2], images[[2]]) - - # assignment works - images2 = images - images3 = images - n_before2 = length(images2) - images2[1] = img2 - expect_true(length(images2) == n_before2) - - n_before3 = length(images3) - images3[[1]] = img2 - - expect_true(length(images3) == n_before3) - expect_equal(images2, images3) - expect_equal(images2[1], imageuri(img2)) - expect_equal(images3[1], imageuri(img2)) - - expect_error({images[1] = 1}, regexp = "Must be of type 'character'", fixed = TRUE) # nolint - - # c() works - expect_class(c(images[1], images[2]), cls) - expect_equal(c(images[1], as.character(images[2])), images[1:2]) - - expect_error(c(images[1], 1), regexp = "all objects must inherit from 'character'", fixed = TRUE) - - # data.table sanity check - dt = data.table(image = images) - expect_class(dt$image, cls) - expect_equal(dt[1, "image"][[1]], images[1]) - - # rbind works with two data.tables - expect_class(rbind(dt, dt)$image, cls) -}) diff --git a/tests/testthat/test_materialize.R b/tests/testthat/test_materialize.R index f179b980..ed65948e 100644 --- a/tests/testthat/test_materialize.R +++ b/tests/testthat/test_materialize.R @@ -101,7 +101,6 @@ test_that("materialize.list works", { # to check: # a) caching works when en / disabling cache manually - # b) set_keep_results stuff works # c) default = "auto" works as expected # TODO @@ -142,8 +141,8 @@ test_that("materialize_internal: caching of datasets works", { # hashes of environments change after a function was called (?) # https://github.com/mlr-org/mlr3torch/issues/156 expect_equal( - x1$.dataset_hash, - x2$.dataset_hash + dd(x1)$.dataset_hash, + dd(x2)$.dataset_hash ) dd1 = DataDescriptor(ds, list(x = c(NA, 3))) @@ -158,13 +157,9 @@ test_that("materialize_internal: caching of datasets works", { expect_true(ds$count == 10) }) -test_that("materialize_internal: resets everything to previous state", { +test_that("materialize_internal with varying shapes", { -}) - -test_that("materialize_internal: set_keep_results works", { - }) test_that("PipeOpFeatureUnion can properly check whether two lazy tensors are identical", { diff --git a/tests/testthat/test_preprocess.R b/tests/testthat/test_preprocess.R index ec0867c0..7a05f115 100644 --- a/tests/testthat/test_preprocess.R +++ b/tests/testthat/test_preprocess.R @@ -94,7 +94,7 @@ test_that("augment_color_jitter", { test_that("augment_random_resized_crop", { autotest_pipeop_torch_preprocess( - obj = po("augment_random_resized_crop"), + obj = po("augment_random_resized_crop", size = c(4, 5)), shapes_in = list(c(1, 3, 8, 8)) ) }) @@ -159,6 +159,13 @@ test_that("augment_random_vertical_flip", { # ) #}) +#test_that("augment_random_perspective", { +# autotest_pipeop_torch_preprocess( +# obj = po("augment_random_perspective"), +# shapes_in = list(c(1, 3, 8, 8)) +# ) +#}) + test_that("augment_random_affine", { autotest_pipeop_torch_preprocess( obj = po("augment_random_affine", degrees = c(2, 70)), @@ -166,12 +173,6 @@ test_that("augment_random_affine", { ) }) -test_that("augment_random_perspective", { - autotest_pipeop_torch_preprocess( - obj = po("augment_random_perspective"), - shapes_in = list(c(1, 3, 8, 8)) - ) -}) test_that("augment_vflip", { autotest_pipeop_torch_preprocess( diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index de30ffa2..740374d9 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -261,43 +261,36 @@ test_that("default target batchgetter works: classification", { expect_equal(y_loaded1$device$type, "meta") }) -test_that("get_batchgetter_img works", { - task = nano_imagenet() - batchgetter = get_batchgetter_img(imgshape = c(3, 64, 64)) - - dat = task$data(1:2, task$feature_names) - - batch = batchgetter(dat, "cpu") - expect_equal(batch$shape, c(2, 3, 64, 64)) - expect_equal(batch$device$type, "cpu") - expect_true(batch$dtype == torch_float()) - - batchgetter_wrong = get_batchgetter_img(imgshape = c(64, 64)) - expect_error(batchgetter_wrong(dat), regexp = "imgshape") - - batch1 = batchgetter(dat, "meta") - expect_true(batch1$device$type == "meta") -}) - -test_that("dataset_img works", { - task = nano_imagenet() - ds = dataset_img(task, list(device = "cpu", channels = 3, height = 64, width = 64)) - - batch = ds$.getbatch(1:2) - expect_equal(batch$x$image$shape, c(2, 3, 64, 64)) - expect_equal(batch$x$image$device$type, "cpu") - expect_true(batch$x$image$dtype == torch_float()) - - ds_meta = dataset_img(task, list(device = "meta", channels = 3, height = 64, width = 64)) - batch_meta = ds_meta$.getbatch(1) - expect_true(batch_meta$x$image$device$type == "meta") -}) - +test_that("caching of graph works", { + env = new.env() + env$counter = 0L + fn = crate(function(x) { + env$counter = env$counter + 1L + match.call() + print(x) + x + 1 + }, env) + po_test = pipeop_preproc_torch("test", fn = fn , shapes_out = "unchanged") + + taskin = tsk("lazy_iris") + + graph = po_test %>>% + list( + po("trafo_nop_1") %>>% po("renamecolumns", renaming = c(x = "z")), + po("trafo_nop_2")) %>>% + po("featureunion") + + task = graph$train(taskin)[[1L]] + + ingress_tokens = list( + z = TorchIngressToken("z", batchgetter_lazy_tensor, c(NA, 4)), + x = TorchIngressToken("x", batchgetter_lazy_tensor, c(NA, 4)) + ) -test_that("caching works", { - # TODO -}) + ds = task_dataset(task, ingress_tokens, device = "cpu") + ds -test_that("merging of graphs works as expected", { - # TODO + ds$.getbatch(1) + env$counter + expect_equal(envc$counter, 1L) }) From 97435d68ecfef74913824be3075f294bb6020798 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 6 Dec 2023 19:32:07 +0100 Subject: [PATCH 17/90] lets go --- R/PipeOpTaskPreprocTorch.R | 25 ++++++++++++++----------- man/mlr_learners.torch_featureless.Rd | 2 +- man/pipeop_preproc_torch_class.Rd | 3 ++- tests/testthat/test_task_dataset.R | 2 +- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index a56f2c51..e269afbc 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -180,6 +180,8 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", private$.fn = assert_function(fn) private$.rowwise = assert_flag(rowwise) + param_set = assert_param_set(param_set$clone(deep = TRUE)) + param_set$add(ps( stages = p_fct(c("train", "predict", "both"), tags = c("train", "required")) )) @@ -371,7 +373,7 @@ pipeop_preproc_torch = function(id, fn, shapes_out, param_set = NULL, param_vals rowwise = FALSE) { pipeop_preproc_torch_class( id = id, - fn = if (is.language(fn)) fn else subs, + fn = if (is.language(fn)) fn else substitute(fn), shapes_out = shapes_out, param_set = if (is.language(param_set)) param_set else substitute(param_set), packages = if (is.language(packages)) packages else substitute(packages), @@ -439,7 +441,7 @@ create_ps_call = function(fn) { #' po_example$param_set pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, packages = character(0), init_params = list(), - rowwise = FALSE) { + rowwise = FALSE, parent_env = parent.frame()) { assert( check_function(shapes_out, args = c("shapes_in", "param_vals", "task"), null.ok = TRUE), check_choice(shapes_out, c("infer", "unchanged")) @@ -451,11 +453,11 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack } } else { # This should add required tags where it is applicable - param_set = create_ps_call(rlang::eval_tidy(fn)) + param_set = create_ps_call(eval(fn, envir = parent_env)) } if (!is.language(init_params)) init_params = substitute(init_params) - if (!rlang::is_quosure(fn)) fn = rlang::quo(fn) + if (!is.language(fn)) fn = substitute(fn) classname = paste0("PipeOpPreprocTorch", paste0(capitalize(strsplit(id, split = "_")[[1L]]), collapse = "")) # Note that we don't set default values @@ -468,7 +470,7 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack if (batchdim_is_unknown) { sin[1] = 1L } - if (rowwise) { + if (self$rowwise) { sin = sin[-1L] } tensor_in = invoke(torch_empty, .args = sin, device = torch_device("meta")) @@ -479,14 +481,14 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack ) sout = dim(tensor_out) - if (rowwise) { + if (self$rowwise) { sout = c(batch_dim, sout) } else if (batchdim_is_unknown) { sout[1] = NA } list(sout) - }, rowwise, .parent = environment(rlang::eval_tidy(fn))) + }) # FIXME: NSE issues, we need to evaluate fn in the proper environment, # I guess we can use this quosure idea that } else if (identical(shapes_out, "unchanged")) { @@ -521,7 +523,7 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack body(init_fun)[[2]][[3]] = param_set body(init_fun)[[3]][[3]] = init_params body(init_fun)[[4]][[3]] = packages - body(init_fun)[[4]][[6]] = as.expression(fn) + body(init_fun)[[4]][[6]] = fn body(init_fun)[[4]][[7]] = rowwise body(init_fun)[[4]][[8]] = stages_init @@ -530,15 +532,16 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack public = list( initialize = init_fun ), - private = if (!is.null(shapes_out)) list(.shapes_out = shapes_out) else list() + private = if (!is.null(shapes_out)) list(.shapes_out = shapes_out) else list(), + parent_env = parent_env ) return(Class) } register_preproc = function(id, fn, param_set = NULL, shapes_out = NULL, packages = character(0), rowwise = FALSE) { - Class = pipeop_preproc_torch_class(id, rlang::quo(fn), param_set = substitute(param_set), shapes_out = shapes_out, - packages = packages, rowwise = rowwise) + Class = pipeop_preproc_torch_class(id, substitute(fn), param_set = substitute(param_set), shapes_out = shapes_out, + packages = packages, rowwise = rowwise, parent_env = parent.frame()) assign(Class$classname, Class, parent.frame()) register_po(id, Class) } diff --git a/man/mlr_learners.torch_featureless.Rd b/man/mlr_learners.torch_featureless.Rd index f112208f..e80fd342 100644 --- a/man/mlr_learners.torch_featureless.Rd +++ b/man/mlr_learners.torch_featureless.Rd @@ -28,7 +28,7 @@ lrn("regr.torch_featureless", ...) \item classif: 'response', 'prob' \item regr: 'response' } -\item Feature Types: \dQuote{logical}, \dQuote{integer}, \dQuote{numeric}, \dQuote{character}, \dQuote{factor}, \dQuote{ordered}, \dQuote{POSIXct}, \dQuote{imageuri}, \dQuote{lazy_tensor} +\item Feature Types: \dQuote{logical}, \dQuote{integer}, \dQuote{numeric}, \dQuote{character}, \dQuote{factor}, \dQuote{ordered}, \dQuote{POSIXct}, \dQuote{lazy_tensor} \item Required Packages: \CRANpkg{mlr3}, \CRANpkg{mlr3torch}, \CRANpkg{torch} } } diff --git a/man/pipeop_preproc_torch_class.Rd b/man/pipeop_preproc_torch_class.Rd index 0f0b3637..8337838d 100644 --- a/man/pipeop_preproc_torch_class.Rd +++ b/man/pipeop_preproc_torch_class.Rd @@ -11,7 +11,8 @@ pipeop_preproc_torch_class( param_set = NULL, packages = character(0), init_params = list(), - rowwise = FALSE + rowwise = FALSE, + parent_env = parent.frame() ) } \arguments{ diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index 740374d9..8ecdaa6a 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -292,5 +292,5 @@ test_that("caching of graph works", { ds$.getbatch(1) env$counter - expect_equal(envc$counter, 1L) + expect_equal(env$counter, 1L) }) From ceced06b5078ea9085ab4f35bdbd6a2d44c95cc4 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 17 Jan 2024 17:35:12 +0100 Subject: [PATCH 18/90] various improvements * Fix substitution bug (by removing these shenanigans) * Implements DataDescriptor as R6 * Removes the "." from some "private" fields (collapsed with DataDescriptor, as R6 classes use . only for private methods but these fields should be accessible) --- NAMESPACE | 1 - R/DataDescriptor.R | 250 ++++++++++--------- R/LearnerTorch.R | 4 +- R/ModelDescriptor.R | 32 +-- R/PipeOpTaskPreprocTorch.R | 98 ++++---- R/PipeOpTorch.R | 36 +-- R/PipeOpTorchIngress.R | 6 +- R/TaskClassif_mnist.R | 2 +- R/lazy_tensor.R | 44 ++-- R/materialize.R | 18 +- R/nn_graph.R | 8 +- R/task_dataset.R | 26 +- man-roxygen/pipeop_torch_example.R | 6 +- man/DataDescriptor.Rd | 195 +++++++++++---- man/ModelDescriptor.Rd | 14 +- man/materialize.Rd | 2 +- man/materialize_internal.Rd | 2 +- man/mlr_pipeops_torch.Rd | 22 +- man/model_descriptor_to_module.Rd | 6 +- man/model_descriptor_union.Rd | 2 +- man/pipeop_preproc_torch.Rd | 3 +- man/pipeop_preproc_torch_class.Rd | 8 +- tests/testthat/helper_functions.R | 4 +- tests/testthat/helper_learner.R | 2 +- tests/testthat/helper_tasks.R | 2 +- tests/testthat/test_DataDescriptor.R | 20 +- tests/testthat/test_ModelDescriptor.R | 10 +- tests/testthat/test_PipeOpTaskPreprocTorch.R | 8 +- tests/testthat/test_PipeOpTorch.R | 24 +- tests/testthat/test_lazy_tensor.R | 22 +- tests/testthat/test_materialize.R | 15 +- tests/testthat/test_task_dataset.R | 48 ++-- 32 files changed, 529 insertions(+), 411 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 28e2f713..115f2c4e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -26,7 +26,6 @@ S3method(format,lazy_tensor) S3method(materialize,data.frame) S3method(materialize,lazy_tensor) S3method(materialize,list) -S3method(print,DataDescriptor) S3method(print,ModelDescriptor) S3method(print,TorchIngressToken) S3method(reset_last_layer,AlexNet) diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index c3473992..b5b0c00a 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -16,23 +16,29 @@ #' indicate the batch dimension. #' @param graph ([`Graph`])\cr #' The preprocessing graph. -#' If left `NULL`, no preprocessing is applied to the data and `.input_map`, `.pointer` and `.pointer_shape` +#' If left `NULL`, no preprocessing is applied to the data and `input_map`, `pointer` and `pointer_shape` #' are inferred in case the dataset returns only one element. -#' @param .input_map (`character()`)\cr +#' @param input_map (`character()`)\cr #' Character vector that must have the same length as the input of the graph. #' Specifies how the data from the `dataset` is fed into the preprocessing graph. -#' @param .pointer (`character(2)` | `NULL`)\cr +#' @param pointer (`character(2)` | `NULL`)\cr #' Indicating an element on which a model is. Points to an output channel within `graph`: #' Element 1 is the `PipeOp`'s id and element 2 is that `PipeOp`'s output channel. -#' @param .pointer_shape (`integer` | `NULL`)\cr -#' Shape of the output indicated by `.pointer`. +#' @param pointer_shape (`integer` | `NULL`)\cr +#' Shape of the output indicated by `pointer`. #' @param clone_graph (`logical(1)`)\cr #' Whether to clone the preprocessing graph. -#' @param .pointer_shape_predict (`integer()` or `NULL`)\cr +#' @param pointer_shape_predict (`integer()` or `NULL`)\cr #' Internal use only. #' Used in a [`Graph`] to anticipate possible mismatches between train and predict shapes. #' +#' @details +#' While it would be more natural to define this as an S3 class, we opted for an R6 class to avoid the usual +#' trouble of serializing S3 objects. +#' If each row contained a DataDescriptor as an S3 class, this would copy the object when serializing. +#' #' @export +#' @include utils.R #' @seealso ModelDescriptor, lazy_tensor #' @examples #' # Create a dataset @@ -50,140 +56,152 @@ #' #' # Create the data descriptor #' -#' dd = DataDescriptor( +#' dd = DataDescriptor$new( #' dataset = ds, #' dataset_shapes = list(x = c(NA, 3, 3)), #' graph = graph, -#' .input_map = "x", -#' .pointer = c("module", "output"), -#' .pointer_shape = c(NA, 9) +#' input_map = "x", +#' pointer = c("module", "output"), +#' pointer_shape = c(NA, 9) #' ) #' #' # with no preprocessing -#' dd_no_preproc = DataDescriptor(ds, list(x = c(NA, 3, 3))) +#' dd_no_preproc = DataDescriptor$new(ds, list(x = c(NA, 3, 3))) #' dd_no_preproc -DataDescriptor = function(dataset, dataset_shapes, graph = NULL, .input_map = NULL, .pointer = NULL, - .pointer_shape = NULL, .pointer_shape_predict = NULL, clone_graph = TRUE) { - assert_class(dataset, "dataset") - - # If the dataset implements a .getbatch() method the shape must be specified, as it should be the same for - # all batches - # For simplicity we here require the first dimension of the shape to be NA so we don't have to deal with it, - # e.g. during subsetting - assert_shapes(dataset_shapes, null_ok = is.null(dataset$.getbatch), unknown_batch = TRUE, named = TRUE) - assert_shape(.pointer_shape_predict, null_ok = TRUE, unknown_batch = TRUE) - - # not sure whether we should keep this? - #example = if (is.null(dataset$.getbatch)) dataset$.getitem(1L) else dataset$.getbatch(1L) - #if (!test_list(example, names = "unique") || !test_permutation(names(example), names(dataset_shapes))) { - # stopf("Dataset must return a list with named elements that are a permutation of the dataset_shapes names.") - # iwalk(dataset_shapes, function(dataset_shape, name) { - # if (!is.null(dataset_shape) && !test_equal(dataset_shapes[[name]][-1], example[[name]]$shape[-1L])) { - # stopf("First batch from dataset is incompatible with the provided dataset_shapes.") - # } - # }) - #} - - if (is.null(graph)) { - if ((length(dataset_shapes) == 1L) && is.null(.input_map)) { - .input_map = names(dataset_shapes) - } - assert_true(length(.input_map) == 1L) - assert_subset(.input_map, names(dataset_shapes)) - - graph = as_graph(po("nop", id = paste0(class(dataset)[[1L]], "_", .input_map))) - .pointer = c(graph$output$op.id, graph$output$channel.name) - .pointer_shape = dataset_shapes[[.input_map]] - } else { - graph = as_graph(graph, clone = clone_graph) - assert_true(length(graph$pipeops) >= 1L) - - assert_true(!is.null(.input_map)) - assert_choice(.pointer[[1]], names(graph$pipeops)) - assert_choice(.pointer[[2]], graph$pipeops[[.pointer[[1]]]]$output$name) - assert_subset(paste0(.pointer, collapse = "."), graph$output$name) - assert_shape(.pointer_shape, null_ok = TRUE) - - assert_subset(.input_map, names(dataset_shapes)) - assert_true(length(.input_map) == length(graph$input$name)) - } - - # We hash the address of the environment, because the hashes of an environment are not stable, - # even with a .dataset (that should usually not really have a state), hashes might change due to byte-code - # compilation - dataset_hash = calculate_hash(address(dataset)) - - obj = structure( - list( - dataset = dataset, - graph = graph, - dataset_shapes = dataset_shapes, - .input_map = .input_map, - .pointer = .pointer, - .pointer_shape = .pointer_shape, - .dataset_hash = dataset_hash, - .hash = NULL, # is set below - # Once a DataDescriptor is created the input PipeOps are fix, we save them - # here because they can be costly to compute - .graph_input = graph$input$name, - .pointer_shape_predict = .pointer_shape_predict - ), - class = "DataDescriptor" +DataDescriptor = R6Class("DataDescriptor", + public = list( + #' @description Creates a new instance of this [R6][R6::R6Class] class. + initialize = function(dataset, dataset_shapes, graph = NULL, input_map = NULL, pointer = NULL, + pointer_shape = NULL, pointer_shape_predict = NULL, clone_graph = TRUE) { + assert_class(dataset, "dataset") + # If the dataset implements a .getbatch() method the shape must be specified, as it should be the same for + # all batches + # For simplicity we here require the first dimension of the shape to be NA so we don't have to deal with it, + # e.g. during subsetting + assert_shapes(dataset_shapes, null_ok = is.null(dataset$.getbatch), unknown_batch = TRUE, named = TRUE) + assert_shape(pointer_shape_predict, null_ok = TRUE, unknown_batch = TRUE) + + # prevent user from e.g. forgetting to wrap the return in a list + example = if (is.null(dataset$.getbatch)) dataset$.getitem(1L) else dataset$.getbatch(1L) + if (!test_list(example, names = "unique") || !test_permutation(names(example), names(dataset_shapes))) { + stopf("Dataset must return a list with named elements that are a permutation of the dataset_shapes names.") + iwalk(dataset_shapes, function(dataset_shape, name) { + if (!is.null(dataset_shape) && !test_equal(dataset_shapes[[name]][-1], example[[name]]$shape[-1L])) { + stopf("First batch from dataset is incompatible with the provided dataset_shapes.") + } + }) + } + + if (is.null(graph)) { + if ((length(dataset_shapes) == 1L) && is.null(input_map)) { + input_map = names(dataset_shapes) + } + assert_true(length(input_map) == 1L) + assert_subset(input_map, names(dataset_shapes)) + + graph = as_graph(po("nop", id = paste0(class(dataset)[[1L]], "_", input_map))) + pointer = c(graph$output$op.id, graph$output$channel.name) + pointer_shape = dataset_shapes[[input_map]] + } else { + graph = as_graph(graph, clone = clone_graph) + assert_true(length(graph$pipeops) >= 1L) + + assert_true(!is.null(input_map)) + assert_choice(pointer[[1]], names(graph$pipeops)) + assert_choice(pointer[[2]], graph$pipeops[[pointer[[1]]]]$output$name) + assert_subset(paste0(pointer, collapse = "."), graph$output$name) + assert_shape(pointer_shape, null_ok = TRUE) + + assert_subset(input_map, names(dataset_shapes)) + assert_true(length(input_map) == length(graph$input$name)) + } + + # We hash the address of the environment, because the hashes of an environment are not stable, + # even with a .dataset (that should usually not really have a state), hashes might change due to byte-code + # compilation + dataset_hash = calculate_hash(address(dataset)) + + + self$dataset = dataset + self$graph = graph + self$dataset_shapes = dataset_shapes + self$input_map = input_map + self$pointer = pointer + self$pointer_shape = pointer_shape + self$dataset_hash = dataset_hash + self$graph_input = graph$input$name + self$pointer_shape_predict = pointer_shape_predict + self$hash = calculate_hash(self$dataset_hash, self$graph$hash, self$input_map) + }, + #' @description Prints the object + #' @param ... (any)\cr + #' Unused + print = function(...) { + catn(sprintf("", length(self$graph$pipeops))) + catn(sprintf("* dataset_shapes: %s", shape_to_str(self$dataset_shapes))) + catn(sprintf("* input_map: (%s) -> Graph", paste0(self$input_map, collapse = ", "))) + catn(sprintf("* pointer: %s", paste0(self$pointer, collapse = "."))) + catn(str_indent("* .shape(train):", + if (is.null(self$pointer_shape)) "" else shape_to_str(list(self$pointer_shape)))) + catn(str_indent("* shape(predict):", + if (is.null(self$pointer_shape_predict)) "" else shape_to_str(list(self$pointer_shape_predict)))) + }, + #' @field dataset ([`torch::dataset`])\cr + #' The dataset. + dataset = NULL, + #' @field graph ([`Graph`])\cr + #' The preprocessing graph. + graph = NULL, + #' @field dataset_shapes (named `list()` of (`integer()` or `NULL`))\cr + #' The shapes of the output. + dataset_shapes = NULL, + #' @field input_map (`character()`)\cr + #' The input map from the dataset to the preprocessing graph. + input_map = NULL, + #' @field pointer (`character(2)` | `NULL`)\cr + #' The output pointer. + pointer = NULL, + #' @field pointer_shape (`integer` | `NULL`)\cr + #' The shape of the output indicated by `pointer`. + pointer_shape = NULL, + #' @field dataset_hash (`character(1)`)\cr + #' Hash for the wrapped dataset. + dataset_hash = NULL, + #' @field hash (`character(1)`)\cr + #' Hash for the data descriptor. + hash = NULL, + #' @field graph_input (`character()`)\cr + #' The input channels of the preprocessing graph (cached to save time). + graph_input = NULL, + #' @field pointer_shape_predict (`integer()` or `NULL`)\cr + #' Internal use only. + pointer_shape_predict = NULL ) - - obj = set_data_descriptor_hash(obj) - - return(obj) -} +) #' @include utils.R data_descriptor_union = function(dd1, dd2) { # Otherwise it is ugly to do the caching of the data loading # and this is not really a strong restriction - assert_true(dd1$.dataset_hash == dd2$.dataset_hash) + assert_true(dd1$dataset_hash == dd2$dataset_hash) g1 = dd1$graph g2 = dd2$graph input_map = unique(c( - set_names(dd1$.input_map, g1$input$name), - set_names(dd2$.input_map, g2$input$name) + set_names(dd1$input_map, g1$input$name), + set_names(dd2$input_map, g2$input$name) )) graph = merge_graphs(g1, g2) # shallow clone, g1 and g2 graphs (not pipeops) are unmodified - DataDescriptor( + DataDescriptor$new( dataset = dd1$dataset, dataset_shapes = dd1$dataset_shapes, graph = graph, - .input_map = input_map, - .pointer = dd1$.pointer, - .pointer_shape = dd1$.pointer_shape, - .pointer_shape_predict = dd1$.pointer_shape_predict, + input_map = input_map, + pointer = dd1$pointer, + pointer_shape = dd1$pointer_shape, + pointer_shape_predict = dd1$pointer_shape_predict, clone_graph = FALSE ) } - -#' @export -#' @include utils.R -print.DataDescriptor = function(x, ...) { - catn(sprintf("", length(x$graph$pipeops))) - catn(sprintf("* dataset_shapes: %s", shape_to_str(x$dataset_shapes))) - catn(sprintf("* .input_map: (%s) -> Graph", paste0(x$.input_map, collapse = ", "))) - catn(sprintf("* .pointer: %s", paste0(x$.pointer, collapse = "."))) - catn(str_indent("* .shape(train):", - if (is.null(x$.pointer_shape)) "" else shape_to_str(list(x$.pointer_shape)))) - catn(str_indent("* .shape(predict):", - if (is.null(x$.pointer_shape_predict)) "" else shape_to_str(list(x$.pointer_shape_predict)))) -} - -# TODO: printer - -set_data_descriptor_hash = function(data_descriptor) { - # avoid partial argument matching - data_descriptor$.hash = calculate_hash( - data_descriptor[[".dataset_hash"]], - data_descriptor[["graph"]][["hash"]], - data_descriptor[[".input_map"]] - ) - return(data_descriptor) -} diff --git a/R/LearnerTorch.R b/R/LearnerTorch.R index 31ba888d..0a491b98 100644 --- a/R/LearnerTorch.R +++ b/R/LearnerTorch.R @@ -310,8 +310,8 @@ LearnerTorch = R6Class("LearnerTorch", first_row = task$head(1) iwalk(first_row, function(x, nm) { if (!is_lazy_tensor(x)) return(NULL) - predict_shape = x$.pointer_shape_predict - train_shape = x$.pointer_shape + predict_shape = x$pointer_shape_predict + train_shape = x$pointer_shape if (is.null(train_shape) || is.null(predict_shape)) { return(NULL) } diff --git a/R/ModelDescriptor.R b/R/ModelDescriptor.R index 2599d0e6..df2d0fd1 100644 --- a/R/ModelDescriptor.R +++ b/R/ModelDescriptor.R @@ -8,8 +8,8 @@ #' Output shapes are named by the output channels of `graph`; it is also possible #' to represent no-ops on tensors, in which case names of input and output should be identical. #' -#' `ModelDescriptor` objects typically represent partial models being built up, in which case the `.pointer` slot -#' indicates a specific point in the graph that produces a tensor of shape `.pointer_shape`, on which the graph should +#' `ModelDescriptor` objects typically represent partial models being built up, in which case the `pointer` slot +#' indicates a specific point in the graph that produces a tensor of shape `pointer_shape`, on which the graph should #' be extended. #' It is allowed for the `graph` in this structure to be modified by-reference in different parts of the code. #' However, these modifications may never add edges with elements of the `Graph` as destination. In particular, no @@ -34,18 +34,18 @@ #' Additional info: what loss to use. #' @param callbacks (A `list` of [`CallbackSet`] or `NULL`)\cr #' Additional info: what callbacks to use. -#' @param .pointer (`character(2)` | `NULL`)\cr +#' @param pointer (`character(2)` | `NULL`)\cr #' Indicating an element on which a model is. Points to an output channel within `graph`: #' Element 1 is the `PipeOp`'s id and element 2 is that `PipeOp`'s output channel. -#' @param .pointer_shape (`integer` | `NULL`)\cr -#' Shape of the output indicated by `.pointer`. +#' @param pointer_shape (`integer` | `NULL`)\cr +#' Shape of the output indicated by `pointer`. #' #' @family Model Configuration #' @family Graph Network #' @return (`ModelDescriptor`) #' @export -ModelDescriptor = function(graph, ingress, task, optimizer = NULL, loss = NULL, callbacks = NULL, .pointer = NULL, - .pointer_shape = NULL) { +ModelDescriptor = function(graph, ingress, task, optimizer = NULL, loss = NULL, callbacks = NULL, pointer = NULL, + pointer_shape = NULL) { assert_r6(graph, "Graph") innames = graph$input$name # graph$input$name access is slow @@ -64,10 +64,10 @@ ModelDescriptor = function(graph, ingress, task, optimizer = NULL, loss = NULL, callbacks = as_torch_callbacks(callbacks) callbacks = set_names(callbacks, assert_names(ids(callbacks), type = "unique")) - if (!is.null(.pointer)) { - .pointer_shape = assert_shape(.pointer_shape, null_ok = FALSE, unknown_batch = TRUE) - assert_choice(.pointer[[1]], names(graph$pipeops)) - assert_choice(.pointer[[2]], graph$pipeops[[.pointer[[1]]]]$output$name) + if (!is.null(pointer)) { + pointer_shape = assert_shape(pointer_shape, null_ok = FALSE, unknown_batch = TRUE) + assert_choice(pointer[[1]], names(graph$pipeops)) + assert_choice(pointer[[2]], graph$pipeops[[pointer[[1]]]]$output$name) } structure(list( @@ -77,8 +77,8 @@ ModelDescriptor = function(graph, ingress, task, optimizer = NULL, loss = NULL, optimizer = optimizer, loss = loss, callbacks = callbacks, - .pointer = .pointer, - .pointer_shape = .pointer_shape + pointer = pointer, + pointer_shape = pointer_shape ), class = "ModelDescriptor") } @@ -95,8 +95,8 @@ print.ModelDescriptor = function(x, ...) { catn(str_indent("* Callbacks: ", if (!is.null(x$callbacks) && length(x$callbacks)) as_short_string(map_chr(x$callbacks, "label"), 100L) else "N/A")) # nolint catn(str_indent("* Optimizer: ", if (!is.null(x$optimizer)) as_short_string(x$optimizer$label) else "N/A")) catn(str_indent("* Loss: ", if (!is.null(x$loss)) as_short_string(x$loss$label) else "N/A")) - catn(str_indent("* .pointer: ", if (is.null(x$.pointer)) "" else { # nolint - sprintf("\n%s %s", paste(x$.pointer, collapse = "."), shape_to_str(list(x$.pointer_shape))) + catn(str_indent("* pointer: ", if (is.null(x$pointer)) "" else { # nolint + sprintf("\n%s %s", paste(x$pointer, collapse = "."), shape_to_str(list(x$pointer_shape))) })) } @@ -110,7 +110,7 @@ print.ModelDescriptor = function(x, ...) { #' * `graph`s are combinded (if they are not identical to begin with). The first entry's `graph` is modified by #' reference. #' * `PipeOp`s with the same ID must be identical. No new input edges may be added to `PipeOp`s. -#' * Drops `.pointer` / `.pointer_shape` entries. +#' * Drops `pointer` / `pointer_shape` entries. #' * The new task is the [feature union][PipeOpFeatureUnion] of the two incoming tasks. #' * The `optimizer` and `loss` of both [`ModelDescriptor`]s must be identical. #' * Ingress tokens and callbacks are merged, where objects with the same `"id"` must be identical. diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index e269afbc..1e7ca0c5 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -330,11 +330,11 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", packages = self$packages ) - shape_before = dd(lt)$.pointer_shape + shape_before = dd(lt)$pointer_shape shape_out = self$shapes_out(list(shape_before), stage = stage, task = task)[[1L]] shape_out_predict = if (stage == "train") { - shape_in_predict = if (is.null(dd(lt)$.pointer_shape_predict)) shape_before + shape_in_predict = if (is.null(dd(lt)$pointer_shape_predict)) shape_before # during `$train()` we also keep track of the shapes that would arise during predict # This avoids that we first train a learner and then only notice during predict that the shapes # during the predict phase are wrong @@ -361,28 +361,30 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", .fn = NULL ) ) - #' @title Create Torch Preprocessing PipeOps #' @description #' Calls [`pipeop_preproc_torch_class`] and instantiates the instance with the given parameter values. #' @inheritParams pipeop_preproc_torch_class +#' @template param_param_vals #' @param param_vals (`list()`)\cr #' The parameter values. #' @export pipeop_preproc_torch = function(id, fn, shapes_out, param_set = NULL, param_vals = list(), packages = character(0), - rowwise = FALSE) { + rowwise = FALSE, parent_env = parent.frame()) { pipeop_preproc_torch_class( id = id, - fn = if (is.language(fn)) fn else substitute(fn), + fn = fn, shapes_out = shapes_out, - param_set = if (is.language(param_set)) param_set else substitute(param_set), - packages = if (is.language(packages)) packages else substitute(packages), - rowwise = rowwise + param_set = param_set, + packages = packages, + rowwise = rowwise, + parent_env = parent_env )$new(param_vals = param_vals) } -create_ps_call = function(fn) { +create_ps = function(fn) { + # TODO: could simplify this as we don't need the expression anymore fmls = rlang::fn_fmls(fn) param_names = names(fmls) param_names = setdiff(param_names[-1L], "...") @@ -405,7 +407,7 @@ create_ps_call = function(fn) { # Create the final language object result = rlang::expr(ps(!!!args)) - return(result) + eval(result) } #' @title Create Torch Preprocessing PipeOps @@ -431,37 +433,19 @@ create_ps_call = function(fn) { #' All parameters but the first and `...` of `fn` are set as untyped parameters with tags 'train' and those that #' have nod default value are tagged as 'required' as well. #' Default values are not annotated. -#' @template param_param_vals #' @template param_packages #' @export #' @returns An [`R6Class`][R6::R6Class] instance inheriting from [`PipeOpTaskPreprocTorch`] #' @examples #' po_example = pipeop_preproc_torch("preproc_example", function(x, a) x + a) #' po_example -#' po_example$param_set +#' po_example$param_setents cannot be passed as variables but need to be passed as expressions. pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, packages = character(0), - init_params = list(), - rowwise = FALSE, parent_env = parent.frame()) { + init_params = list(), rowwise = FALSE, parent_env = parent.frame(), leanify = NULL) { assert( check_function(shapes_out, args = c("shapes_in", "param_vals", "task"), null.ok = TRUE), check_choice(shapes_out, c("infer", "unchanged")) ) - - if (!is.null(param_set)) { - if (!is.language(param_set)) { - param_set = substitute(param_set) - } - } else { - # This should add required tags where it is applicable - param_set = create_ps_call(eval(fn, envir = parent_env)) - } - - if (!is.language(init_params)) init_params = substitute(init_params) - if (!is.language(fn)) fn = substitute(fn) - - classname = paste0("PipeOpPreprocTorch", paste0(capitalize(strsplit(id, split = "_")[[1L]]), collapse = "")) - # Note that we don't set default values - if (identical(shapes_out, "infer")) { shapes_out = crate(function(shapes_in, param_vals, task) { sin = shapes_in[[1L]] @@ -499,40 +483,52 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack stopf("unreachable") } + param_set = param_set %??% create_ps(fn) + + stages_init = if (startsWith(id, "augment_")) "train" else "both" init_fun = crate(function(id = idname, param_vals = list()) { # nolint - param_set = x1 # nolint - param_set$values = x2 # nolint + info = private$.__construction_info + param_set = info$param_set$clone(deep = TRUE) + param_set$values = info$init_params # nolint super$initialize( id = id, - packages = x3, # nolint + packages = info$packages, param_set = param_set, param_vals = param_vals, - fn = x4, # nolint - rowwise = x5, # nolint - stages_init = x6 # nolint + fn = info$fn, # nolint + rowwise = info$rowwise, + stages_init = info$stages_init ) - }) - stages_init = if (startsWith(id, "augment_")) { - "train" - } else { - "both" - } + # no need to keep the data around after initialiation + private$.__construction_info = NULL + }, param_set, stages_init, rowwise, packages, init_params) formals(init_fun)$id = id - # param_set is already an expression - body(init_fun)[[2]][[3]] = param_set - body(init_fun)[[3]][[3]] = init_params - body(init_fun)[[4]][[3]] = packages - body(init_fun)[[4]][[6]] = fn - body(init_fun)[[4]][[7]] = rowwise - body(init_fun)[[4]][[8]] = stages_init + + classname = paste0("PipeOpPreprocTorch", paste0(capitalize(strsplit(id, split = "_")[[1L]]), collapse = "")) + # Note that we don't set default values + + private = list( + .__construction_info = list( + packages = packages, + param_set = param_set, + fn = fn, + rowwise = rowwise, + stages_init = stages_init, + init_params = init_params + ) + ) + + if (!is.null(shapes_out)) { + private$.shapes_out = shapes_out + } Class = R6Class(classname, inherit = PipeOpTaskPreprocTorch, public = list( initialize = init_fun ), - private = if (!is.null(shapes_out)) list(.shapes_out = shapes_out) else list(), + private = private, parent_env = parent_env ) @@ -540,7 +536,7 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack } register_preproc = function(id, fn, param_set = NULL, shapes_out = NULL, packages = character(0), rowwise = FALSE) { - Class = pipeop_preproc_torch_class(id, substitute(fn), param_set = substitute(param_set), shapes_out = shapes_out, + Class = pipeop_preproc_torch_class(id, fn, param_set = param_set, shapes_out = shapes_out, packages = packages, rowwise = rowwise, parent_env = parent.frame()) assign(Class$classname, Class, parent.frame()) register_po(id, Class) diff --git a/R/PipeOpTorch.R b/R/PipeOpTorch.R index 45ccb5ac..65d9439d 100644 --- a/R/PipeOpTorch.R +++ b/R/PipeOpTorch.R @@ -63,7 +63,7 @@ #' @section Internals: #' During training, the `PipeOpTorch` creates a [`PipeOpModule`] for the given parameter specification and the #' input shapes from the incoming [`ModelDescriptor`](s) using the private method `.make_module()`. -#' The input shapes are provided by the slot `.pointer_shape` of the incoming [`ModelDescriptor`]s. +#' The input shapes are provided by the slot `pointer_shape` of the incoming [`ModelDescriptor`]s. #' The channel names of this [`PipeOpModule`] are identical to the channel names of the generating [`PipeOpTorch`]. #' #' A [model descriptor union][model_descriptor_union] of all incoming [`ModelDescriptor`]s is then created. @@ -71,14 +71,14 @@ #' The [`PipeOpModule`] is added to the [`graph`][Graph] slot of this union and the the edges that connect the #' sending `PipeOpModule`s to the input channel of this `PipeOpModule` are addeded to the graph. #' This is possible because every incoming [`ModelDescriptor`] contains the information about the -#' `id` and the `channel` name of the sending `PipeOp` in the slot `.pointer`. +#' `id` and the `channel` name of the sending `PipeOp` in the slot `pointer`. #' #' The new graph in the [`model_descriptor_union`] represents the current state of the neural network #' architecture. It is isomorphic to the subgraph that consists of all pipeops of class `PipeOpTorch` and #' [`PipeOpTorchIngress`] that are ancestors of this `PipeOpTorch`. #' -#' For the output, a shallow copy of the [`ModelDescriptor`] is created and the `.pointer` and -#' `.pointer_shape` are updated accordingly. The shallow copy means that all [`ModelDescriptor`]s point to the same +#' For the output, a shallow copy of the [`ModelDescriptor`] is created and the `pointer` and +#' `pointer_shape` are updated accordingly. The shallow copy means that all [`ModelDescriptor`]s point to the same #' [`Graph`] which allows the graph to be modified by-reference in different parts of the code. #' @export #' @family Graph Network @@ -183,8 +183,8 @@ #' graph = gunion(list(po("torch_ingress_num_1"), po("torch_ingress_num_2"))) #' mds_in = graph$train( list(task1, task2), single_input = FALSE) #' -#' mds_in[[1L]][c("graph", "task", "ingress", ".pointer", ".pointer_shape")] -#' mds_in[[2L]][c("graph", "task", "ingress", ".pointer", ".pointer_shape")] +#' mds_in[[1L]][c("graph", "task", "ingress", "pointer", "pointer_shape")] +#' mds_in[[2L]][c("graph", "task", "ingress", "pointer", "pointer_shape")] #' #' # creating the PipeOpTorch and training it #' po_torch = PipeOpTorchCustom$new() @@ -208,12 +208,12 @@ #' identical(mds_out[[1L]]$ingress, mds_out[[2L]]$ingress) #' mds_out[[1L]]$ingress #' -#' # The .pointer and .pointer_shape slots are different -#' mds_out[[1L]]$.pointer -#' mds_out[[2L]]$.pointer +#' # The pointer and pointer_shape slots are different +#' mds_out[[1L]]$pointer +#' mds_out[[2L]]$pointer #' -#' mds_out[[1L]]$.pointer_shape -#' mds_out[[2L]]$.pointer_shape +#' mds_out[[1L]]$pointer_shape +#' mds_out[[2L]]$pointer_shape #' #' ## Prediction #' predict_input = list(input1 = task1, input2 = task2) @@ -313,11 +313,11 @@ PipeOpTorch = R6Class("PipeOpTorch", }, .train = function(inputs) { param_vals = self$param_set$get_values() - input_pointers = map(inputs, ".pointer") - input_shapes = map(inputs, ".pointer_shape") + input_pointers = map(inputs, "pointer") + input_shapes = map(inputs, "pointer_shape") # Now begin creating the result-object: it contains a merged version of all `inputs`' $graph slots etc. - # The only thing missing afterwards is (1) integrating module_op to the merged $graph, and adding `.pointer`s. + # The only thing missing afterwards is (1) integrating module_op to the merged $graph, and adding `pointer`s. result_template = Reduce(model_descriptor_union, inputs) task = result_template$task @@ -340,7 +340,7 @@ PipeOpTorch = R6Class("PipeOpTorch", # integrate the operation into the graph result_template$graph$add_pipeop(module_op, clone = FALSE) - # All of the `inputs` contained possibly the same `graph`, but definitely had different `.pointer`s, + # All of the `inputs` contained possibly the same `graph`, but definitely had different `pointer`s, # indicating the different channels from within the `graph` that should be connected to the new operation. vararg = "..." == module_op$input$name[[1L]] current_channel = "..." @@ -355,12 +355,12 @@ PipeOpTorch = R6Class("PipeOpTorch", } # now we split up the result_template into one item per output channel. - # each output channel contains a different `.pointer` / `.pointer_shape`, referring to the + # each output channel contains a different `pointer` / `pointer_shape`, referring to the # individual outputs of the module_op. results = Map(shape = shapes_out, channel_id = module_op$output$name, f = function(shape, channel_id) { r = result_template # unnecessary, but good for readability: result_template is not changed - r$.pointer = c(module_op$id, channel_id) - r$.pointer_shape = shape + r$pointer = c(module_op$id, channel_id) + r$pointer_shape = shape r }) # PipeOp API requires us to only set this to some list. We set it to output shape to ease debugging. diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index 5a14d493..bf0838c8 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -89,8 +89,8 @@ PipeOpTorchIngress = R6Class("PipeOpTorchIngress", graph = graph, ingress = structure(list(ingress), names = graph$input$name), task = task, - .pointer = as.character(graph$output[, c("op.id", "channel.name"), with = FALSE]), - .pointer_shape = ingress$shape + pointer = as.character(graph$output[, c("op.id", "channel.name"), with = FALSE]), + pointer_shape = ingress$shape )) }, .predict = function(inputs) inputs @@ -341,7 +341,7 @@ PipeOpTorchIngressLazyTensor = R6Class("PipeOpTorchIngressLazyTensor", stopf("PipeOpTorchIngressLazyTensor expects 1 'lazy_tensor' feature, but got %i.", length(lazy_cols)) } example = task$data(task$row_ids[1L], lazy_cols)[[1L]] - input_shape = dd(example)$.pointer_shape + input_shape = dd(example)$pointer_shape pv_shape = param_vals$shape if (is.null(input_shape)) { diff --git a/R/TaskClassif_mnist.R b/R/TaskClassif_mnist.R index 9b65c00a..15fa11e8 100644 --- a/R/TaskClassif_mnist.R +++ b/R/TaskClassif_mnist.R @@ -64,7 +64,7 @@ load_task_mnist = function(id = "mnist") { .length = function() dim(self$images)[1L] )(data$image) - data_descriptor = DataDescriptor(dataset = ds, list(image = c(NA, 1, 28, 28))) + data_descriptor = DataDescriptor$new(dataset = ds, list(image = c(NA, 1, 28, 28))) dt = data.table( image = lazy_tensor(data_descriptor), diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index d80bbc2e..fc56cfb5 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -32,17 +32,17 @@ new_lazy_tensor = function(data_descriptor, ids) { # Note that we just include the hash as an attribute, so c() does not allow to combine lazy tensors whose # data descriptors have different hashes. - vctrs::new_vctr(map(ids, function(id) list(id, data_descriptor)), hash = data_descriptor$.hash, class = "lazy_tensor") + vctrs::new_vctr(map(ids, function(id) list(id, data_descriptor)), hash = data_descriptor$hash, class = "lazy_tensor") } #' @export format.lazy_tensor = function(x, ...) { # nolint if (!length(x)) return(character(0)) - shape = dd(x)$.pointer_shape + shape = dd(x)$pointer_shape shape = if (is.null(shape)) { return(rep("", length(x))) } - shape = paste0(dd(x)$.pointer_shape[-1L], collapse = "x") + shape = paste0(dd(x)$pointer_shape[-1L], collapse = "x") map_chr(x, function(elt) { sprintf("", shape) @@ -76,7 +76,7 @@ as_lazy_tensor.DataDescriptor = function(x, ids = NULL) { # nolint #' @export as_lazy_tensor.dataset = function(x, dataset_shapes, ids = NULL, ...) { # nolint - dd = DataDescriptor(dataset = x, dataset_shapes = dataset_shapes, ...) + dd = DataDescriptor$new(dataset = x, dataset_shapes = dataset_shapes, ...) lazy_tensor(dd, ids) } @@ -137,11 +137,11 @@ is_lazy_tensor = function(x) { #' @details #' The following is done: #' 1. A shallow copy of the [`lazy_tensor`]'s preprocessing `graph` is created. -#' 1. The provided `pipeop` is added to the (shallowly cloned) `graph` and connected to the current `.pointer` of the +#' 1. The provided `pipeop` is added to the (shallowly cloned) `graph` and connected to the current `pointer` of the #' [`DataDescriptor`]. -#' 1. The `.pointer` of the [`DataDescriptor`] is updated to point to the new output channel of the `pipeop`. -#' 1. The `.pointer_shape` of the [`DataDescriptor`] set to the provided `shape`. -#' 1. The `.hash` of the [`DataDescriptor`] is updated. +#' 1. The `pointer` of the [`DataDescriptor`] is updated to point to the new output channel of the `pipeop`. +#' 1. The `pointer_shape` of the [`DataDescriptor`] set to the provided `shape`. +#' 1. The `hash` of the [`DataDescriptor`] is updated. #' Input must be PipeOpModule with exactly one input and one output #' shape must be shape with NA in first dimension #' @@ -174,20 +174,20 @@ transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { graph$add_pipeop(pipeop, clone = FALSE) graph$add_edge( - src_id = data_descriptor$.pointer[1L], - src_channel = data_descriptor$.pointer[2L], + src_id = data_descriptor$pointer[1L], + src_channel = data_descriptor$pointer[2L], dst_id = pipeop$id, dst_channel = pipeop$input$name ) - data_descriptor = DataDescriptor( + data_descriptor = DataDescriptor$new( data_descriptor$dataset, dataset_shapes = data_descriptor$dataset_shapes, graph = graph, - .input_map = data_descriptor$.input_map, - .pointer = c(pipeop$id, pipeop$output$name), - .pointer_shape = shape, - .pointer_shape_predict = shape_predict, + input_map = data_descriptor$input_map, + pointer = c(pipeop$id, pipeop$output$name), + pointer_shape = shape, + pointer_shape_predict = shape_predict, clone_graph = FALSE ) @@ -211,13 +211,13 @@ transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { "dataset", "graph", "dataset_shapes", - ".input_map", - ".pointer", - ".pointer_shape", - ".dataset_hash", - ".hash", - ".graph_input", - ".pointer_shape_predict" + "input_map", + "pointer", + "pointer_shape", + "dataset_hash", + "hash", + "graph_input", + "pointer_shape_predict" )) dd[[name]] } diff --git a/R/materialize.R b/R/materialize.R index 9f9f0ffc..fc7052d3 100644 --- a/R/materialize.R +++ b/R/materialize.R @@ -11,7 +11,7 @@ #' Materializing a lazy tensor consists of: #' 1. Loading the data from the internal dataset of the [`DataDescriptor`]. #' 2. Processing these batches in the preprocessing [`Graph`]s. -#' 3. Returning the result of the [`PipeOp`] pointed to by the [`DataDescriptor`] (`.pointer`). +#' 3. Returning the result of the [`PipeOp`] pointed to by the [`DataDescriptor`] (`pointer`). #' #' With multiple [`lazy_tensor`] columns we can benefit from caching because: #' a) Output(s) from the dataset might be input to multiple graphs. @@ -53,8 +53,8 @@ materialize.list = function(x, device = "cpu", rbind = FALSE, cache = "auto") { assert(check_choice(cache, "auto"), check_environment(cache, null.ok = TRUE)) if (identical(cache, "auto")) { - data_hashes = map_chr(x_lt, function(x) dd(x)$.dataset_hash) - hashes = map_chr(x_lt, function(x) x$.hash) + data_hashes = map_chr(x_lt, function(x) dd(x)$dataset_hash) + hashes = map_chr(x_lt, function(x) x$hash) cache = if (uniqueN(data_hashes) > 1L || uniqueN(hashes) > 1L) { new.env() } @@ -91,7 +91,7 @@ materialize.lazy_tensor = function(x, device = "cpu", rbind = FALSE) { # nolint #' Materializing a lazy tensor consists of: #' 1. Loading the data from the internal dataset of the [`DataDescriptor`]. #' 2. Processing these batches in the preprocessing [`Graph`]s. -#' 3. Returning the result of the [`PipeOp`] pointed to by the [`DataDescriptor`] (`.pointer`). +#' 3. Returning the result of the [`PipeOp`] pointed to by the [`DataDescriptor`] (`pointer`). #' #' When materializing multiple [`lazy_tensor`] columns, caching can be useful because: #' a) Output(s) from the dataset might be input to multiple graphs. @@ -124,15 +124,15 @@ materialize_internal = function(x, device = "cpu", cache = NULL, rbind) { graph = data_descriptor$graph varying_shapes = some(data_descriptor$dataset_shapes, is.null) - pointer_name = paste0(data_descriptor$.pointer, collapse = ".") + pointer_name = paste0(data_descriptor$pointer, collapse = ".") if (do_caching) { - output_hash = calculate_hash(ids, data_descriptor$.hash) + output_hash = calculate_hash(ids, data_descriptor$hash) output_hit = exists(output_hash, cache, inherits = FALSE) if (output_hit) { return(cache[[output_hash]][[pointer_name]]) } - input_hash = calculate_hash(data_descriptor$.dataset_hash, ids) + input_hash = calculate_hash(data_descriptor$dataset_hash, ids) input_hit = exists(input_hash, cache, inherits = FALSE) @@ -169,10 +169,10 @@ materialize_internal = function(x, device = "cpu", cache = NULL, rbind) { # this can change input = if (rbind && !varying_shapes) { - set_names(input[data_descriptor$.input_map], data_descriptor$.graph_input) + set_names(input[data_descriptor$input_map], data_descriptor$graph_input) } else { map(input, function(x) { - set_names(x[data_descriptor$.input_map], data_descriptor$.graph_input) + set_names(x[data_descriptor$input_map], data_descriptor$graph_input) }) } diff --git a/R/nn_graph.R b/R/nn_graph.R index badeb79a..14f4acf5 100644 --- a/R/nn_graph.R +++ b/R/nn_graph.R @@ -84,11 +84,11 @@ nn_graph = nn_module( #' most circumstances harder to use than just creating [`nn_graph`] directly. #' #' @param model_descriptor ([`ModelDescriptor`])\cr -#' Model Descriptor. `.pointer` is ignored, instead `output_pointer` values are used. `$graph` member is +#' Model Descriptor. `pointer` is ignored, instead `output_pointer` values are used. `$graph` member is #' modified by-reference. #' @param output_pointers (`list` of `character`)\cr -#' Collection of `.pointer`s that indicate what part of the `model_descriptor$graph` is being used for output. -#' Entries have the format of `ModelDescriptor$.pointer`. +#' Collection of `pointer`s that indicate what part of the `model_descriptor$graph` is being used for output. +#' Entries have the format of `ModelDescriptor$pointer`. #' @param list_output (`logical(1)`)\cr #' Whether output should be a list of tensors. If `FALSE`, then `length(output_pointers)` must be 1. #' @@ -99,7 +99,7 @@ model_descriptor_to_module = function(model_descriptor, output_pointers = NULL, assert_class(model_descriptor, "ModelDescriptor") assert_flag(list_output) assert_list(output_pointers, types = "character", len = if (!list_output) 1, null.ok = TRUE) - output_pointers = output_pointers %??% list(model_descriptor$.pointer) + output_pointers = output_pointers %??% list(model_descriptor$pointer) # all graph inputs have an entry in self$shapes_in # ModelDescriptor allows Graph to grow by-reference and therefore may have diff --git a/R/task_dataset.R b/R/task_dataset.R index 4854f67b..3c798436 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -72,7 +72,7 @@ task_dataset = dataset( } } - self$cache_lazy_tensors = length(unique(map_chr(data, function(x) x$.hash))) > 1L + self$cache_lazy_tensors = length(unique(map_chr(data, function(x) x$hash))) > 1L }, .getbatch = function(index) { cache = if (self$cache_lazy_tensors) new.env() @@ -96,11 +96,11 @@ task_dataset = dataset( merge_lazy_tensor_graphs = function(lts) { # Otherwise it is ugly to do the caching of the data loading # and this is not really a strong restriction - assert_true(length(unique(map_chr(lts, function(x) dd(x)$.dataset_hash))) == 1L) + assert_true(length(unique(map_chr(lts, function(x) dd(x)$dataset_hash))) == 1L) graph = Reduce(merge_graphs, map(lts, function(x) dd(x)$graph)) input_map = Reduce(c, map(lts, function(lt) { - set_names(list(dd(lt)$.input_map), dd(lt)$graph$input$name) + set_names(list(dd(lt)$input_map), dd(lt)$graph$input$name) })) input_map = input_map[unique(names(input_map))] @@ -110,31 +110,31 @@ merge_lazy_tensor_graphs = function(lts) { # some PipeOs that were previously terminal might not be anymore, # for those we add nops and updaate the pointers for their data descriptors map_dtc(lts, function(lt) { - pointer_name = paste0(lt$.pointer, collapse = ".") + pointer_name = paste0(lt$pointer, collapse = ".") pointer = if (pointer_name %nin% graph$output$name) { po_terminal = po("nop", id = uniqueify(pointer_name, graph$ids())) graph$add_pipeop(po_terminal, clone = FALSE) graph$add_pipeop( - src_id = lt$.pointer[1L], + src_id = lt$pointer[1L], dst_id = po_terminal$id, - src_channel = lt$.pointer[2L], + src_channel = lt$pointer[2L], dst_channel = po_terminal$input$name ) c(po_terminal$id, po_terminal$output$name) } else { - lt$.pointer + lt$pointer } - data_descriptor = DataDescriptor( + data_descriptor = DataDescriptor$new( dataset = dd(lts[[1]])$dataset, dataset_shapes = dd(lts[[1L]])$dataset_shapes, graph = graph, - .input_map = input_map, - .pointer = pointer, - .pointer_shape = lt$.pointer_shape, - .pointer_shape_predict = lt$.pointer_shape_predict, + input_map = input_map, + pointer = pointer, + pointer_shape = lt$pointer_shape, + pointer_shape_predict = lt$pointer_shape_predict, clone_graph = FALSE ) new_lazy_tensor(data_descriptor, map_int(vec_data(lt), 1L)) @@ -143,7 +143,7 @@ merge_lazy_tensor_graphs = function(lts) { dataset_ltnsr = function(task, param_vals) { assert_true(length(task$feature_names) == 1L) - shape = dd(task$data(cols = task$feature_names)[[1L]])$.pointer_shape + shape = dd(task$data(cols = task$feature_names)[[1L]])$pointer_shape if (is.null(shape)) { stopf("Each row element of the lazy tensor column must be of a known shape, please resize it accordingly.") } diff --git a/man-roxygen/pipeop_torch_example.R b/man-roxygen/pipeop_torch_example.R index 9f737cd3..37a22048 100644 --- a/man-roxygen/pipeop_torch_example.R +++ b/man-roxygen/pipeop_torch_example.R @@ -19,7 +19,7 @@ # # # # These are the output shapes generated by the pipeop for the given task -# pipeop$shapes_out(md$.pointer_shape) +# pipeop$shapes_out(md$pointer_shape) # # # Apply the pipeop to the model descriptor # mdout = pipeop$train(list(md))[[1L]] @@ -31,7 +31,7 @@ # # # The pointer is updated to the output channel of the applied pipeop # c(pipeop$id, pipeop$output$name) -# mdout$.pointer +# mdout$pointer # # # The shapes are equal to those calculated by `$shapes_out()` above -# mdout$.pointer_shape +# mdout$pointer_shape diff --git a/man/DataDescriptor.Rd b/man/DataDescriptor.Rd index 5afc3182..2e8f1342 100644 --- a/man/DataDescriptor.Rd +++ b/man/DataDescriptor.Rd @@ -3,51 +3,6 @@ \name{DataDescriptor} \alias{DataDescriptor} \title{Data Descriptor} -\usage{ -DataDescriptor( - dataset, - dataset_shapes, - graph = NULL, - .input_map = NULL, - .pointer = NULL, - .pointer_shape = NULL, - .pointer_shape_predict = NULL, - clone_graph = TRUE -) -} -\arguments{ -\item{dataset}{(\code{\link[torch:dataset]{torch::dataset}})\cr -The torch dataset.} - -\item{dataset_shapes}{(named \code{list()} of (\code{integer()} or \code{NULL}))\cr -The shapes of the output. -Names are the elements of the list returned by the dataset. -If the shape is not \code{NULL} (unknown, e.g. for images of different sizes) the first dimension must be \code{NA} to -indicate the batch dimension.} - -\item{graph}{(\code{\link{Graph}})\cr -The preprocessing graph. -If left \code{NULL}, no preprocessing is applied to the data and \code{.input_map}, \code{.pointer} and \code{.pointer_shape} -are inferred in case the dataset returns only one element.} - -\item{.input_map}{(\code{character()})\cr -Character vector that must have the same length as the input of the graph. -Specifies how the data from the \code{dataset} is fed into the preprocessing graph.} - -\item{.pointer}{(\code{character(2)} | \code{NULL})\cr -Indicating an element on which a model is. Points to an output channel within \code{graph}: -Element 1 is the \code{PipeOp}'s id and element 2 is that \code{PipeOp}'s output channel.} - -\item{.pointer_shape}{(\code{integer} | \code{NULL})\cr -Shape of the output indicated by \code{.pointer}.} - -\item{.pointer_shape_predict}{(\code{integer()} or \code{NULL})\cr -Internal use only. -Used in a \code{\link{Graph}} to anticipate possible mismatches between train and predict shapes.} - -\item{clone_graph}{(\code{logical(1)})\cr -Whether to clone the preprocessing graph.} -} \description{ A data descriptor is a rather internal data structure used in the \code{\link{lazy_tensor}} data type. In essence it is an annotated \code{\link[torch:dataset]{torch::dataset}} and a preprocessing graph (consisting mosty of \code{\link{PipeOpModule}} @@ -55,6 +10,11 @@ operators). The additional meta data (e.g. pointer, shapes) allows to preprocess \code{\link[mlr3pipelines:Graph]{mlr3pipelines::Graph}} just like any (non-lazy) data types. The preprocessing is applied when \code{\link[=materialize]{materialize()}} is called on the \code{\link{lazy_tensor}}. } +\details{ +While it would be more natural to define this as an S3 class, we opted for an R6 class to avoid the usual +trouble of serializing S3 objects. +If each row contained a DataDescriptor as an S3 class, this would copy the object when serializing. +} \examples{ # Create a dataset dsg = dataset( @@ -71,19 +31,154 @@ graph = as_graph(po_module) # Create the data descriptor -dd = DataDescriptor( +dd = DataDescriptor$new( dataset = ds, dataset_shapes = list(x = c(NA, 3, 3)), graph = graph, - .input_map = "x", - .pointer = c("module", "output"), - .pointer_shape = c(NA, 9) + input_map = "x", + pointer = c("module", "output"), + pointer_shape = c(NA, 9) ) # with no preprocessing -dd_no_preproc = DataDescriptor(ds, list(x = c(NA, 3, 3))) +dd_no_preproc = DataDescriptor$new(ds, list(x = c(NA, 3, 3))) dd_no_preproc } \seealso{ ModelDescriptor, lazy_tensor } +\section{Public fields}{ +\if{html}{\out{
}} +\describe{ +\item{\code{dataset}}{(\code{\link[torch:dataset]{torch::dataset}})\cr +The dataset.} + +\item{\code{graph}}{(\code{\link{Graph}})\cr +The preprocessing graph.} + +\item{\code{dataset_shapes}}{(named \code{list()} of (\code{integer()} or \code{NULL}))\cr +The shapes of the output.} + +\item{\code{input_map}}{(\code{character()})\cr +The input map from the dataset to the preprocessing graph.} + +\item{\code{pointer}}{(\code{character(2)} | \code{NULL})\cr +The output pointer.} + +\item{\code{pointer_shape}}{(\code{integer} | \code{NULL})\cr +The shape of the output indicated by \code{pointer}.} + +\item{\code{dataset_hash}}{(\code{character(1)})\cr +Hash for the wrapped dataset.} + +\item{\code{hash}}{(\code{character(1)})\cr +Hash for the data descriptor.} + +\item{\code{graph_input}}{(\code{character()})\cr +The input channels of the preprocessing graph (cached to save time).} + +\item{\code{pointer_shape_predict}}{(\code{integer()} or \code{NULL})\cr +Internal use only.} +} +\if{html}{\out{
}} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-DataDescriptor-new}{\code{DataDescriptor$new()}} +\item \href{#method-DataDescriptor-print}{\code{DataDescriptor$print()}} +\item \href{#method-DataDescriptor-clone}{\code{DataDescriptor$clone()}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-DataDescriptor-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{DataDescriptor$new( + dataset, + dataset_shapes, + graph = NULL, + input_map = NULL, + pointer = NULL, + pointer_shape = NULL, + pointer_shape_predict = NULL, + clone_graph = TRUE +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{dataset}}{(\code{\link[torch:dataset]{torch::dataset}})\cr +The torch dataset.} + +\item{\code{dataset_shapes}}{(named \code{list()} of (\code{integer()} or \code{NULL}))\cr +The shapes of the output. +Names are the elements of the list returned by the dataset. +If the shape is not \code{NULL} (unknown, e.g. for images of different sizes) the first dimension must be \code{NA} to +indicate the batch dimension.} + +\item{\code{graph}}{(\code{\link{Graph}})\cr +The preprocessing graph. +If left \code{NULL}, no preprocessing is applied to the data and \code{input_map}, \code{pointer} and \code{pointer_shape} +are inferred in case the dataset returns only one element.} + +\item{\code{input_map}}{(\code{character()})\cr +Character vector that must have the same length as the input of the graph. +Specifies how the data from the \code{dataset} is fed into the preprocessing graph.} + +\item{\code{pointer}}{(\code{character(2)} | \code{NULL})\cr +Indicating an element on which a model is. Points to an output channel within \code{graph}: +Element 1 is the \code{PipeOp}'s id and element 2 is that \code{PipeOp}'s output channel.} + +\item{\code{pointer_shape}}{(\code{integer} | \code{NULL})\cr +Shape of the output indicated by \code{pointer}.} + +\item{\code{pointer_shape_predict}}{(\code{integer()} or \code{NULL})\cr +Internal use only. +Used in a \code{\link{Graph}} to anticipate possible mismatches between train and predict shapes.} + +\item{\code{clone_graph}}{(\code{logical(1)})\cr +Whether to clone the preprocessing graph.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-DataDescriptor-print}{}}} +\subsection{Method \code{print()}}{ +Prints the object +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{DataDescriptor$print(...)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{...}}{(any)\cr +Unused} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-DataDescriptor-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{DataDescriptor$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/ModelDescriptor.Rd b/man/ModelDescriptor.Rd index 84814878..a6e9ee4a 100644 --- a/man/ModelDescriptor.Rd +++ b/man/ModelDescriptor.Rd @@ -11,8 +11,8 @@ ModelDescriptor( optimizer = NULL, loss = NULL, callbacks = NULL, - .pointer = NULL, - .pointer_shape = NULL + pointer = NULL, + pointer_shape = NULL ) } \arguments{ @@ -34,12 +34,12 @@ Additional info: what loss to use.} \item{callbacks}{(A \code{list} of \code{\link{CallbackSet}} or \code{NULL})\cr Additional info: what callbacks to use.} -\item{.pointer}{(\code{character(2)} | \code{NULL})\cr +\item{pointer}{(\code{character(2)} | \code{NULL})\cr Indicating an element on which a model is. Points to an output channel within \code{graph}: Element 1 is the \code{PipeOp}'s id and element 2 is that \code{PipeOp}'s output channel.} -\item{.pointer_shape}{(\code{integer} | \code{NULL})\cr -Shape of the output indicated by \code{.pointer}.} +\item{pointer_shape}{(\code{integer} | \code{NULL})\cr +Shape of the output indicated by \code{pointer}.} } \value{ (\code{ModelDescriptor}) @@ -52,8 +52,8 @@ pipes them through \code{graph}. Input shapes get mapped to input channels of \c Output shapes are named by the output channels of \code{graph}; it is also possible to represent no-ops on tensors, in which case names of input and output should be identical. -\code{ModelDescriptor} objects typically represent partial models being built up, in which case the \code{.pointer} slot -indicates a specific point in the graph that produces a tensor of shape \code{.pointer_shape}, on which the graph should +\code{ModelDescriptor} objects typically represent partial models being built up, in which case the \code{pointer} slot +indicates a specific point in the graph that produces a tensor of shape \code{pointer_shape}, on which the graph should be extended. It is allowed for the \code{graph} in this structure to be modified by-reference in different parts of the code. However, these modifications may never add edges with elements of the \code{Graph} as destination. In particular, no diff --git a/man/materialize.Rd b/man/materialize.Rd index 303d52dc..37716a52 100644 --- a/man/materialize.Rd +++ b/man/materialize.Rd @@ -38,7 +38,7 @@ Materializing a lazy tensor consists of: \enumerate{ \item Loading the data from the internal dataset of the \code{\link{DataDescriptor}}. \item Processing these batches in the preprocessing \code{\link{Graph}}s. -\item Returning the result of the \code{\link{PipeOp}} pointed to by the \code{\link{DataDescriptor}} (\code{.pointer}). +\item Returning the result of the \code{\link{PipeOp}} pointed to by the \code{\link{DataDescriptor}} (\code{pointer}). } With multiple \code{\link{lazy_tensor}} columns we can benefit from caching because: diff --git a/man/materialize_internal.Rd b/man/materialize_internal.Rd index e26bd856..2c5b36b8 100644 --- a/man/materialize_internal.Rd +++ b/man/materialize_internal.Rd @@ -31,7 +31,7 @@ Materializing a lazy tensor consists of: \enumerate{ \item Loading the data from the internal dataset of the \code{\link{DataDescriptor}}. \item Processing these batches in the preprocessing \code{\link{Graph}}s. -\item Returning the result of the \code{\link{PipeOp}} pointed to by the \code{\link{DataDescriptor}} (\code{.pointer}). +\item Returning the result of the \code{\link{PipeOp}} pointed to by the \code{\link{DataDescriptor}} (\code{pointer}). } When materializing multiple \code{\link{lazy_tensor}} columns, caching can be useful because: diff --git a/man/mlr_pipeops_torch.Rd b/man/mlr_pipeops_torch.Rd index da2de0f9..f0308fc6 100644 --- a/man/mlr_pipeops_torch.Rd +++ b/man/mlr_pipeops_torch.Rd @@ -73,7 +73,7 @@ be automatically inferred from the shapes of the input tensors. During training, the \code{PipeOpTorch} creates a \code{\link{PipeOpModule}} for the given parameter specification and the input shapes from the incoming \href{s}{\code{ModelDescriptor}} using the private method \code{.make_module()}. -The input shapes are provided by the slot \code{.pointer_shape} of the incoming \code{\link{ModelDescriptor}}s. +The input shapes are provided by the slot \code{pointer_shape} of the incoming \code{\link{ModelDescriptor}}s. The channel names of this \code{\link{PipeOpModule}} are identical to the channel names of the generating \code{\link{PipeOpTorch}}. A \link[=model_descriptor_union]{model descriptor union} of all incoming \code{\link{ModelDescriptor}}s is then created. @@ -81,14 +81,14 @@ Note that this modifies the \code{\link[=Graph]{graph}} of the first \code{\link The \code{\link{PipeOpModule}} is added to the \code{\link[=Graph]{graph}} slot of this union and the the edges that connect the sending \code{PipeOpModule}s to the input channel of this \code{PipeOpModule} are addeded to the graph. This is possible because every incoming \code{\link{ModelDescriptor}} contains the information about the -\code{id} and the \code{channel} name of the sending \code{PipeOp} in the slot \code{.pointer}. +\code{id} and the \code{channel} name of the sending \code{PipeOp} in the slot \code{pointer}. The new graph in the \code{\link{model_descriptor_union}} represents the current state of the neural network architecture. It is isomorphic to the subgraph that consists of all pipeops of class \code{PipeOpTorch} and \code{\link{PipeOpTorchIngress}} that are ancestors of this \code{PipeOpTorch}. -For the output, a shallow copy of the \code{\link{ModelDescriptor}} is created and the \code{.pointer} and -\code{.pointer_shape} are updated accordingly. The shallow copy means that all \code{\link{ModelDescriptor}}s point to the same +For the output, a shallow copy of the \code{\link{ModelDescriptor}} is created and the \code{pointer} and +\code{pointer_shape} are updated accordingly. The shallow copy means that all \code{\link{ModelDescriptor}}s point to the same \code{\link{Graph}} which allows the graph to be modified by-reference in different parts of the code. } @@ -193,8 +193,8 @@ task2 = task$clone()$select(paste0("Petal.", c("Length", "Width"))) graph = gunion(list(po("torch_ingress_num_1"), po("torch_ingress_num_2"))) mds_in = graph$train( list(task1, task2), single_input = FALSE) -mds_in[[1L]][c("graph", "task", "ingress", ".pointer", ".pointer_shape")] -mds_in[[2L]][c("graph", "task", "ingress", ".pointer", ".pointer_shape")] +mds_in[[1L]][c("graph", "task", "ingress", "pointer", "pointer_shape")] +mds_in[[2L]][c("graph", "task", "ingress", "pointer", "pointer_shape")] # creating the PipeOpTorch and training it po_torch = PipeOpTorchCustom$new() @@ -218,12 +218,12 @@ mds_out[[2L]]$task identical(mds_out[[1L]]$ingress, mds_out[[2L]]$ingress) mds_out[[1L]]$ingress -# The .pointer and .pointer_shape slots are different -mds_out[[1L]]$.pointer -mds_out[[2L]]$.pointer +# The pointer and pointer_shape slots are different +mds_out[[1L]]$pointer +mds_out[[2L]]$pointer -mds_out[[1L]]$.pointer_shape -mds_out[[2L]]$.pointer_shape +mds_out[[1L]]$pointer_shape +mds_out[[2L]]$pointer_shape ## Prediction predict_input = list(input1 = task1, input2 = task2) diff --git a/man/model_descriptor_to_module.Rd b/man/model_descriptor_to_module.Rd index 1da0e702..33ffefc9 100644 --- a/man/model_descriptor_to_module.Rd +++ b/man/model_descriptor_to_module.Rd @@ -12,12 +12,12 @@ model_descriptor_to_module( } \arguments{ \item{model_descriptor}{(\code{\link{ModelDescriptor}})\cr -Model Descriptor. \code{.pointer} is ignored, instead \code{output_pointer} values are used. \verb{$graph} member is +Model Descriptor. \code{pointer} is ignored, instead \code{output_pointer} values are used. \verb{$graph} member is modified by-reference.} \item{output_pointers}{(\code{list} of \code{character})\cr -Collection of \code{.pointer}s that indicate what part of the \code{model_descriptor$graph} is being used for output. -Entries have the format of \code{ModelDescriptor$.pointer}.} +Collection of \code{pointer}s that indicate what part of the \code{model_descriptor$graph} is being used for output. +Entries have the format of \code{ModelDescriptor$pointer}.} \item{list_output}{(\code{logical(1)})\cr Whether output should be a list of tensors. If \code{FALSE}, then \code{length(output_pointers)} must be 1.} diff --git a/man/model_descriptor_union.Rd b/man/model_descriptor_union.Rd index 73effd81..63ffa75c 100644 --- a/man/model_descriptor_union.Rd +++ b/man/model_descriptor_union.Rd @@ -24,7 +24,7 @@ It creates the union of multiple \code{\link{ModelDescriptor}}s: \item \code{graph}s are combinded (if they are not identical to begin with). The first entry's \code{graph} is modified by reference. \item \code{PipeOp}s with the same ID must be identical. No new input edges may be added to \code{PipeOp}s. -\item Drops \code{.pointer} / \code{.pointer_shape} entries. +\item Drops \code{pointer} / \code{pointer_shape} entries. \item The new task is the \link[=PipeOpFeatureUnion]{feature union} of the two incoming tasks. \item The \code{optimizer} and \code{loss} of both \code{\link{ModelDescriptor}}s must be identical. \item Ingress tokens and callbacks are merged, where objects with the same \code{"id"} must be identical. diff --git a/man/pipeop_preproc_torch.Rd b/man/pipeop_preproc_torch.Rd index 9195a029..38848db3 100644 --- a/man/pipeop_preproc_torch.Rd +++ b/man/pipeop_preproc_torch.Rd @@ -11,7 +11,8 @@ pipeop_preproc_torch( param_set = NULL, param_vals = list(), packages = character(0), - rowwise = FALSE + rowwise = FALSE, + parent_env = parent.frame() ) } \arguments{ diff --git a/man/pipeop_preproc_torch_class.Rd b/man/pipeop_preproc_torch_class.Rd index 8337838d..4e67baa2 100644 --- a/man/pipeop_preproc_torch_class.Rd +++ b/man/pipeop_preproc_torch_class.Rd @@ -12,7 +12,8 @@ pipeop_preproc_torch_class( packages = character(0), init_params = list(), rowwise = FALSE, - parent_env = parent.frame() + parent_env = parent.frame(), + leanify = NULL ) } \arguments{ @@ -42,9 +43,6 @@ Default values are not annotated.} \item{packages}{(\code{character()})\cr The R packages this object depends on.} - -\item{param_vals}{(named \code{list()})\cr -Parameter values to be set after construction.} } \value{ An \code{\link[R6:R6Class]{R6Class}} instance inheriting from \code{\link{PipeOpTaskPreprocTorch}} @@ -56,5 +54,5 @@ Start by reading the documentation of \code{\link{PipeOpTaskPreprocTorch}}. \examples{ po_example = pipeop_preproc_torch("preproc_example", function(x, a) x + a) po_example -po_example$param_set +po_example$param_setents cannot be passed as variables but need to be passed as expressions. } diff --git a/tests/testthat/helper_functions.R b/tests/testthat/helper_functions.R index 168e28c2..f5051b77 100644 --- a/tests/testthat/helper_functions.R +++ b/tests/testthat/helper_functions.R @@ -7,8 +7,8 @@ expect_po_ingress = function(po_ingress, task) { testthat::expect_true(token$graph$ids() == po_ingress$id) testthat::expect_true(all(token$task$feature_types$type %in% po_ingress$feature_types)) testthat::expect_equal(token$callbacks, named_list()) - testthat::expect_equal(token$.pointer, c(po_ingress$id, "output")) - testthat::expect_equal(token$.pointer_shape, get_private(po_ingress)$.shape(task, po_ingress$param_set$values)) + testthat::expect_equal(token$pointer, c(po_ingress$id, "output")) + testthat::expect_equal(token$pointer_shape, get_private(po_ingress)$.shape(task, po_ingress$param_set$values)) ingress = token$ingress expect_set_equal( diff --git a/tests/testthat/helper_learner.R b/tests/testthat/helper_learner.R index ac7b016e..9a6790f1 100644 --- a/tests/testthat/helper_learner.R +++ b/tests/testthat/helper_learner.R @@ -70,7 +70,7 @@ LearnerTorchImageTest = R6Class("LearnerTorchImageTest", ), private = list( .network = function(task, param_vals) { - shape = dd(task$data(task$row_ids[1L], task$feature_names)[[1L]])$.pointer_shape + shape = dd(task$data(task$row_ids[1L], task$feature_names)[[1L]])$pointer_shape d = prod(shape[-1]) nout = get_nout(task) nn_sequential( diff --git a/tests/testthat/helper_tasks.R b/tests/testthat/helper_tasks.R index b420aa89..5f223b34 100644 --- a/tests/testthat/helper_tasks.R +++ b/tests/testthat/helper_tasks.R @@ -41,7 +41,7 @@ nano_mnist = function(id = "nano_mnist") { .length = function() dim(self$images)[1L] )(data$image) - data_descriptor = DataDescriptor(dataset = ds, list(image = c(NA, 1, 28, 28))) + data_descriptor = DataDescriptor$new(dataset = ds, list(image = c(NA, 1, 28, 28))) dt = data.table( image = lazy_tensor(data_descriptor), diff --git a/tests/testthat/test_DataDescriptor.R b/tests/testthat/test_DataDescriptor.R index a27eb6ea..74298d38 100644 --- a/tests/testthat/test_DataDescriptor.R +++ b/tests/testthat/test_DataDescriptor.R @@ -11,26 +11,26 @@ test_that("DataDescriptor works", { } )() - dd = DataDescriptor(ds, dataset_shapes = list(x = c(NA, 5, 3))) + dd = DataDescriptor$new(ds, dataset_shapes = list(x = c(NA, 5, 3))) expect_class(dd, "DataDescriptor") - expect_equal(dd$.pointer_shape, c(NA, 5, 3)) + expect_equal(dd$pointer_shape, c(NA, 5, 3)) expect_class(dd$graph$pipeops[[1L]], "PipeOpNOP") expect_true(length(dd$graph$pipeops) == 1L) - expect_equal(dd$.pointer, c(dd$graph$output$op.id, dd$graph$output$channel.name)) - expect_string(dd$.dataset_hash) - expect_string(dd$.hash) - expect_false(dd$.dataset_hash == dd$.hash) + expect_equal(dd$pointer, c(dd$graph$output$op.id, dd$graph$output$channel.name)) + expect_string(dd$dataset_hash) + expect_string(dd$hash) + expect_false(dd$dataset_hash == dd$hash) - dd1 = DataDescriptor(ds, dataset_shapes = list(x = c(NA, 5, 3))) + dd1 = DataDescriptor$new(ds, dataset_shapes = list(x = c(NA, 5, 3))) expect_equal(dd$dataset_shapes, dd1$dataset_shapes) # dataset shapes must be provided - expect_error(DataDescriptor(ds), "missing") + expect_error(DataDescriptor$new(ds), "missing") # batch must always be NA - expect_error(DataDescriptor(ds, dataset_shapes = c(10, 5, 3))) + expect_error(DataDescriptor$new(ds, dataset_shapes = c(10, 5, 3))) graph = as_graph(po("nop", id = "nop")) - expect_error(DataDescriptor(ds, dataset_shapes = list(x = c(NA, 5, 4)), "When passing a graph")) + expect_error(DataDescriptor$new(ds, dataset_shapes = list(x = c(NA, 5, 4)), "When passing a graph")) }) diff --git a/tests/testthat/test_ModelDescriptor.R b/tests/testthat/test_ModelDescriptor.R index cb81e1ec..5be3b036 100644 --- a/tests/testthat/test_ModelDescriptor.R +++ b/tests/testthat/test_ModelDescriptor.R @@ -23,8 +23,8 @@ test_that("ModelDescriptor basic checks", { loss = loss, optimizer = optimizer, callbacks = list(cb), - .pointer = pointer, - .pointer_shape = pointer_shape + pointer = pointer, + pointer_shape = pointer_shape ) expect_class(md, "ModelDescriptor") @@ -32,8 +32,8 @@ test_that("ModelDescriptor basic checks", { expect_identical(md$task, task) expect_identical(md$ingress, ingresslist) expect_identical(md$callbacks, list(checkpoint = cb)) - expect_identical(md$.pointer, pointer) - expect_equal(md$.pointer_shape, pointer_shape) + expect_identical(md$pointer, pointer) + expect_equal(md$pointer_shape, pointer_shape) repr = capture.output(md) expected = c( @@ -43,7 +43,7 @@ test_that("ModelDescriptor basic checks", { "* Callbacks: Checkpoint", "* Optimizer: Adaptive Moment Estimation", "* Loss: Cross Entropy", - "* .pointer: nn_linear.output [(NA,3)]" + "* pointer: nn_linear.output [(NA,3)]" ) expect_equal(expected, repr) diff --git a/tests/testthat/test_PipeOpTaskPreprocTorch.R b/tests/testthat/test_PipeOpTaskPreprocTorch.R index 0b39731e..db5d8a88 100644 --- a/tests/testthat/test_PipeOpTaskPreprocTorch.R +++ b/tests/testthat/test_PipeOpTaskPreprocTorch.R @@ -225,8 +225,14 @@ test_that("pipeop_preproc_torch", { expect_equal(size, list(c(NA, 10, 10))) }) +test_that("can pass variable to fn", { + fn = function(x) x + po_test = pipeop_preproc_torch("test", fn = fn, shapes_out = "infer") + expect_pipeop(po_test) +}) + test_that("predict shapes are added during training", { - po_test = pipeop_preproc_torch("test", function(x) torch_cat(list(x, x * 2), dim = 2), shapes_out = "infer") + fn = po_test = pipeop_preproc_torch("test", fn = function(x) torch_cat(list(x, x * 2), dim = 2), shapes_out = "infer") po_test$param_set$set_values( stages = "train" diff --git a/tests/testthat/test_PipeOpTorch.R b/tests/testthat/test_PipeOpTorch.R index 0c52fbe7..417c00e1 100644 --- a/tests/testthat/test_PipeOpTorch.R +++ b/tests/testthat/test_PipeOpTorch.R @@ -36,13 +36,13 @@ test_that("single input and output", { mdout = obj$train(list(md))[[1L]] expect_identical(address(md$graph), address(mdout$graph)) - expect_true(!identical(md$.pointer, mdout$.pointer)) - expect_true(!identical(md$.pointer_shape, mdout$.pointer_shape)) + expect_true(!identical(md$pointer, mdout$pointer)) + expect_true(!identical(md$pointer_shape, mdout$pointer_shape)) expect_equal(address(md$loss), address(mdout$loss)) expect_equal(address(md$optimizer), address(mdout$optimizer)) expect_equal(address(md$callbacks[[1L]]), address(mdout$callbacks[[1L]])) - expect_equal(mdout$.pointer, c("nn_linear", "output")) - expect_equal(mdout$.pointer_shape, c(NA, 10)) + expect_equal(mdout$pointer, c("nn_linear", "output")) + expect_equal(mdout$pointer_shape, c(NA, 10)) expect_true(obj$is_trained) expect_true("nn_linear" %in% names(mdout$graph$pipeops)) expect_class(mdout$graph$pipeops$nn_linear, "PipeOpModule") @@ -77,8 +77,8 @@ test_that("train handles multiple input channels correctly", { mdsout = obj$train(mds) expect_true(obj$is_trained) expect_equal(address(mdsout[[1L]]$graph), address(mdsout[[1L]]$graph)) - expect_equal(mdsout[[1L]]$.pointer, c("nn_merge_sum", "output")) - expect_equal(mdsout[[1L]]$.pointer_shape, c(NA, 2)) + expect_equal(mdsout[[1L]]$pointer, c("nn_merge_sum", "output")) + expect_equal(mdsout[[1L]]$pointer_shape, c(NA, 2)) expect_equal( data.table( @@ -105,10 +105,10 @@ test_that("train handles multiple input channels correctly", { mdout2 = mdouts[["output2"]] expect_equal(address(mdout1$graph), address(mdout2$graph)) - expect_equal(mdout1$.pointer, c("nn_debug", "output1")) - expect_equal(mdout2$.pointer, c("nn_debug", "output2")) - expect_equal(mdout1$.pointer_shape, c(NA, 2)) - expect_equal(mdout2$.pointer_shape, c(NA, 3)) + expect_equal(mdout1$pointer, c("nn_debug", "output1")) + expect_equal(mdout2$pointer, c("nn_debug", "output2")) + expect_equal(mdout1$pointer_shape, c(NA, 2)) + expect_equal(mdout2$pointer_shape, c(NA, 3)) }) test_that("shapes_out", { @@ -134,10 +134,10 @@ test_that("PipeOpTorch errs when there are unexpected NAs in the shape", { task = tsk("iris") md = graph$train(task)[[1L]] - md$.pointer_shape = c(4, NA) + md$pointer_shape = c(4, NA) expect_error(po("nn_relu")$train(list(md)), regexp = "Invalid shape") - md$.pointer_shape = c(NA, NA, 4) + md$pointer_shape = c(NA, NA, 4) expect_error(po("nn_relu")$train(list(md)), regexp = "Invalid shape") }) diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index a79d058f..f72d4287 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -14,9 +14,9 @@ test_that("Unknown shapes work", { } )() - dd = DataDescriptor(ds, dataset_shapes = list(x = NULL)) + dd = DataDescriptor$new(ds, dataset_shapes = list(x = NULL)) expect_class(dd, "DataDescriptor") - expect_equal(dd$.pointer_shape, NULL) + expect_equal(dd$pointer_shape, NULL) expect_equal(dd$dataset_shapes, list(x = NULL)) lt = as_lazy_tensor(dd) @@ -24,12 +24,12 @@ test_that("Unknown shapes work", { materialize(lt) ds = random_dataset(10, 3) - expect_error(DataDescriptor(ds, list(x = NULL))) + expect_error(DataDescriptor$new(ds, list(x = NULL))) }) test_that("lazy_tensor works", { - dd1 = DataDescriptor(random_dataset(5, 4), list(x = c(NA, 5, 4))) - dd2 = DataDescriptor(random_dataset(5, 4), list(x = c(NA, 5, 4))) + dd1 = DataDescriptor$new(random_dataset(5, 4), list(x = c(NA, 5, 4))) + dd2 = DataDescriptor$new(random_dataset(5, 4), list(x = c(NA, 5, 4))) lt = lazy_tensor() expect_class(lt, "lazy_tensor") @@ -80,15 +80,15 @@ test_that("transform_lazy_tensor works", { # pipeop was not cloned expect_true(identical(dd1$graph$pipeops$dataset_x, dd$graph$pipeops$dataset_x)) - # .pointer was set - expect_equal(dd1$.pointer, c("mod", "output")) + # pointer was set + expect_equal(dd1$pointer, c("mod", "output")) - # .pointer_shape was set - expect_equal(dd1$.pointer_shape, c(NA, 10)) + # pointer_shape was set + expect_equal(dd1$pointer_shape, c(NA, 10)) # hash was updated - expect_false(dd$.hash == dd1$.hash) - expect_true(dd$.dataset_hash == dd1$.dataset_hash) + expect_false(dd$hash == dd1$hash) + expect_true(dd$dataset_hash == dd1$dataset_hash) # materialization gives correct result lt1_mat = materialize(lt1, rbind = TRUE) diff --git a/tests/testthat/test_materialize.R b/tests/testthat/test_materialize.R index ed65948e..2b3e9881 100644 --- a/tests/testthat/test_materialize.R +++ b/tests/testthat/test_materialize.R @@ -138,19 +138,22 @@ test_that("materialize_internal: caching of datasets works", { x1 = as_lazy_tensor(ds, list(x = c(NA, 3))) x2 = as_lazy_tensor(ds, list(x = c(NA, 3))) + # hashes of environments change after a function was called (?) # https://github.com/mlr-org/mlr3torch/issues/156 expect_equal( - dd(x1)$.dataset_hash, - dd(x2)$.dataset_hash + dd(x1)$dataset_hash, + dd(x2)$dataset_hash ) - dd1 = DataDescriptor(ds, list(x = c(NA, 3))) - dd2 = DataDescriptor(ds, list(x = c(NA, 3))) + dd1 = DataDescriptor$new(ds, list(x = c(NA, 3))) + dd2 = DataDescriptor$new(ds, list(x = c(NA, 3))) - dd1$.dataset_hash - dd2$.dataset_hash + dd1$dataset_hash + dd2$dataset_hash + # need to do this, because DataDescritor creation retrieves an example batch to verify the shapes. + ds$count = 0 d = data.table(x1 = x1, x2 = x2) materialize(d, rbind = TRUE, cache = new.env()) diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index 8ecdaa6a..0225e9ad 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -270,27 +270,29 @@ test_that("caching of graph works", { print(x) x + 1 }, env) - po_test = pipeop_preproc_torch("test", fn = fn , shapes_out = "unchanged") - - taskin = tsk("lazy_iris") - - graph = po_test %>>% - list( - po("trafo_nop_1") %>>% po("renamecolumns", renaming = c(x = "z")), - po("trafo_nop_2")) %>>% - po("featureunion") - - task = graph$train(taskin)[[1L]] - - ingress_tokens = list( - z = TorchIngressToken("z", batchgetter_lazy_tensor, c(NA, 4)), - x = TorchIngressToken("x", batchgetter_lazy_tensor, c(NA, 4)) - ) - - ds = task_dataset(task, ingress_tokens, device = "cpu") - ds - - ds$.getbatch(1) - env$counter - expect_equal(env$counter, 1L) + po_test = pipeop_preproc_torch("test", fn = fn, shapes_out = "unchanged") + # + # expect_true(is.function(po_test$fn)) + # + # taskin = tsk("lazy_iris") + # + # graph = po_test %>>% + # list( + # po("trafo_nop_1") %>>% po("renamecolumns", renaming = c(x = "z")), + # po("trafo_nop_2")) %>>% + # po("featureunion") + # + # task = graph$train(taskin)[[1L]] + # + # ingress_tokens = list( + # z = TorchIngressToken("z", batchgetter_lazy_tensor, c(NA, 4)), + # x = TorchIngressToken("x", batchgetter_lazy_tensor, c(NA, 4)) + # ) + # + # ds = task_dataset(task, ingress_tokens, device = "cpu") + # ds + # + # ds$.getbatch(1) + # print(env) + # expect_equal(env$counter, 1) }) From cbc234eeabb224e12662be4f5371552edc3d5890 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 17 Jan 2024 19:18:48 +0100 Subject: [PATCH 19/90] some fixes --- DESCRIPTION | 3 +- R/DataDescriptor.R | 6 ++-- R/PipeOpModule.R | 2 +- R/PipeOpTaskPreprocTorch.R | 21 ++++++++---- R/PipeOpTorchIngress.R | 5 +-- R/TaskClassif_lazy_iris.R | 2 +- R/lazy_tensor.R | 6 ++-- R/materialize.R | 12 ++++--- R/merge_graphs.R | 1 - man/DataDescriptor.Rd | 4 +-- man/materialize.Rd | 10 ++++-- man/merge_graphs.Rd | 11 ------ man/mlr_pipeops_module.Rd | 2 +- man/mlr_pipeops_preproc_torch.Rd | 2 +- man/mlr_pipeops_torch_ingress_ltnsr.Rd | 5 +-- man/mlr_tasks_lazy_iris.Rd | 2 +- man/pipeop_preproc_torch.Rd | 6 ++++ man/pipeop_preproc_torch_class.Rd | 14 ++++++-- tests/testthat/test_preprocess.R | 3 +- tests/testthat/test_task_dataset.R | 47 +++++++++++++------------- 20 files changed, 92 insertions(+), 72 deletions(-) delete mode 100644 man/merge_graphs.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 343c864a..466d2841 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -49,6 +49,7 @@ Imports: paradox (>= 0.11.0), R6, rlang, + torchvision, vctrs, withr Suggests: @@ -61,9 +62,7 @@ Suggests: magick, progress, rmarkdown, - vctrs, viridis, - torchvision, testthat (>= 3.0.0), zip Remotes: diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index b5b0c00a..ceb300ce 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -3,7 +3,7 @@ #' @description #' A data descriptor is a rather internal data structure used in the [`lazy_tensor`] data type. #' In essence it is an annotated [`torch::dataset`] and a preprocessing graph (consisting mosty of [`PipeOpModule`] -#' operators). The additional meta data (e.g. pointer, shapes) allows to preprocess [`lazy_tensors`] in an +#' operators). The additional meta data (e.g. pointer, shapes) allows to preprocess [`lazy_tensor`]s in an #' [`mlr3pipelines::Graph`] just like any (non-lazy) data types. #' The preprocessing is applied when [`materialize()`] is called on the [`lazy_tensor`]. #' @@ -44,7 +44,7 @@ #' # Create a dataset #' dsg = dataset( #' initialize = function() self$x = torch_randn(10, 3, 3), -#' .getitem = function(i) self$x[i, ], +#' .getitem = function(i) list(x = self$x[i, ]), #' .length = function() nrow(self$x) #' ) #' ds = dsg() @@ -141,7 +141,7 @@ DataDescriptor = R6Class("DataDescriptor", catn(sprintf("* dataset_shapes: %s", shape_to_str(self$dataset_shapes))) catn(sprintf("* input_map: (%s) -> Graph", paste0(self$input_map, collapse = ", "))) catn(sprintf("* pointer: %s", paste0(self$pointer, collapse = "."))) - catn(str_indent("* .shape(train):", + catn(str_indent("* shape(train):", if (is.null(self$pointer_shape)) "" else shape_to_str(list(self$pointer_shape)))) catn(str_indent("* shape(predict):", if (is.null(self$pointer_shape_predict)) "" else shape_to_str(list(self$pointer_shape_predict)))) diff --git a/R/PipeOpModule.R b/R/PipeOpModule.R index 7e0403be..a2670b0a 100644 --- a/R/PipeOpModule.R +++ b/R/PipeOpModule.R @@ -75,7 +75,7 @@ #' formalArgs(linear_module$module) #' linear_module$input$name #' -#' Constructing a PipeOpModule using a simple function +#' # Constructing a PipeOpModule using a simple function #' po_add1 = po("module", #' id = "add_one", #' module = function(x) x + 1 diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 1e7ca0c5..8775dd35 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -34,7 +34,7 @@ #' The packages the preprocessing function depends on. #' @param param_set ([`ParamSet`])\cr #' In case the function `fn` takes additional parameter besides a [`torch_tensor`] they can be -#' specfied as parameters. None of the parameters can have the [`"predict"`] tag. +#' specfied as parameters. None of the parameters can have the `"predict"` tag. #' All tags should be set to `"train"`. #' @param stages_init (`logical(1)`)\cr #' Initial value for the `stages` parameter. @@ -301,7 +301,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", if (length(param_vals)) { if (private$.rowwise) { trafo = crate(function(x) { - torch_cat(map(seq_len(nrow(x)), function(i) invoke(trafo, x[i, ..], .args = param_vals)$unsqueeze(1L)), dim = 1L) + torch_cat(lapply(seq_len(nrow(x)), function(i) mlr3misc::invoke(trafo, x[i, ..], .args = param_vals)$unsqueeze(1L)), dim = 1L) }, param_vals, trafo, .parent = environment(trafo)) } else { crate(function(x) { @@ -312,7 +312,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", if (private$.rowwise) { crate(function(x) { torch_cat(map(seq_len(nrow(x)), function(i) trafo(x[i, ..])$unsqueeze(1L)), dim = 1L) - }, trafo) + }, trafo, .parent = topenv()) } else { trafo } @@ -433,15 +433,21 @@ create_ps = function(fn) { #' All parameters but the first and `...` of `fn` are set as untyped parameters with tags 'train' and those that #' have nod default value are tagged as 'required' as well. #' Default values are not annotated. +#' @param parent_env (`environment`)\cr +#' The parent environment for the R6 class. +#' @param rowwise (`logical(1)`)\cr +#' Whether the preprocessing is applied row-wise. +#' @param init_params (name `list()`)\cr +#' List containing initial parameter values. #' @template param_packages #' @export #' @returns An [`R6Class`][R6::R6Class] instance inheriting from [`PipeOpTaskPreprocTorch`] #' @examples #' po_example = pipeop_preproc_torch("preproc_example", function(x, a) x + a) #' po_example -#' po_example$param_setents cannot be passed as variables but need to be passed as expressions. +#' po_example$param_set pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, packages = character(0), - init_params = list(), rowwise = FALSE, parent_env = parent.frame(), leanify = NULL) { + init_params = list(), rowwise = FALSE, parent_env = parent.frame()) { assert( check_function(shapes_out, args = c("shapes_in", "param_vals", "task"), null.ok = TRUE), check_choice(shapes_out, c("infer", "unchanged")) @@ -486,7 +492,7 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack param_set = param_set %??% create_ps(fn) stages_init = if (startsWith(id, "augment_")) "train" else "both" - init_fun = crate(function(id = idname, param_vals = list()) { # nolint + init_fun = crate(function(id = id, param_vals = list()) { # nolint info = private$.__construction_info param_set = info$param_set$clone(deep = TRUE) param_set$values = info$init_params # nolint @@ -501,7 +507,7 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack ) # no need to keep the data around after initialiation private$.__construction_info = NULL - }, param_set, stages_init, rowwise, packages, init_params) + }) formals(init_fun)$id = id @@ -540,6 +546,7 @@ register_preproc = function(id, fn, param_set = NULL, shapes_out = NULL, package packages = packages, rowwise = rowwise, parent_env = parent.frame()) assign(Class$classname, Class, parent.frame()) register_po(id, Class) + NULL } register_po("preproc_torch", PipeOpTaskPreprocTorch, metainf = list(fn = identity, rowwise = FALSE)) diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index bf0838c8..8d0caf5b 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -305,8 +305,9 @@ register_po("torch_ingress_categ", PipeOpTorchIngressCategorical) #' po_resize = po("trafo_resize", size = c(6, 6)) #' task_unknown_resize = po_resize$train(list(task_unknown))[[1L]] #' -#' # printing the transformed column still hows unknown shapes, because the preprocessing pipeop cannot infer -#' # the shapes, however we know that the shape is now (3, 10, 10) for all rows +#' # printing the transformed column still shows unknown shapes, +#' # because the preprocessing pipeop cannot infer them, +#' # however we know that the shape is now (3, 10, 10) for all rows #' task_unknown_resize$data(1:2, "x") #' po_ingress$param_set$set_values(shape = c(NA, 3, 6, 6)) #' diff --git a/R/TaskClassif_lazy_iris.R b/R/TaskClassif_lazy_iris.R index c271180c..2e7ca8c7 100644 --- a/R/TaskClassif_lazy_iris.R +++ b/R/TaskClassif_lazy_iris.R @@ -7,7 +7,7 @@ #' #' @description #' A classification task for the popular [datasets::iris] data set. -#' Just like the the [iris task from mlr3](mlr3::mlr_tasks_iris), but the features are represented as one lazy tensor column. +#' Just like the iris task, but the features are represented as one lazy tensor column. #' #' @section Construction: #' ``` diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index fc56cfb5..88605666 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -70,7 +70,7 @@ as_lazy_tensor = function(x, ...) { } #' @export -as_lazy_tensor.DataDescriptor = function(x, ids = NULL) { # nolint +as_lazy_tensor.DataDescriptor = function(x, ids = NULL, ...) { # nolint lazy_tensor(x, ids = ids) } @@ -81,12 +81,12 @@ as_lazy_tensor.dataset = function(x, dataset_shapes, ids = NULL, ...) { # nolint } #' @export -as_lazy_tensor.numeric = function(x) { # nolint +as_lazy_tensor.numeric = function(x, ...) { # nolint as_lazy_tensor(torch_tensor(x)) } #' @export -as_lazy_tensor.torch_tensor = function(x) { # nolint +as_lazy_tensor.torch_tensor = function(x, ...) { # nolint if (length(dim(x)) == 1L) { x = x$unsqueeze(2) } diff --git a/R/materialize.R b/R/materialize.R index fc7052d3..1ff979ce 100644 --- a/R/materialize.R +++ b/R/materialize.R @@ -2,7 +2,7 @@ #' @description #' This will materialize a [`lazy_tensor()`] or a `data.frame()` / `list()` containing -- among other things -- #' [`lazy_tensor()`] columns. -#' I.e. the data described in the underlying [`DataDescriptors`] is loaded for the indices in the [`lazy_tensor()`], +#' I.e. the data described in the underlying [`DataDescriptor`]s is loaded for the indices in the [`lazy_tensor()`], #' is preprocessed and then put unto the specified device. #' Because not all elements in a lazy tensor must have the same shape, a list of tensors is returned by default. #' If all elements have the same shape, these tensors can also be rbinded into a single tensor (parameter `rbind`). @@ -28,6 +28,10 @@ #' Whether to rbind the lazy tensor columns (`TRUE`) or return them as a list of tensors (`FALSE`). #' In the second case, the batch dimension is present for all individual tensors. #' @return (`list()` of [`lazy_tensor`]s or a [`lazy_tensor`]) +#' @param device (`character(1)`)\cr +#' The torch device. +#' @param ... (any)\cr +#' Additional arguments. #' @export #' @examples #' lt1 = as_lazy_tensor(torch_randn(10, 3)) @@ -48,7 +52,7 @@ materialize = function(x, device = "cpu", rbind = FALSE, ...) { #' Optional cache for (intermediate) materialization results. #' Per default, caching will be enabled when the same dataset / graph is used for more than one lazy tensor column. #' @export -materialize.list = function(x, device = "cpu", rbind = FALSE, cache = "auto") { # nolint +materialize.list = function(x, device = "cpu", rbind = FALSE, cache = "auto", ...) { # nolint x_lt = x[map_lgl(x, is_lazy_tensor)] assert(check_choice(cache, "auto"), check_environment(cache, null.ok = TRUE)) @@ -73,13 +77,13 @@ materialize.list = function(x, device = "cpu", rbind = FALSE, cache = "auto") { #' @method materialize data.frame #' @export -materialize.data.frame = function(x, device = "cpu", rbind = FALSE, cache = "auto") { # nolint +materialize.data.frame = function(x, device = "cpu", rbind = FALSE, cache = "auto", ...) { # nolint materialize(as.list(x), device = device, rbind = rbind, cache = cache) } #' @export -materialize.lazy_tensor = function(x, device = "cpu", rbind = FALSE) { # nolint +materialize.lazy_tensor = function(x, device = "cpu", rbind = FALSE, ...) { # nolint materialize_internal(x = x, device = device, cache = NULL, rbind = rbind) } diff --git a/R/merge_graphs.R b/R/merge_graphs.R index d684dccf..8144ff0d 100644 --- a/R/merge_graphs.R +++ b/R/merge_graphs.R @@ -1,4 +1,3 @@ -#' note that this mo merge_graphs = function(g1, g2) { graph = g1$clone(deep = FALSE) diff --git a/man/DataDescriptor.Rd b/man/DataDescriptor.Rd index 2e8f1342..dbcd0f06 100644 --- a/man/DataDescriptor.Rd +++ b/man/DataDescriptor.Rd @@ -6,7 +6,7 @@ \description{ A data descriptor is a rather internal data structure used in the \code{\link{lazy_tensor}} data type. In essence it is an annotated \code{\link[torch:dataset]{torch::dataset}} and a preprocessing graph (consisting mosty of \code{\link{PipeOpModule}} -operators). The additional meta data (e.g. pointer, shapes) allows to preprocess \code{\link{lazy_tensors}} in an +operators). The additional meta data (e.g. pointer, shapes) allows to preprocess \code{\link{lazy_tensor}}s in an \code{\link[mlr3pipelines:Graph]{mlr3pipelines::Graph}} just like any (non-lazy) data types. The preprocessing is applied when \code{\link[=materialize]{materialize()}} is called on the \code{\link{lazy_tensor}}. } @@ -19,7 +19,7 @@ If each row contained a DataDescriptor as an S3 class, this would copy the objec # Create a dataset dsg = dataset( initialize = function() self$x = torch_randn(10, 3, 3), - .getitem = function(i) self$x[i, ], + .getitem = function(i) list(x = self$x[i, ]), .length = function() nrow(self$x) ) ds = dsg() diff --git a/man/materialize.Rd b/man/materialize.Rd index 37716a52..8ae1b52e 100644 --- a/man/materialize.Rd +++ b/man/materialize.Rd @@ -7,17 +7,23 @@ \usage{ materialize(x, device = "cpu", rbind = FALSE, ...) -\method{materialize}{list}(x, device = "cpu", rbind = FALSE, cache = "auto") +\method{materialize}{list}(x, device = "cpu", rbind = FALSE, cache = "auto", ...) } \arguments{ \item{x}{(any)\cr The object to materialize. Either a \code{\link{lazy_tensor}} or a \code{list()} / \code{data.frame()} containing \code{\link{lazy_tensor}} columns.} +\item{device}{(\code{character(1)})\cr +The torch device.} + \item{rbind}{(\code{logical(1)})\cr Whether to rbind the lazy tensor columns (\code{TRUE}) or return them as a list of tensors (\code{FALSE}). In the second case, the batch dimension is present for all individual tensors.} +\item{...}{(any)\cr +Additional arguments.} + \item{cache}{(\code{character(1)} or \code{environment()} or \code{NULL})\cr Optional cache for (intermediate) materialization results. Per default, caching will be enabled when the same dataset / graph is used for more than one lazy tensor column.} @@ -28,7 +34,7 @@ Per default, caching will be enabled when the same dataset / graph is used for m \description{ This will materialize a \code{\link[=lazy_tensor]{lazy_tensor()}} or a \code{data.frame()} / \code{list()} containing -- among other things -- \code{\link[=lazy_tensor]{lazy_tensor()}} columns. -I.e. the data described in the underlying \code{\link{DataDescriptors}} is loaded for the indices in the \code{\link[=lazy_tensor]{lazy_tensor()}}, +I.e. the data described in the underlying \code{\link{DataDescriptor}}s is loaded for the indices in the \code{\link[=lazy_tensor]{lazy_tensor()}}, is preprocessed and then put unto the specified device. Because not all elements in a lazy tensor must have the same shape, a list of tensors is returned by default. If all elements have the same shape, these tensors can also be rbinded into a single tensor (parameter \code{rbind}). diff --git a/man/merge_graphs.Rd b/man/merge_graphs.Rd deleted file mode 100644 index 1327b0a5..00000000 --- a/man/merge_graphs.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/merge_graphs.R -\name{merge_graphs} -\alias{merge_graphs} -\title{note that this mo} -\usage{ -merge_graphs(g1, g2) -} -\description{ -note that this mo -} diff --git a/man/mlr_pipeops_module.Rd b/man/mlr_pipeops_module.Rd index 1dac91b6..de3d5e62 100644 --- a/man/mlr_pipeops_module.Rd +++ b/man/mlr_pipeops_module.Rd @@ -84,7 +84,7 @@ linear_module formalArgs(linear_module$module) linear_module$input$name -Constructing a PipeOpModule using a simple function +# Constructing a PipeOpModule using a simple function po_add1 = po("module", id = "add_one", module = function(x) x + 1 diff --git a/man/mlr_pipeops_preproc_torch.Rd b/man/mlr_pipeops_preproc_torch.Rd index f7f04dbd..bcd9c6f5 100644 --- a/man/mlr_pipeops_preproc_torch.Rd +++ b/man/mlr_pipeops_preproc_torch.Rd @@ -228,7 +228,7 @@ Parameter values to be set after construction.} \item{\code{param_set}}{(\code{\link{ParamSet}})\cr In case the function \code{fn} takes additional parameter besides a \code{\link{torch_tensor}} they can be -specfied as parameters. None of the parameters can have the \code{\link{"predict"}} tag. +specfied as parameters. None of the parameters can have the \code{"predict"} tag. All tags should be set to \code{"train"}.} \item{\code{packages}}{(\code{character()})\cr diff --git a/man/mlr_pipeops_torch_ingress_ltnsr.Rd b/man/mlr_pipeops_torch_ingress_ltnsr.Rd index 2ab7da4b..00c53cf5 100644 --- a/man/mlr_pipeops_torch_ingress_ltnsr.Rd +++ b/man/mlr_pipeops_torch_ingress_ltnsr.Rd @@ -59,8 +59,9 @@ task_unknown = as_task_regr(data.table( po_resize = po("trafo_resize", size = c(6, 6)) task_unknown_resize = po_resize$train(list(task_unknown))[[1L]] -# printing the transformed column still hows unknown shapes, because the preprocessing pipeop cannot infer -# the shapes, however we know that the shape is now (3, 10, 10) for all rows +# printing the transformed column still shows unknown shapes, +# because the preprocessing pipeop cannot infer them, +# however we know that the shape is now (3, 10, 10) for all rows task_unknown_resize$data(1:2, "x") po_ingress$param_set$set_values(shape = c(NA, 3, 6, 6)) diff --git a/man/mlr_tasks_lazy_iris.Rd b/man/mlr_tasks_lazy_iris.Rd index 11a5d300..3dd7ee28 100644 --- a/man/mlr_tasks_lazy_iris.Rd +++ b/man/mlr_tasks_lazy_iris.Rd @@ -11,7 +11,7 @@ } \description{ A classification task for the popular \link[datasets:iris]{datasets::iris} data set. -Just like the the \href{mlr3::mlr_tasks_iris}{iris task from mlr3}, but the features are represented as one lazy tensor column. +Just like the iris task, but the features are represented as one lazy tensor column. } \section{Construction}{ diff --git a/man/pipeop_preproc_torch.Rd b/man/pipeop_preproc_torch.Rd index 38848db3..0061261d 100644 --- a/man/pipeop_preproc_torch.Rd +++ b/man/pipeop_preproc_torch.Rd @@ -45,6 +45,12 @@ The parameter values.} \item{packages}{(\code{character()})\cr The R packages this object depends on.} + +\item{rowwise}{(\code{logical(1)})\cr +Whether the preprocessing is applied row-wise.} + +\item{parent_env}{(\code{environment})\cr +The parent environment for the R6 class.} } \description{ Calls \code{\link{pipeop_preproc_torch_class}} and instantiates the instance with the given parameter values. diff --git a/man/pipeop_preproc_torch_class.Rd b/man/pipeop_preproc_torch_class.Rd index 4e67baa2..0074e64f 100644 --- a/man/pipeop_preproc_torch_class.Rd +++ b/man/pipeop_preproc_torch_class.Rd @@ -12,8 +12,7 @@ pipeop_preproc_torch_class( packages = character(0), init_params = list(), rowwise = FALSE, - parent_env = parent.frame(), - leanify = NULL + parent_env = parent.frame() ) } \arguments{ @@ -43,6 +42,15 @@ Default values are not annotated.} \item{packages}{(\code{character()})\cr The R packages this object depends on.} + +\item{init_params}{(name \code{list()})\cr +List containing initial parameter values.} + +\item{rowwise}{(\code{logical(1)})\cr +Whether the preprocessing is applied row-wise.} + +\item{parent_env}{(\code{environment})\cr +The parent environment for the R6 class.} } \value{ An \code{\link[R6:R6Class]{R6Class}} instance inheriting from \code{\link{PipeOpTaskPreprocTorch}} @@ -54,5 +62,5 @@ Start by reading the documentation of \code{\link{PipeOpTaskPreprocTorch}}. \examples{ po_example = pipeop_preproc_torch("preproc_example", function(x, a) x + a) po_example -po_example$param_setents cannot be passed as variables but need to be passed as expressions. +po_example$param_set } diff --git a/tests/testthat/test_preprocess.R b/tests/testthat/test_preprocess.R index 7a05f115..e312aac0 100644 --- a/tests/testthat/test_preprocess.R +++ b/tests/testthat/test_preprocess.R @@ -220,9 +220,10 @@ test_that("augment_center_crop", { }) test_that("augment_random_choice", { + # needs dev version of torchvision autotest_pipeop_torch_preprocess( obj = po("augment_random_choice", transforms = list( - identity, identity + identity, function(x) x + 1 )), shapes_in = list(c(1, 3, 8, 8)) ) diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index 0225e9ad..2e1916e3 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -271,28 +271,27 @@ test_that("caching of graph works", { x + 1 }, env) po_test = pipeop_preproc_torch("test", fn = fn, shapes_out = "unchanged") - # - # expect_true(is.function(po_test$fn)) - # - # taskin = tsk("lazy_iris") - # - # graph = po_test %>>% - # list( - # po("trafo_nop_1") %>>% po("renamecolumns", renaming = c(x = "z")), - # po("trafo_nop_2")) %>>% - # po("featureunion") - # - # task = graph$train(taskin)[[1L]] - # - # ingress_tokens = list( - # z = TorchIngressToken("z", batchgetter_lazy_tensor, c(NA, 4)), - # x = TorchIngressToken("x", batchgetter_lazy_tensor, c(NA, 4)) - # ) - # - # ds = task_dataset(task, ingress_tokens, device = "cpu") - # ds - # - # ds$.getbatch(1) - # print(env) - # expect_equal(env$counter, 1) + + expect_true(is.function(po_test$fn)) + + taskin = tsk("lazy_iris") + + graph = po_test %>>% + list( + po("trafo_nop_1") %>>% po("renamecolumns", renaming = c(x = "z")), + po("trafo_nop_2")) %>>% + po("featureunion") + + task = graph$train(taskin)[[1L]] + + ingress_tokens = list( + z = TorchIngressToken("z", batchgetter_lazy_tensor, c(NA, 4)), + x = TorchIngressToken("x", batchgetter_lazy_tensor, c(NA, 4)) + ) + + ds = task_dataset(task, ingress_tokens, device = "cpu") + + ds$.getbatch(1) + print(env) + expect_equal(env$counter, 1) }) From b79aedcfd1bdfc6b267ce7fe679dbc3b655e3317 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 17 Jan 2024 19:30:27 +0100 Subject: [PATCH 20/90] fix documentation issue --- R/DataDescriptor.R | 22 ++----------------- R/PipeOpTaskPreprocTorch.R | 4 ++-- R/TaskClassif_tiny_imagenet.R | 2 +- R/preprocess.R | 1 + man-roxygen/preprocess_torchvision.R | 1 + man/DataDescriptor.Rd | 22 ++----------------- man/PipeOpPreprocTorchAugmentCenterCrop.Rd | 1 + man/PipeOpPreprocTorchAugmentColorJitter.Rd | 1 + man/PipeOpPreprocTorchAugmentCrop.Rd | 1 + man/PipeOpPreprocTorchAugmentHflip.Rd | 1 + man/PipeOpPreprocTorchAugmentRandomAffine.Rd | 1 + man/PipeOpPreprocTorchAugmentRandomApply.Rd | 1 + man/PipeOpPreprocTorchAugmentRandomChoice.Rd | 1 + man/PipeOpPreprocTorchAugmentRandomCrop.Rd | 1 + ...PreprocTorchAugmentRandomHorizontalFlip.Rd | 1 + man/PipeOpPreprocTorchAugmentRandomOrder.Rd | 1 + ...eOpPreprocTorchAugmentRandomResizedCrop.Rd | 1 + ...OpPreprocTorchAugmentRandomVerticalFlip.Rd | 1 + man/PipeOpPreprocTorchAugmentResizedCrop.Rd | 1 + man/PipeOpPreprocTorchAugmentRotate.Rd | 1 + man/PipeOpPreprocTorchAugmentVflip.Rd | 1 + ...PipeOpPreprocTorchTrafoAdjustBrightness.Rd | 1 + man/PipeOpPreprocTorchTrafoAdjustGamma.Rd | 1 + man/PipeOpPreprocTorchTrafoAdjustHue.Rd | 1 + ...PipeOpPreprocTorchTrafoAdjustSaturation.Rd | 1 + man/PipeOpPreprocTorchTrafoGrayscale.Rd | 1 + man/PipeOpPreprocTorchTrafoNop.Rd | 1 + man/PipeOpPreprocTorchTrafoNormalize.Rd | 1 + man/PipeOpPreprocTorchTrafoPad.Rd | 1 + man/PipeOpPreprocTorchTrafoResize.Rd | 1 + man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd | 1 + man/mlr_pipeops_preproc_torch.Rd | 2 +- 32 files changed, 35 insertions(+), 44 deletions(-) diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index ceb300ce..2aa217d3 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -48,26 +48,8 @@ #' .length = function() nrow(self$x) #' ) #' ds = dsg() -#' -#' # Create the preprocessing graph -#' po_module = po("module", module = function(x) torch_reshape(x, c(-1, 9))) -#' po_module$output -#' graph = as_graph(po_module) -#' -#' # Create the data descriptor -#' -#' dd = DataDescriptor$new( -#' dataset = ds, -#' dataset_shapes = list(x = c(NA, 3, 3)), -#' graph = graph, -#' input_map = "x", -#' pointer = c("module", "output"), -#' pointer_shape = c(NA, 9) -#' ) -#' -#' # with no preprocessing -#' dd_no_preproc = DataDescriptor$new(ds, list(x = c(NA, 3, 3))) -#' dd_no_preproc +#' dd = DataDescriptor$new(ds, list(x = c(NA, 3, 3))) +#' dd DataDescriptor = R6Class("DataDescriptor", public = list( #' @description Creates a new instance of this [R6][R6::R6Class] class. diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 8775dd35..eb02ca17 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -101,7 +101,7 @@ #' po_simple = po("preproc_torch", #' # get rid of environment baggage #' fn = mlr3misc::crate(function(x, a) x + a), -#' param_set = ps(a = p_int(tags = c("train", "required"))) +#' param_set = paradox::ps(a = paradox::p_int(tags = c("train", "required"))) #' ) #' #' po_simple$param_set$set_values( @@ -305,7 +305,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", }, param_vals, trafo, .parent = environment(trafo)) } else { crate(function(x) { - invoke(.f = trafo, x, .args = param_vals) + mlr3misc::invoke(.f = trafo, x, .args = param_vals) }, param_vals, trafo, .parent = environment(trafo)) } } else { diff --git a/R/TaskClassif_tiny_imagenet.R b/R/TaskClassif_tiny_imagenet.R index 4aedef6f..876334f4 100644 --- a/R/TaskClassif_tiny_imagenet.R +++ b/R/TaskClassif_tiny_imagenet.R @@ -88,7 +88,7 @@ load_task_tiny_imagenet = function(id = "tiny_imagenet") { dt$image = as_lazy_tensor(dataset_image(dt$image), dataset_shapes = list(x = c(NA, 3, 64, 64))) dt$..row_id = seq_len(nrow(dt)) DataBackendDataTable$new(data = dt, primary_key = "..row_id") - }) + }, .parent = topenv()) backend = DataBackendLazy$new( constructor = cached_constructor, diff --git a/R/preprocess.R b/R/preprocess.R index 0e3d2d3b..f4debf8b 100644 --- a/R/preprocess.R +++ b/R/preprocess.R @@ -32,6 +32,7 @@ register_preproc("trafo_resize", torchvision::transform_resize, #' @title PipeOpPreprocTorchTrafoNop #' @usage NULL #' @name mlr_pipeops_preproc_torch.trafo_nop +#' @aliases PipeOpPreprocTorchTrafoNop #' @rdname PipeOpPreprocTorchTrafoNop #' @format [`R6Class`] inheriting from [`PipeOpTaskPreprocTorch`]. #' diff --git a/man-roxygen/preprocess_torchvision.R b/man-roxygen/preprocess_torchvision.R index 60047437..d2a7b287 100644 --- a/man-roxygen/preprocess_torchvision.R +++ b/man-roxygen/preprocess_torchvision.R @@ -1,5 +1,6 @@ #' <% pipeop = po(id) %> #' @title <%= class(pipeop)[[1L]] %> +#' @aliases <%= class(pipeop)[[1L]] %> #' @usage NULL #' @name mlr_pipeops_preproc_torch.<%= id %> #' @rdname <%= class(pipeop)[[1L]] %> diff --git a/man/DataDescriptor.Rd b/man/DataDescriptor.Rd index dbcd0f06..35a0ee44 100644 --- a/man/DataDescriptor.Rd +++ b/man/DataDescriptor.Rd @@ -23,26 +23,8 @@ dsg = dataset( .length = function() nrow(self$x) ) ds = dsg() - -# Create the preprocessing graph -po_module = po("module", module = function(x) torch_reshape(x, c(-1, 9))) -po_module$output -graph = as_graph(po_module) - -# Create the data descriptor - -dd = DataDescriptor$new( - dataset = ds, - dataset_shapes = list(x = c(NA, 3, 3)), - graph = graph, - input_map = "x", - pointer = c("module", "output"), - pointer_shape = c(NA, 9) -) - -# with no preprocessing -dd_no_preproc = DataDescriptor$new(ds, list(x = c(NA, 3, 3))) -dd_no_preproc +dd = DataDescriptor$new(ds, list(x = c(NA, 3, 3))) +dd } \seealso{ ModelDescriptor, lazy_tensor diff --git a/man/PipeOpPreprocTorchAugmentCenterCrop.Rd b/man/PipeOpPreprocTorchAugmentCenterCrop.Rd index 2738c4d8..6a0c706e 100644 --- a/man/PipeOpPreprocTorchAugmentCenterCrop.Rd +++ b/man/PipeOpPreprocTorchAugmentCenterCrop.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.augment_center_crop} \alias{mlr_pipeops_preproc_torch.augment_center_crop} +\alias{PipeOpPreprocTorchAugmentCenterCrop} \title{PipeOpPreprocTorchAugmentCenterCrop} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchAugmentColorJitter.Rd b/man/PipeOpPreprocTorchAugmentColorJitter.Rd index 35af00ea..311f55d1 100644 --- a/man/PipeOpPreprocTorchAugmentColorJitter.Rd +++ b/man/PipeOpPreprocTorchAugmentColorJitter.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.augment_color_jitter} \alias{mlr_pipeops_preproc_torch.augment_color_jitter} +\alias{PipeOpPreprocTorchAugmentColorJitter} \title{PipeOpPreprocTorchAugmentColorJitter} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchAugmentCrop.Rd b/man/PipeOpPreprocTorchAugmentCrop.Rd index 8f62d69f..f18c1add 100644 --- a/man/PipeOpPreprocTorchAugmentCrop.Rd +++ b/man/PipeOpPreprocTorchAugmentCrop.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.augment_crop} \alias{mlr_pipeops_preproc_torch.augment_crop} +\alias{PipeOpPreprocTorchAugmentCrop} \title{PipeOpPreprocTorchAugmentCrop} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchAugmentHflip.Rd b/man/PipeOpPreprocTorchAugmentHflip.Rd index 18377dd8..39f23af7 100644 --- a/man/PipeOpPreprocTorchAugmentHflip.Rd +++ b/man/PipeOpPreprocTorchAugmentHflip.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.augment_hflip} \alias{mlr_pipeops_preproc_torch.augment_hflip} +\alias{PipeOpPreprocTorchAugmentHflip} \title{PipeOpPreprocTorchAugmentHflip} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchAugmentRandomAffine.Rd b/man/PipeOpPreprocTorchAugmentRandomAffine.Rd index cf19cd40..bb40cc78 100644 --- a/man/PipeOpPreprocTorchAugmentRandomAffine.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomAffine.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.augment_random_affine} \alias{mlr_pipeops_preproc_torch.augment_random_affine} +\alias{PipeOpPreprocTorchAugmentRandomAffine} \title{PipeOpPreprocTorchAugmentRandomAffine} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchAugmentRandomApply.Rd b/man/PipeOpPreprocTorchAugmentRandomApply.Rd index ec68984b..63ed26fd 100644 --- a/man/PipeOpPreprocTorchAugmentRandomApply.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomApply.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.augment_random_apply} \alias{mlr_pipeops_preproc_torch.augment_random_apply} +\alias{PipeOpPreprocTorchAugmentRandomApply} \title{PipeOpPreprocTorchAugmentRandomApply} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchAugmentRandomChoice.Rd b/man/PipeOpPreprocTorchAugmentRandomChoice.Rd index 49775f5b..f73d415f 100644 --- a/man/PipeOpPreprocTorchAugmentRandomChoice.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomChoice.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.augment_random_choice} \alias{mlr_pipeops_preproc_torch.augment_random_choice} +\alias{PipeOpPreprocTorchAugmentRandomChoice} \title{PipeOpPreprocTorchAugmentRandomChoice} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchAugmentRandomCrop.Rd b/man/PipeOpPreprocTorchAugmentRandomCrop.Rd index d9de56df..14271714 100644 --- a/man/PipeOpPreprocTorchAugmentRandomCrop.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomCrop.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.augment_random_crop} \alias{mlr_pipeops_preproc_torch.augment_random_crop} +\alias{PipeOpPreprocTorchAugmentRandomCrop} \title{PipeOpPreprocTorchAugmentRandomCrop} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd b/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd index e32a9533..ec59b1ad 100644 --- a/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.augment_random_horizontal_flip} \alias{mlr_pipeops_preproc_torch.augment_random_horizontal_flip} +\alias{PipeOpPreprocTorchAugmentRandomHorizontalFlip} \title{PipeOpPreprocTorchAugmentRandomHorizontalFlip} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchAugmentRandomOrder.Rd b/man/PipeOpPreprocTorchAugmentRandomOrder.Rd index ec083c18..ed629317 100644 --- a/man/PipeOpPreprocTorchAugmentRandomOrder.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomOrder.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.augment_random_order} \alias{mlr_pipeops_preproc_torch.augment_random_order} +\alias{PipeOpPreprocTorchAugmentRandomOrder} \title{PipeOpPreprocTorchAugmentRandomOrder} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd b/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd index a77a68d9..f33f6dc4 100644 --- a/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.augment_random_resized_crop} \alias{mlr_pipeops_preproc_torch.augment_random_resized_crop} +\alias{PipeOpPreprocTorchAugmentRandomResizedCrop} \title{PipeOpPreprocTorchAugmentRandomResizedCrop} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd b/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd index a3889360..1e2b1280 100644 --- a/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.augment_random_vertical_flip} \alias{mlr_pipeops_preproc_torch.augment_random_vertical_flip} +\alias{PipeOpPreprocTorchAugmentRandomVerticalFlip} \title{PipeOpPreprocTorchAugmentRandomVerticalFlip} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchAugmentResizedCrop.Rd b/man/PipeOpPreprocTorchAugmentResizedCrop.Rd index c1ea919e..62787725 100644 --- a/man/PipeOpPreprocTorchAugmentResizedCrop.Rd +++ b/man/PipeOpPreprocTorchAugmentResizedCrop.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.augment_resized_crop} \alias{mlr_pipeops_preproc_torch.augment_resized_crop} +\alias{PipeOpPreprocTorchAugmentResizedCrop} \title{PipeOpPreprocTorchAugmentResizedCrop} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchAugmentRotate.Rd b/man/PipeOpPreprocTorchAugmentRotate.Rd index fdef500c..52163486 100644 --- a/man/PipeOpPreprocTorchAugmentRotate.Rd +++ b/man/PipeOpPreprocTorchAugmentRotate.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.augment_rotate} \alias{mlr_pipeops_preproc_torch.augment_rotate} +\alias{PipeOpPreprocTorchAugmentRotate} \title{PipeOpPreprocTorchAugmentRotate} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchAugmentVflip.Rd b/man/PipeOpPreprocTorchAugmentVflip.Rd index 673566f5..36c15cfe 100644 --- a/man/PipeOpPreprocTorchAugmentVflip.Rd +++ b/man/PipeOpPreprocTorchAugmentVflip.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.augment_vflip} \alias{mlr_pipeops_preproc_torch.augment_vflip} +\alias{PipeOpPreprocTorchAugmentVflip} \title{PipeOpPreprocTorchAugmentVflip} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd b/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd index cfe69c65..36ead02e 100644 --- a/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd +++ b/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.trafo_adjust_brightness} \alias{mlr_pipeops_preproc_torch.trafo_adjust_brightness} +\alias{PipeOpPreprocTorchTrafoAdjustBrightness} \title{PipeOpPreprocTorchTrafoAdjustBrightness} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd b/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd index 35b647f0..96187f4e 100644 --- a/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd +++ b/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.trafo_adjust_gamma} \alias{mlr_pipeops_preproc_torch.trafo_adjust_gamma} +\alias{PipeOpPreprocTorchTrafoAdjustGamma} \title{PipeOpPreprocTorchTrafoAdjustGamma} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchTrafoAdjustHue.Rd b/man/PipeOpPreprocTorchTrafoAdjustHue.Rd index 0e91d9e9..70ee9657 100644 --- a/man/PipeOpPreprocTorchTrafoAdjustHue.Rd +++ b/man/PipeOpPreprocTorchTrafoAdjustHue.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.trafo_adjust_hue} \alias{mlr_pipeops_preproc_torch.trafo_adjust_hue} +\alias{PipeOpPreprocTorchTrafoAdjustHue} \title{PipeOpPreprocTorchTrafoAdjustHue} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd b/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd index afefab53..c3ec9817 100644 --- a/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd +++ b/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.trafo_adjust_saturation} \alias{mlr_pipeops_preproc_torch.trafo_adjust_saturation} +\alias{PipeOpPreprocTorchTrafoAdjustSaturation} \title{PipeOpPreprocTorchTrafoAdjustSaturation} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchTrafoGrayscale.Rd b/man/PipeOpPreprocTorchTrafoGrayscale.Rd index be42f698..b1675491 100644 --- a/man/PipeOpPreprocTorchTrafoGrayscale.Rd +++ b/man/PipeOpPreprocTorchTrafoGrayscale.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.trafo_grayscale} \alias{mlr_pipeops_preproc_torch.trafo_grayscale} +\alias{PipeOpPreprocTorchTrafoGrayscale} \title{PipeOpPreprocTorchTrafoGrayscale} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchTrafoNop.Rd b/man/PipeOpPreprocTorchTrafoNop.Rd index f6a95fb8..1d8eb892 100644 --- a/man/PipeOpPreprocTorchTrafoNop.Rd +++ b/man/PipeOpPreprocTorchTrafoNop.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.trafo_nop} \alias{mlr_pipeops_preproc_torch.trafo_nop} +\alias{PipeOpPreprocTorchTrafoNop} \title{PipeOpPreprocTorchTrafoNop} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchTrafoNormalize.Rd b/man/PipeOpPreprocTorchTrafoNormalize.Rd index 79dafb82..5dd9a9b0 100644 --- a/man/PipeOpPreprocTorchTrafoNormalize.Rd +++ b/man/PipeOpPreprocTorchTrafoNormalize.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.trafo_normalize} \alias{mlr_pipeops_preproc_torch.trafo_normalize} +\alias{PipeOpPreprocTorchTrafoNormalize} \title{PipeOpPreprocTorchTrafoNormalize} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchTrafoPad.Rd b/man/PipeOpPreprocTorchTrafoPad.Rd index 5c740b0a..c22ca878 100644 --- a/man/PipeOpPreprocTorchTrafoPad.Rd +++ b/man/PipeOpPreprocTorchTrafoPad.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.trafo_pad} \alias{mlr_pipeops_preproc_torch.trafo_pad} +\alias{PipeOpPreprocTorchTrafoPad} \title{PipeOpPreprocTorchTrafoPad} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchTrafoResize.Rd b/man/PipeOpPreprocTorchTrafoResize.Rd index f2816bd2..b031940b 100644 --- a/man/PipeOpPreprocTorchTrafoResize.Rd +++ b/man/PipeOpPreprocTorchTrafoResize.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.trafo_resize} \alias{mlr_pipeops_preproc_torch.trafo_resize} +\alias{PipeOpPreprocTorchTrafoResize} \title{PipeOpPreprocTorchTrafoResize} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd b/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd index b2509106..10a89e1a 100644 --- a/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd +++ b/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/preprocess.R \name{mlr_pipeops_preproc_torch.trafo_rgb_to_grayscale} \alias{mlr_pipeops_preproc_torch.trafo_rgb_to_grayscale} +\alias{PipeOpPreprocTorchTrafoRgbToGrayscale} \title{PipeOpPreprocTorchTrafoRgbToGrayscale} \format{ \code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. diff --git a/man/mlr_pipeops_preproc_torch.Rd b/man/mlr_pipeops_preproc_torch.Rd index bcd9c6f5..b8618d1e 100644 --- a/man/mlr_pipeops_preproc_torch.Rd +++ b/man/mlr_pipeops_preproc_torch.Rd @@ -97,7 +97,7 @@ taskin = as_task_regr(d, target = "y") po_simple = po("preproc_torch", # get rid of environment baggage fn = mlr3misc::crate(function(x, a) x + a), - param_set = ps(a = p_int(tags = c("train", "required"))) + param_set = paradox::ps(a = paradox::p_int(tags = c("train", "required"))) ) po_simple$param_set$set_values( From 45f3d3d9236aa6d3d6f37c46ffed70e39e36453e Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 19 Jan 2024 20:40:28 +0100 Subject: [PATCH 21/90] fix some bugs, remove unneeded deps --- DESCRIPTION | 4 +- NAMESPACE | 9 ++- R/CallbackSetHistory.R | 4 +- R/DataDescriptor.R | 10 +++- R/LearnerTorch.R | 4 +- R/PipeOpTaskPreprocTorch.R | 39 +++++-------- R/PipeOpTorchIngress.R | 4 +- R/TaskClassif_mnist.R | 1 + R/TaskClassif_tiny_imagenet.R | 1 + R/cache.R | 11 ++-- R/lazy_tensor.R | 94 +++++++++++++++++++----------- R/materialize.R | 6 +- R/task_dataset.R | 16 ++--- R/zzz.R | 1 - inst/WORDLIST | 1 - man/materialize.Rd | 2 +- man/mlr_pipeops_preproc_torch.Rd | 9 +-- tests/testthat/helper_tasks.R | 4 +- tests/testthat/test_cache.R | 8 +-- tests/testthat/test_lazy_tensor.R | 12 ++-- tests/testthat/test_task_dataset.R | 2 - 21 files changed, 135 insertions(+), 107 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 466d2841..c8131ca0 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -41,14 +41,12 @@ Imports: backports, checkmate (>= 2.2.0), coro, - fs, lgr, mlr3misc (>= 0.13.0), methods, data.table, paradox (>= 0.11.0), R6, - rlang, torchvision, vctrs, withr @@ -106,6 +104,7 @@ Collate: 'PipeOpTorchConvTranspose.R' 'PipeOpTorchDropout.R' 'PipeOpTorchHead.R' + 'shape.R' 'PipeOpTorchIngress.R' 'PipeOpTorchLayerNorm.R' 'PipeOpTorchLinear.R' @@ -134,6 +133,5 @@ Collate: 'preprocess.R' 'rd_info.R' 'reset_last_layer.R' - 'shape.R' 'task_dataset.R' 'with_torch_settings.R' diff --git a/NAMESPACE b/NAMESPACE index 115f2c4e..92cab35d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,6 +1,9 @@ # Generated by roxygen2: do not edit by hand -S3method("$",lazy_tensor) +S3method("[",lazy_tensor) +S3method("[<-",lazy_tensor) +S3method("[[",lazy_tensor) +S3method("[[<-",lazy_tensor) S3method(as.data.table,DictionaryMlr3torchCallbacks) S3method(as.data.table,DictionaryMlr3torchLosses) S3method(as.data.table,DictionaryMlr3torchOptimizers) @@ -21,6 +24,7 @@ S3method(as_torch_loss,nn_loss) S3method(as_torch_optimizer,TorchOptimizer) S3method(as_torch_optimizer,character) S3method(as_torch_optimizer,torch_optimizer_generator) +S3method(c,lazy_tensor) S3method(col_info,DataBackendLazy) S3method(format,lazy_tensor) S3method(materialize,data.frame) @@ -28,6 +32,7 @@ S3method(materialize,lazy_tensor) S3method(materialize,list) S3method(print,ModelDescriptor) S3method(print,TorchIngressToken) +S3method(print,lazy_tensor) S3method(reset_last_layer,AlexNet) S3method(reset_last_layer,resnet) S3method(t_clbk,"NULL") @@ -42,7 +47,6 @@ S3method(t_opt,"NULL") S3method(t_opt,character) S3method(t_opts,"NULL") S3method(t_opts,character) -S3method(vec_ptype_abbr,lazy_tensor) export(CallbackSet) export(CallbackSetCheckpoint) export(CallbackSetHistory) @@ -172,6 +176,5 @@ import(vctrs) importFrom(R6,R6Class) importFrom(R6,is.R6) importFrom(methods,formalArgs) -importFrom(rlang,"!!") importFrom(tools,R_user_dir) importFrom(utils,getFromNamespace) diff --git a/R/CallbackSetHistory.R b/R/CallbackSetHistory.R index 57b82f69..271dd3f7 100644 --- a/R/CallbackSetHistory.R +++ b/R/CallbackSetHistory.R @@ -70,9 +70,9 @@ CallbackSetHistory = R6Class("CallbackSetHistory", stopf("No eligible measures to plot for set '%s'.", set) } - epoch = score = measure = NULL + epoch = score = measure = .data = NULL if (ncol(data) == 2L) { - ggplot2::ggplot(data = data, ggplot2::aes(x = epoch, y = !!rlang::sym(measures))) + + ggplot2::ggplot(data = data, ggplot2::aes(x = epoch, y = .data[[measures]])) + ggplot2::geom_line() + ggplot2::geom_point() + ggplot2::labs( diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index 2aa217d3..0cd7cfba 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -64,7 +64,15 @@ DataDescriptor = R6Class("DataDescriptor", assert_shape(pointer_shape_predict, null_ok = TRUE, unknown_batch = TRUE) # prevent user from e.g. forgetting to wrap the return in a list - example = if (is.null(dataset$.getbatch)) dataset$.getitem(1L) else dataset$.getbatch(1L) + example = if (is.null(dataset$.getbatch)) { + example = dataset$.getitem(1L) + if (!test_list(example)) { + stopf("dataset must return names list") + } + map(example, function(x) x$unsqueeze(1)) + } else { + dataset$.getbatch(1L) + } if (!test_list(example, names = "unique") || !test_permutation(names(example), names(dataset_shapes))) { stopf("Dataset must return a list with named elements that are a permutation of the dataset_shapes names.") iwalk(dataset_shapes, function(dataset_shape, name) { diff --git a/R/LearnerTorch.R b/R/LearnerTorch.R index 0a491b98..250df067 100644 --- a/R/LearnerTorch.R +++ b/R/LearnerTorch.R @@ -310,8 +310,8 @@ LearnerTorch = R6Class("LearnerTorch", first_row = task$head(1) iwalk(first_row, function(x, nm) { if (!is_lazy_tensor(x)) return(NULL) - predict_shape = x$pointer_shape_predict - train_shape = x$pointer_shape + predict_shape = dd(x)$pointer_shape_predict + train_shape = dd(x)$pointer_shape if (is.null(train_shape) || is.null(predict_shape)) { return(NULL) } diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index eb02ca17..bcb08172 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -125,7 +125,8 @@ #' materialize(taskout_predict_aug$data(cols = c("x1", "x2")), rbind = TRUE) #' #' # Creating a more complex preprocessing PipeOp -#'po_poly = pipeop_preproc_torch( +#' PipeOpPreprocTorchPoly = R6::R6Class("PipeOpPreprocTorchPoly", +#' inherit = PipeOpTaskPreprocTorch, #' public = list( #' initialize = function(id = "preproc_poly", param_vals = list()) { #' param_set = paradox::ps( @@ -160,15 +161,15 @@ #' list(c(NA, param_vals$n_degree)) #' } #' ) -#') +#' ) #' -#'po_poly = PipeOpPreprocTorchPoly$new( -#' param_vals = list(n_degree = 3L, affect_columns = selector_name("x3")) -#') +#' po_poly = PipeOpPreprocTorchPoly$new( +#' param_vals = list(n_degree = 3L, affect_columns = selector_name("x3")) +#' ) #' -#'po_poly$shapes_out(list(c(NA, 1L))) +#' po_poly$shapes_out(list(c(NA, 1L)), stage = "train") #' -#'taskout = po_poly$train(list(tasken))[[1L]] +#'taskout = po_poly$train(list(taskin))[[1L]] #'materialize(taskout$data(cols = "x3"), rbind = TRUE) PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", inherit = PipeOpTaskPreproc, @@ -385,29 +386,21 @@ pipeop_preproc_torch = function(id, fn, shapes_out, param_set = NULL, param_vals create_ps = function(fn) { # TODO: could simplify this as we don't need the expression anymore - fmls = rlang::fn_fmls(fn) + missing = alist(x = )$x + fmls = formals(fn) param_names = names(fmls) + # we assume the firs argument is for the tensor param_names = setdiff(param_names[-1L], "...") fmls = fmls[param_names] - is_required = map(fmls, function(x) identical(x, rlang::missing_arg())) + is_required = map_lgl(fmls, function(x) identical(x, alist(x = )$x)) # Create an empty named list to store the arguments args = list() - # Iterate through the elements of v and create expressions - for (pname in param_names) { - arg_name = as.name(pname) - if (is_required[[pname]]) { - arg_value = rlang::expr(p_uty(tags = c("train", "required"))) - } else { - arg_value = rlang::expr(p_uty(tags = "train")) - } - args[[arg_name]] = arg_value - } - - # Create the final language object - result = rlang::expr(ps(!!!args)) + args = set_names(map(param_names, function(pn) { + p_uty(tags = if (is_required[pn]) c("train", "required") else "train") + }), param_names) - eval(result) + invoke(ps, .args = args) } #' @title Create Torch Preprocessing PipeOps diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index 8d0caf5b..4a966184 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -277,7 +277,7 @@ register_po("torch_ingress_categ", PipeOpTorchIngressCategorical) #' @family PipeOps #' @family Graph Network #' @export -#' @include utils.R +#' @include utils.R shape.R #' @examples #' po_ingress = po("torch_ingress_ltnsr") #' task = tsk("lazy_iris") @@ -330,7 +330,7 @@ PipeOpTorchIngressLazyTensor = R6Class("PipeOpTorchIngressLazyTensor", initialize = function(id = "torch_ingress_ltnsr", param_vals = list()) { param_set = ps( shape = p_uty(tags = "train", custom_check = crate( - function(x) check_shape(x, null_ok = FALSE, unknown_batch = TRUE))) + function(x) check_shape(x, null_ok = FALSE, unknown_batch = TRUE), .parent = topenv())) ) super$initialize(id = id, param_vals = param_vals, feature_types = "lazy_tensor", param_set = param_set) } diff --git a/R/TaskClassif_mnist.R b/R/TaskClassif_mnist.R index 15fa11e8..4e3303dc 100644 --- a/R/TaskClassif_mnist.R +++ b/R/TaskClassif_mnist.R @@ -30,6 +30,7 @@ NULL # @param path (`character(1)`)\cr # The cache_dir/datasets/tiny_imagenet folder. constructor_mnist = function(path) { + require_namespaces("torchvision") # path points to {cache_dir, tempfile}/data/mnist d_train = torchvision::mnist_dataset(root = file.path(path), train = TRUE, download = TRUE) # test set is already downloaded with the training set above diff --git a/R/TaskClassif_tiny_imagenet.R b/R/TaskClassif_tiny_imagenet.R index 876334f4..b5f73788 100644 --- a/R/TaskClassif_tiny_imagenet.R +++ b/R/TaskClassif_tiny_imagenet.R @@ -32,6 +32,7 @@ NULL # @param path (`character(1)`)\cr # The cache_dir/datasets/tiny_imagenet folder. constructor_tiny_imagenet = function(path) { + require_namespaces("torchvision") # path points to {cache_dir, tempfile}/data/tiny_imagenet torchvision::tiny_imagenet_dataset(root = file.path(path), download = TRUE) download_folder = file.path(path, "tiny-imagenet-200") diff --git a/R/cache.R b/R/cache.R index fb1678d7..2e6a47b0 100644 --- a/R/cache.R +++ b/R/cache.R @@ -25,7 +25,7 @@ get_cache_dir = function(cache = NULL) { } assert(check_directory_exists(cache), check_path_for_output(cache)) - fs::path_norm(cache) + normalizePath(cache, mustWork = FALSE) } #' Initializes the cache directory. @@ -37,7 +37,8 @@ get_cache_dir = function(cache = NULL) { #' #' @noRd initialize_cache = function(cache_dir) { - if (isFALSE(cache_dir) || (file.exists(cache_dir) && fs::path_real(cache_dir) %in% CACHE$initialized)) { + if (isFALSE(cache_dir) || (file.exists(cache_dir) && normalizePath(cache_dir, mustWork = FALSE) %in% + CACHE$initialized)) { lg$debug("Skipping initialization of cache", cache_dir = cache_dir) return(TRUE) } @@ -70,7 +71,7 @@ initialize_cache = function(cache_dir) { writeLines(jsonlite::toJSON(CACHE$versions, auto_unbox = TRUE), con = cache_file) } - CACHE$initialized = c(CACHE$initialized, fs::path_real(cache_dir)) + CACHE$initialized = c(CACHE$initialized, normalizePath(cache_dir, mustWork = FALSE)) return(TRUE) } @@ -83,7 +84,7 @@ cached = function(constructor, type, name) { do_caching = !isFALSE(cache_dir) # Even when we don't cache, we need to store the data somewhere - path = fs::path_norm(if (do_caching) file.path(cache_dir, type, name) else tempfile()) + path = normalizePath(if (do_caching) file.path(cache_dir, type, name) else tempfile(), mustWork = FALSE) if (do_caching && dir.exists(path)) { # we cache and there is a cache hit @@ -123,6 +124,6 @@ clear_mlr3torch_cache = function() { return(FALSE) } unlink(get_cache_dir(), recursive = TRUE) - CACHE$initialized = setdiff(CACHE$initialized, fs::path_norm(get_cache_dir())) + CACHE$initialized = setdiff(CACHE$initialized, normalizePath(get_cache_dir(), mustWork = FALSE)) return(TRUE) } diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index 88605666..020c830b 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -23,6 +23,7 @@ lazy_tensor = function(data_descriptor = NULL, ids = NULL) { new_lazy_tensor(data_descriptor, ids) } + new_lazy_tensor = function(data_descriptor, ids) { # previously, only the id was included and not the hash # this led to issues with stuff like unlist(), which dropped attribute and suddenly the lazy_tensor column @@ -32,7 +33,53 @@ new_lazy_tensor = function(data_descriptor, ids) { # Note that we just include the hash as an attribute, so c() does not allow to combine lazy tensors whose # data descriptors have different hashes. - vctrs::new_vctr(map(ids, function(id) list(id, data_descriptor)), hash = data_descriptor$hash, class = "lazy_tensor") + structure(map(ids, function(id) list(id, data_descriptor)), class = c("lazy_tensor", "list")) +} + +#' @export +`[.lazy_tensor` = function(x, i) { + structure(unclass(x)[i], class = c("lazy_tensor", "list")) +} + +#' @export +`[[.lazy_tensor` = function(x, i) { + structure(unclass(x)[[i]], class = c("lazy_tensor", "list")) +} + +#' @export +`[<-.lazy_tensor` = function(x, i, value) { + assert_true(is_lazy_tensor(value)) + # no compatibility check + if (length(x) == 0) return(NextMethod()) + assert_true(identical(dd(x)$hash, dd(value)$hash)) + x = unclass(x) + x[i] = value + structure(x, class = c("lazy_tensor", "list")) +} + +#' @export +`[[<-.lazy_tensor` = function(x, i, value) { + assert_true(is_lazy_tensor(value)) + # no compatibility check + if (length(x) == 0) return(NextMethod()) + assert_true(identical(dd(x)$hash), dd(value)$hash) + x = unclass(x) + x[[i]] = value + structure(x, class = c("lazy_tensor", "list")) +} + +#' @export +c.lazy_tensor = function(...) { + dots = list(...) + if (!all(map_lgl(dots, is_lazy_tensor))) { + return(NextMethod()) + } + if (length(unique(map_chr(dots, function(x) dd(x)$hash))) > 1) { + stopf("Can only concatenate lazy tensors with the same data descriptors.") + } + + x = NextMethod() + structure(x, class = c("lazy_tensor", "list")) } #' @export @@ -49,6 +96,16 @@ format.lazy_tensor = function(x, ...) { # nolint }) } +#' @export +print.lazy_tensor = function(x, ...) { + cat(paste0("", "\n", collapse = "")) + if (length(x) == 0) return(invisible(x)) + + out <- stats::setNames(format(x), names(x)) + print(out, quote = FALSE) + invisible(x) +} + dd = function(x) { if (!length(x)) { stopf("Cannot access data descriptor when lazy_tensor has length 0.") @@ -104,11 +161,6 @@ as_lazy_tensor.torch_tensor = function(x, ...) { # nolint as_lazy_tensor(ds, dataset_shapes = list(x = c(NA, dim(x)[-1]))) } -#' @export -vec_ptype_abbr.lazy_tensor <- function(x, ...) { # nolint - "ltnsr" -} - #' @title Check for lazy tensor #' @description #' Checks whether an object is a lazy tensor. @@ -191,33 +243,5 @@ transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { clone_graph = FALSE ) - new_lazy_tensor(data_descriptor, map_int(vec_data(lt), 1)) -} - -#' @export -`$.lazy_tensor` = function(x, name) { - # FIXME: remove this method - #stop("Not supported anymore") - if (!length(x)) { - stop("lazy tensor has length 0.") - } - - dd = x[[1L]][[2L]] - if (name == "data_descriptor") { - return(dd) - } - - assert_choice(name, c( - "dataset", - "graph", - "dataset_shapes", - "input_map", - "pointer", - "pointer_shape", - "dataset_hash", - "hash", - "graph_input", - "pointer_shape_predict" - )) - dd[[name]] + new_lazy_tensor(data_descriptor, map_int(lt, 1)) } diff --git a/R/materialize.R b/R/materialize.R index 1ff979ce..6ce6233a 100644 --- a/R/materialize.R +++ b/R/materialize.R @@ -38,7 +38,7 @@ #' materialize(lt1, rbind = TRUE) #' materialize(lt1, rbind = FALSE) #' lt2 = as_lazy_tensor(torch_randn(10, 4)) -#' d = data.frame(lt1 = lt1, lt2 = lt2) +#' d = data.table::data.table(lt1 = lt1, lt2 = lt2) #' materialize(d, rbind = TRUE) #' materialize(d, rbind = FALSE) materialize = function(x, device = "cpu", rbind = FALSE, ...) { @@ -58,7 +58,7 @@ materialize.list = function(x, device = "cpu", rbind = FALSE, cache = "auto", .. if (identical(cache, "auto")) { data_hashes = map_chr(x_lt, function(x) dd(x)$dataset_hash) - hashes = map_chr(x_lt, function(x) x$hash) + hashes = map_chr(x_lt, function(x) dd(x)$hash) cache = if (uniqueN(data_hashes) > 1L || uniqueN(hashes) > 1L) { new.env() } @@ -121,7 +121,7 @@ materialize_internal = function(x, device = "cpu", cache = NULL, rbind) { stopf("Cannot materialize lazy tensor of length 0.") } do_caching = !is.null(cache) - ids = map_int(vec_data(x), 1) + ids = map_int(x, 1) data_descriptor = dd(x) ds = data_descriptor$dataset diff --git a/R/task_dataset.R b/R/task_dataset.R index 3c798436..5e232dcd 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -72,7 +72,7 @@ task_dataset = dataset( } } - self$cache_lazy_tensors = length(unique(map_chr(data, function(x) x$hash))) > 1L + self$cache_lazy_tensors = length(unique(map_chr(data, function(x) dd(x)$hash))) > 1L }, .getbatch = function(index) { cache = if (self$cache_lazy_tensors) new.env() @@ -110,21 +110,21 @@ merge_lazy_tensor_graphs = function(lts) { # some PipeOs that were previously terminal might not be anymore, # for those we add nops and updaate the pointers for their data descriptors map_dtc(lts, function(lt) { - pointer_name = paste0(lt$pointer, collapse = ".") + pointer_name = paste0(dd(lt)$pointer, collapse = ".") pointer = if (pointer_name %nin% graph$output$name) { po_terminal = po("nop", id = uniqueify(pointer_name, graph$ids())) graph$add_pipeop(po_terminal, clone = FALSE) graph$add_pipeop( - src_id = lt$pointer[1L], + src_id = dd(lt)$pointer[1L], dst_id = po_terminal$id, - src_channel = lt$pointer[2L], + src_channel = dd(lt)$pointer[2L], dst_channel = po_terminal$input$name ) c(po_terminal$id, po_terminal$output$name) } else { - lt$pointer + dd(lt)$pointer } data_descriptor = DataDescriptor$new( @@ -133,11 +133,11 @@ merge_lazy_tensor_graphs = function(lts) { graph = graph, input_map = input_map, pointer = pointer, - pointer_shape = lt$pointer_shape, - pointer_shape_predict = lt$pointer_shape_predict, + pointer_shape = dd(lt)$pointer_shape, + pointer_shape_predict = dd(lt)$pointer_shape_predict, clone_graph = FALSE ) - new_lazy_tensor(data_descriptor, map_int(vec_data(lt), 1L)) + new_lazy_tensor(data_descriptor, map_int(lt, 1L)) }) } diff --git a/R/zzz.R b/R/zzz.R index f66502a0..48029171 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -10,7 +10,6 @@ #' @import mlr3 #' @import vctrs #' @importFrom tools R_user_dir -#' @importFrom rlang !! #' #' @section Options: #' * `mlr3torch.cache`: diff --git a/inst/WORDLIST b/inst/WORDLIST index 16f1f6c9..1f6de236 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -1102,7 +1102,6 @@ rK Rk Rl RL -rlang rM rmsprop rN diff --git a/man/materialize.Rd b/man/materialize.Rd index 8ae1b52e..995196b3 100644 --- a/man/materialize.Rd +++ b/man/materialize.Rd @@ -60,7 +60,7 @@ lt1 = as_lazy_tensor(torch_randn(10, 3)) materialize(lt1, rbind = TRUE) materialize(lt1, rbind = FALSE) lt2 = as_lazy_tensor(torch_randn(10, 4)) -d = data.frame(lt1 = lt1, lt2 = lt2) +d = data.table::data.table(lt1 = lt1, lt2 = lt2) materialize(d, rbind = TRUE) materialize(d, rbind = FALSE) } diff --git a/man/mlr_pipeops_preproc_torch.Rd b/man/mlr_pipeops_preproc_torch.Rd index b8618d1e..9e2942d9 100644 --- a/man/mlr_pipeops_preproc_torch.Rd +++ b/man/mlr_pipeops_preproc_torch.Rd @@ -121,7 +121,8 @@ taskout_predict_aug = po_simple$predict(list(taskin))[[1L]] materialize(taskout_predict_aug$data(cols = c("x1", "x2")), rbind = TRUE) # Creating a more complex preprocessing PipeOp -po_poly = pipeop_preproc_torch( +PipeOpPreprocTorchPoly = R6::R6Class("PipeOpPreprocTorchPoly", + inherit = PipeOpTaskPreprocTorch, public = list( initialize = function(id = "preproc_poly", param_vals = list()) { param_set = paradox::ps( @@ -159,12 +160,12 @@ po_poly = pipeop_preproc_torch( ) po_poly = PipeOpPreprocTorchPoly$new( - param_vals = list(n_degree = 3L, affect_columns = selector_name("x3")) + param_vals = list(n_degree = 3L, affect_columns = selector_name("x3")) ) -po_poly$shapes_out(list(c(NA, 1L))) +po_poly$shapes_out(list(c(NA, 1L)), stage = "train") -taskout = po_poly$train(list(tasken))[[1L]] +taskout = po_poly$train(list(taskin))[[1L]] materialize(taskout$data(cols = "x3"), rbind = TRUE) } \section{Super classes}{ diff --git a/tests/testthat/helper_tasks.R b/tests/testthat/helper_tasks.R index 5f223b34..34cb706d 100644 --- a/tests/testthat/helper_tasks.R +++ b/tests/testthat/helper_tasks.R @@ -2,7 +2,7 @@ nano_dogs_vs_cats = function(id = "nano_dogs_vs_cats") { assert_string(id) path = testthat::test_path("assets", "nano_dogs_vs_cats") image_names = list.files(path) - uris = fs::path_norm(file.path(path, image_names)) + uris = normalizePath(file.path(path, image_names), mustWork = FALSE) ds = dataset_image(uris) @@ -68,7 +68,7 @@ nano_imagenet = function(id = "nano_imagenet") { path = testthat::test_path("assets", "nano_imagenet") image_names = list.files(path) - uris = fs::path_norm(file.path(path, image_names)) + uris = normalizePath(file.path(path, image_names), mustWork = FALSE) images = as_lazy_tensor(dataset_image(uris), list(x = c(NA, 3, 64, 64))) labels = map_chr(image_names, function(name) strsplit(name, split = "_")[[1L]][1L]) diff --git a/tests/testthat/test_cache.R b/tests/testthat/test_cache.R index a6c7be98..bc85ea13 100644 --- a/tests/testthat/test_cache.R +++ b/tests/testthat/test_cache.R @@ -7,7 +7,7 @@ test_that("cache works if mlr3torch.cache is set to false", { dat = data.table(x = rnorm(1)) test_constructor = function(path) { - fwrite(dat, fs::path_norm(file.path(path, "data.csv"))) + fwrite(dat, normalizePath(file.path(path, "data.csv"), mustWork = FALSE)) return(dat) } @@ -49,7 +49,7 @@ test_that("cache works if mlr3torch.cache is set to a directory", { dat2 = cached(function(x) stop(), "datasets", "test_data") expect_equal(dat1$data, dat2$data) # /private/var and /var are symlinked and somehow different paths are returned on macOS - expect_equal(fs::path_real(dat1$path), fs::path_real(dat2$path)) + expect_equal(normalizePath(dat1$path, mustWork = FALSE), normalizePath(dat2$path, mustWork = FALSE)) }) test_that("cache works if mlr3torch.cache is set to TRUE", { @@ -105,7 +105,7 @@ test_that("cache initialization and versioning are correct", { } dat1 = cached(test_constructor, name, "test_data") - cache_dir = fs::path_real(cache_dir) + cache_dir = normalizePath(cache_dir, mustWork = FALSE) # here the version should be 5 cache_version = jsonlite::read_json(file.path(cache_dir, "version.json")) @@ -114,7 +114,7 @@ test_that("cache initialization and versioning are correct", { # the other cache version is left unchanged expect_true(cache_version$datasets == CACHE$versions$datasets) - expect_true(fs::path_real(cache_dir) %in% CACHE$initialized) + expect_true(normalizePath(cache_dir, mustWork = FALSE) %in% CACHE$initialized) # the subfolder is created assert_true(name %in% list.files(cache_dir)) diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index f72d4287..f0361d7a 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -22,6 +22,8 @@ test_that("Unknown shapes work", { lt = as_lazy_tensor(dd) expect_class(lt, "lazy_tensor") materialize(lt) + expect_true(test_class(lt[1:2], "lazy_tensor")) + expect_true(test_class(lt[[1]], "lazy_tensor")) ds = random_dataset(10, 3) expect_error(DataDescriptor$new(ds, list(x = NULL))) @@ -34,17 +36,17 @@ test_that("lazy_tensor works", { lt = lazy_tensor() expect_class(lt, "lazy_tensor") expect_true(length(lt) == 0L) - expect_error(is.null(lt$data_descriptor)) + expect_error(is.null(dd(lt)$data_descriptor)) lt1 = lazy_tensor(dd1) lt2 = lazy_tensor(dd2) - expect_error(c(lt1, lt2), "attributes are incompatible") + expect_error(c(lt1, lt2), "Can only concatenate") expect_error({lt1[1] = lt2[1]}) # nolint lt1_empty = lt1[integer(0)] - expect_error(is.null(lt1_empty$data_descriptor)) + expect_error(is.null(dd(lt1_empty))) expect_class(lt1_empty, "lazy_tensor") expect_error(materialize(lazy_tensor()), "Cannot materialize") @@ -67,13 +69,13 @@ test_that("transform_lazy_tensor works", { lt1 = transform_lazy_tensor(lt, po_module, new_shape) - dd1 = lt1$data_descriptor + dd1 = dd(lt1) expect_equal(dd1$graph$edges, data.table(src_id = "dataset_x", src_channel = "output", dst_id = "mod", dst_channel = "input") ) - dd = lt$data_descriptor + dd = dd(lt) # graph was cloned expect_true(!identical(dd1$graph, dd$graph)) diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index 2e1916e3..0e76d19e 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -266,8 +266,6 @@ test_that("caching of graph works", { env$counter = 0L fn = crate(function(x) { env$counter = env$counter + 1L - match.call() - print(x) x + 1 }, env) po_test = pipeop_preproc_torch("test", fn = fn, shapes_out = "unchanged") From acf6239f929e858776cc1b199561fae568bee822 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 19 Jan 2024 20:42:27 +0100 Subject: [PATCH 22/90] remove vctrs from desc --- DESCRIPTION | 1 - 1 file changed, 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index c8131ca0..4ecb9733 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -48,7 +48,6 @@ Imports: paradox (>= 0.11.0), R6, torchvision, - vctrs, withr Suggests: callr, From 5849806c97b65c28617df955c546a7d4e167ec6c Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 19 Jan 2024 20:44:32 +0100 Subject: [PATCH 23/90] remove vctrs from imports --- NAMESPACE | 1 - R/zzz.R | 1 - 2 files changed, 2 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 92cab35d..b58ba052 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -172,7 +172,6 @@ import(mlr3misc) import(mlr3pipelines) import(paradox) import(torch) -import(vctrs) importFrom(R6,R6Class) importFrom(R6,is.R6) importFrom(methods,formalArgs) diff --git a/R/zzz.R b/R/zzz.R index 48029171..9c408090 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -8,7 +8,6 @@ #' @import torch #' @import mlr3pipelines #' @import mlr3 -#' @import vctrs #' @importFrom tools R_user_dir #' #' @section Options: From da9b40d44a5e7214c237e3d208c20226537bdb9e Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Mon, 22 Jan 2024 17:45:29 +0100 Subject: [PATCH 24/90] rcmdcheck passes --- .github/dependabot.yaml | 6 + DESCRIPTION | 2 +- R/DataDescriptor.R | 3 +- R/PipeOpTaskPreprocTorch.R | 40 +++-- R/PipeOpTorchIngress.R | 2 +- R/TaskClassif_tiny_imagenet.R | 1 + R/lazy_tensor.R | 4 +- R/materialize.R | 90 +++++----- R/nn_graph.R | 16 +- R/preprocess.R | 165 +++++++++++++++--- R/reset_last_layer.R | 20 ++- R/task_dataset.R | 5 +- R/utils.R | 4 + man/DataDescriptor.Rd | 2 +- man/PipeOpPreprocTorchAugmentColorJitter.Rd | 16 +- man/PipeOpPreprocTorchAugmentCrop.Rd | 16 +- man/PipeOpPreprocTorchAugmentRandomAffine.Rd | 19 +- man/PipeOpPreprocTorchAugmentRandomApply.Rd | 12 +- man/PipeOpPreprocTorchAugmentRandomCrop.Rd | 8 +- ...PreprocTorchAugmentRandomHorizontalFlip.Rd | 10 +- ...eOpPreprocTorchAugmentRandomResizedCrop.Rd | 16 +- ...OpPreprocTorchAugmentRandomVerticalFlip.Rd | 10 +- man/PipeOpPreprocTorchAugmentResizedCrop.Rd | 20 +-- man/PipeOpPreprocTorchAugmentRotate.Rd | 18 +- ...PipeOpPreprocTorchTrafoAdjustBrightness.Rd | 10 +- man/PipeOpPreprocTorchTrafoAdjustGamma.Rd | 12 +- man/PipeOpPreprocTorchTrafoAdjustHue.Rd | 10 +- ...PipeOpPreprocTorchTrafoAdjustSaturation.Rd | 10 +- man/PipeOpPreprocTorchTrafoGrayscale.Rd | 10 +- man/PipeOpPreprocTorchTrafoNormalize.Rd | 1 - man/PipeOpPreprocTorchTrafoPad.Rd | 4 +- man/materialize.Rd | 2 +- man/mlr_pipeops_preproc_torch.Rd | 5 +- man/mlr_pipeops_torch_ingress_ltnsr.Rd | 2 +- man/nn_graph.Rd | 13 +- man/pipeop_preproc_torch.Rd | 2 +- man/pipeop_preproc_torch_class.Rd | 2 +- man/reset_layer.Rd | 20 ++- tests/testthat/helper_autotest.R | 2 +- tests/testthat/test_autotests.R | 17 -- tests/testthat/test_lazy_tensor.R | 4 +- tests/testthat/test_materialize.R | 29 +-- 42 files changed, 396 insertions(+), 264 deletions(-) create mode 100644 .github/dependabot.yaml diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 00000000..5ace4600 --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/DESCRIPTION b/DESCRIPTION index 4ecb9733..662e8819 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -47,7 +47,6 @@ Imports: data.table, paradox (>= 0.11.0), R6, - torchvision, withr Suggests: callr, @@ -61,6 +60,7 @@ Suggests: rmarkdown, viridis, testthat (>= 3.0.0), + torchvision, zip Remotes: r-lib/zip, diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index 0cd7cfba..188dd59c 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -22,7 +22,7 @@ #' Character vector that must have the same length as the input of the graph. #' Specifies how the data from the `dataset` is fed into the preprocessing graph. #' @param pointer (`character(2)` | `NULL`)\cr -#' Indicating an element on which a model is. Points to an output channel within `graph`: +#' Points to an output channel within `graph`: #' Element 1 is the `PipeOp`'s id and element 2 is that `PipeOp`'s output channel. #' @param pointer_shape (`integer` | `NULL`)\cr #' Shape of the output indicated by `pointer`. @@ -111,7 +111,6 @@ DataDescriptor = R6Class("DataDescriptor", # compilation dataset_hash = calculate_hash(address(dataset)) - self$dataset = dataset self$graph = graph self$dataset_shapes = dataset_shapes diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index bcb08172..f3ec9d80 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -28,8 +28,9 @@ #' #' @template param_id #' @template param_param_vals -#' @param fn (`function`)\cr +#' @param fn (`function` or `character(2)`)\cr #' The preprocessing function. Should not modify its input in-place. +#' If it is a `character(2)`, the first element should be the namespace and thje second element the name. #' @param packages (`character()`)\cr #' The packages the preprocessing function depends on. #' @param param_set ([`ParamSet`])\cr @@ -178,7 +179,8 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' Creates a new instance of this [`R6`][R6::R6Class] class. initialize = function(fn, id = "preproc_torch", param_vals = list(), param_set = ps(), packages = character(0), stages_init = "both", rowwise = FALSE) { # nolint - private$.fn = assert_function(fn) + assert(check_function(fn), check_character(fn, len = 2L)) + private$.fn = fn private$.rowwise = assert_flag(rowwise) param_set = assert_param_set(param_set$clone(deep = TRUE)) @@ -249,6 +251,9 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' The preprocessing function. fn = function(rhs) { assert_ro_binding(rhs) + if (test_character(private$.fn)) { + private$.fn = getFromNamespace(private$.fn[2L], private$.fn[1L]) + } private$.fn }, #' @field rowwise @@ -296,7 +301,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", param_vals$affect_columns = NULL stages = param_vals$stages param_vals$stages = NULL - trafo = private$.fn + trafo = self$fn fn = if (identical(stages, "both") || stage %in% stages) { if (length(param_vals)) { @@ -355,7 +360,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", .additional_phash_input = function() { list( self$param_set$ids(), self$packages, - formals(private$.fn), body(private$.fn), address(environment(private$.fn)) + formals(self$fn), body(self$fn), address(environment(self$fn)) ) }, .shapes_out = function(shapes_in, param_vals, task) list(NULL), @@ -370,7 +375,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' @param param_vals (`list()`)\cr #' The parameter values. #' @export -pipeop_preproc_torch = function(id, fn, shapes_out, param_set = NULL, param_vals = list(), packages = character(0), +pipeop_preproc_torch = function(id, fn, shapes_out = NULL, param_set = NULL, param_vals = list(), packages = character(0), rowwise = FALSE, parent_env = parent.frame()) { pipeop_preproc_torch_class( id = id, @@ -385,8 +390,6 @@ pipeop_preproc_torch = function(id, fn, shapes_out, param_set = NULL, param_vals create_ps = function(fn) { - # TODO: could simplify this as we don't need the expression anymore - missing = alist(x = )$x fmls = formals(fn) param_names = names(fmls) # we assume the firs argument is for the tensor @@ -436,7 +439,7 @@ create_ps = function(fn) { #' @export #' @returns An [`R6Class`][R6::R6Class] instance inheriting from [`PipeOpTaskPreprocTorch`] #' @examples -#' po_example = pipeop_preproc_torch("preproc_example", function(x, a) x + a) +#' po_example = pipeop_preproc_torch("preproc_example", function(x, a) x + a, ) #' po_example #' po_example$param_set pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, packages = character(0), @@ -445,6 +448,8 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack check_function(shapes_out, args = c("shapes_in", "param_vals", "task"), null.ok = TRUE), check_choice(shapes_out, c("infer", "unchanged")) ) + + # we e.g. want torchvision in suggests, so we cannot already access the function. if (identical(shapes_out, "infer")) { shapes_out = crate(function(shapes_in, param_vals, task) { sin = shapes_in[[1L]] @@ -457,7 +462,7 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack sin = sin[-1L] } tensor_in = invoke(torch_empty, .args = sin, device = torch_device("meta")) - tensor_out = tryCatch(invoke(private$.fn, tensor_in, .args = param_vals), + tensor_out = tryCatch(invoke(self$fn, tensor_in, .args = param_vals), error = function(e) { stopf("Failed to infer output shape, presumably invalid input shape; error message is: %s", e) } @@ -485,9 +490,19 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack param_set = param_set %??% create_ps(fn) stages_init = if (startsWith(id, "augment_")) "train" else "both" + + # the .__construction info construct is used to not having to rely on NSE init_fun = crate(function(id = id, param_vals = list()) { # nolint info = private$.__construction_info - param_set = info$param_set$clone(deep = TRUE) + fn = info$fn + if (is.character(fn)) { + fn = getFromNamespace(fn[2L], fn[1L]) + } + if (is.null(info$param_set)) { + param_set = create_ps(fn) + } else { + param_set = info$param_set$clone(deep = TRUE) + } param_set$values = info$init_params # nolint super$initialize( id = id, @@ -535,6 +550,11 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack } register_preproc = function(id, fn, param_set = NULL, shapes_out = NULL, packages = character(0), rowwise = FALSE) { + fn_call = substitute(fn) + if (identical(as.list(fn_call)[[1]], quote(`::`))) { + fn = as.character(as.list(fn_call)[-1L]) + } + Class = pipeop_preproc_torch_class(id, fn, param_set = param_set, shapes_out = shapes_out, packages = packages, rowwise = rowwise, parent_env = parent.frame()) assign(Class$classname, Class, parent.frame()) diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index 4a966184..401c74e4 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -291,7 +291,7 @@ register_po("torch_ingress_categ", PipeOpTorchIngressCategorical) #' # Now we try a lazy tensor with unknown shape, i.e. the shapes between the rows can differ #' #' ds = dataset( -#' initialize = function() self$x = list(torch_randn(3, 10, 10), torch_randn(10, 8, 8)), +#' initialize = function() self$x = list(torch_randn(3, 10, 10), torch_randn(3, 8, 8)), #' .getitem = function(i) list(x = self$x[[i]]), #' .length = function() 2)() #' diff --git a/R/TaskClassif_tiny_imagenet.R b/R/TaskClassif_tiny_imagenet.R index b5f73788..6fd79326 100644 --- a/R/TaskClassif_tiny_imagenet.R +++ b/R/TaskClassif_tiny_imagenet.R @@ -86,6 +86,7 @@ load_task_tiny_imagenet = function(id = "tiny_imagenet") { withr::with_locale(c(LC_COLLATE = "C"), { dt = cached(constructor_tiny_imagenet, "datasets", "tiny_imagenet")$data }) + dt$image = as_lazy_tensor(dataset_image(dt$image), dataset_shapes = list(x = c(NA, 3, 64, 64))) dt$..row_id = seq_len(nrow(dt)) DataBackendDataTable$new(data = dt, primary_key = "..row_id") diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index 020c830b..d9e4563a 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -43,7 +43,7 @@ new_lazy_tensor = function(data_descriptor, ids) { #' @export `[[.lazy_tensor` = function(x, i) { - structure(unclass(x)[[i]], class = c("lazy_tensor", "list")) + unclass(x)[[i]] } #' @export @@ -74,7 +74,7 @@ c.lazy_tensor = function(...) { if (!all(map_lgl(dots, is_lazy_tensor))) { return(NextMethod()) } - if (length(unique(map_chr(dots, function(x) dd(x)$hash))) > 1) { + if (length(unique(map_chr(dots[lengths(dots) != 0], function(x) dd(x)$hash))) > 1) { stopf("Can only concatenate lazy tensors with the same data descriptors.") } diff --git a/R/materialize.R b/R/materialize.R index 6ce6233a..a703b9b9 100644 --- a/R/materialize.R +++ b/R/materialize.R @@ -26,7 +26,7 @@ #' Either a [`lazy_tensor`] or a `list()` / `data.frame()` containing [`lazy_tensor`] columns. #' @param rbind (`logical(1)`)\cr #' Whether to rbind the lazy tensor columns (`TRUE`) or return them as a list of tensors (`FALSE`). -#' In the second case, the batch dimension is present for all individual tensors. +#' In the second case, there is no batch dimension. #' @return (`list()` of [`lazy_tensor`]s or a [`lazy_tensor`]) #' @param device (`character(1)`)\cr #' The torch device. @@ -87,6 +87,44 @@ materialize.lazy_tensor = function(x, device = "cpu", rbind = FALSE, ...) { # no materialize_internal(x = x, device = device, cache = NULL, rbind = rbind) } +get_input = function(ds, ids, varying_shapes, rbind) { + if (is.null(ds$.getbatch)) { # .getindex is never NULL but a function that errs if it was not defined + x = map(ids, function(id) map(ds$.getitem(id), function(x) x$unsqueeze(1))) + if (varying_shapes) { + x + } else { + map(transpose_list(x), function(x) torch_cat(x, dim = 1L)) + } + } else { + ds$.getbatch(ids) + } +} + +get_output = function(input, graph, varying_shapes, rbind, device) { + output = if (varying_shapes) { + # list --graph--> (list or tensor) + transpose_list(map(input, function(x) graph$train(x, single_input = FALSE))) + } else { + # tensor --graph--> tensor + graph$train(input, single_input = FALSE) + } + + # now we get it in the right output format and convert it to the requested device + output = if (rbind) { + if (varying_shapes) { # need to convert from list of tensors to tensor + output = map(output, list_to_batch) + } + map(output, function(x) x$to(device = device)) + } else { + if (!varying_shapes) { # need to convert from tensor to list of tensors + output = map(output, function(x) torch_split(x, split_size = 1L, dim = 1L)) + } + map(output, function(out) map(out, function(o) o$squeeze(1)$to(device = device))) + } + + return(output) +} + #' @title Materialize a Lazy Tensor #' @description #' Convert a [`lazy_tensor()`] to a [`torch_tensor()`]. @@ -142,25 +180,11 @@ materialize_internal = function(x, device = "cpu", cache = NULL, rbind) { if (input_hit) { input = cache[[input_hash]] - input_hit = TRUE } } if (!do_caching || !input_hit) { - input = if (is.null(ds$.getbatch)) { # .getindex is never NULL but a function that errs if it was not defined - x = map(ids, function(id) map(ds$.getitem(id), function(x) x$unsqueeze(1))) - if (varying_shapes || !rbind) { - x - } else { - map(transpose_list(x), function(x) torch_cat(x, dim = 1L)) - } - } else { - if (rbind) { - ds$.getbatch(ids) - } else { - map(ids, function(id) ds$.getbatch(id)) - } - } + input = get_input(ds, ids, varying_shapes, rbind) } if (do_caching && !input_hit) { @@ -170,42 +194,20 @@ materialize_internal = function(x, device = "cpu", cache = NULL, rbind) { # input is the output of a dataset so it can contain more than what we need for the graph, # also we need to set the correct names. # This is done after retrieving the element from the cache / before saving the element to the cache because - # this can change - - input = if (rbind && !varying_shapes) { - set_names(input[data_descriptor$input_map], data_descriptor$graph_input) - } else { + # this can change depending on the preprocessing graph + input = if (varying_shapes) { map(input, function(x) { set_names(x[data_descriptor$input_map], data_descriptor$graph_input) }) - } - - output = if (rbind && !varying_shapes) { - # tensor --graph--> tensor - graph$train(input, single_input = FALSE) } else { - # list --graph--> (list or tensor) - out = map(input, function(x) graph$train(x, single_input = FALSE)) - - if (rbind) { - # here, is a list with hierarchy: [id = [po_id = [ch_nm = ]]] - # We want to obtain a list [po_id = [ch_nm = [...]]] where the [...] is the rbind over all ids - rows = seq_along(out) - out = map(names(out[[1L]]), function(name) torch_cat(map(out[rows], name))) - } - out + set_names(input[data_descriptor$input_map], data_descriptor$graph_input) } + output = get_output(input, graph, varying_shapes, rbind, device) + if (do_caching) { cache[[output_hash]] = output } - # put the tensor on the required device - if (rbind) { - res = output[[pointer_name]]$to(device = device) - } else { - res = map(output, function(o) o[[pointer_name]]$to(device = device)) - } - - return(res) + output[[pointer_name]] } diff --git a/R/nn_graph.R b/R/nn_graph.R index 14f4acf5..444f5503 100644 --- a/R/nn_graph.R +++ b/R/nn_graph.R @@ -16,20 +16,26 @@ #' @family Graph Network #' @export #' @examples -#' graph = po("module_1", module = nn_linear(10, 20)) %>>% -#' po("module_2", module = nn_relu()) %>>% -#' po("module_3", module = nn_linear(20, 1)) +#' graph = mlr3pipelines::Graph$new() +#' graph$add_pipeop(po("module_1", module = nn_linear(10, 20)), clone = FALSE) +#' graph$add_pipeop(po("module_2", module = nn_relu()), clone = FALSE) +#' graph$add_pipeop(po("module_3", module = nn_linear(20, 1)), clone = FALSE) +#' graph$add_edge("module_1", "module_2") +#' graph$add_edge("module_2", "module_3") +#' #' network = nn_graph(graph, shapes_in = list(module_1.input = c(NA, 10))) -#' network +#' #' x = torch_randn(16, 10) +#' #' network(module_1.input = x) nn_graph = nn_module( "nn_graph", initialize = function(graph, shapes_in, output_map = graph$output$name, list_output = FALSE) { - self$graph = as_graph(graph) + self$graph = as_graph(graph, clone = FALSE) self$graph_input_name = graph$input$name # cache this, it is expensive # we do NOT verify the input and type of the graph to be `"torch_tensor"`. + # The reason for this is that the graph, when constructed with the PipeOpTorch Machinery, contains PipeOpNOPs, # which have input and output type *. diff --git a/R/preprocess.R b/R/preprocess.R index f4debf8b..85bac91e 100644 --- a/R/preprocess.R +++ b/R/preprocess.R @@ -42,99 +42,218 @@ register_preproc("trafo_nop", identity, shapes_out = "unchanged", rowwise = FALS #' @template preprocess_torchvision #' @templateVar id trafo_adjust_gamma -register_preproc("trafo_adjust_gamma", torchvision::transform_adjust_gamma, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint +register_preproc("trafo_adjust_gamma", torchvision::transform_adjust_gamma, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, + param_set = ps( + gamma = p_dbl(lower = 0, tags = c("train", "required")), + gain = p_dbl(default = 1, tags = "train") + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id trafo_adjust_brightness -register_preproc("trafo_adjust_brightness", torchvision::transform_adjust_brightness, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint +register_preproc("trafo_adjust_brightness", torchvision::transform_adjust_brightness, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, + param_set = ps( + brightness_factor = p_dbl(lower = 0, tags = c("train", "required")) + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id trafo_adjust_hue -register_preproc("trafo_adjust_hue", torchvision::transform_adjust_hue, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) +register_preproc("trafo_adjust_hue", torchvision::transform_adjust_hue, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, + param_set = ps( + hue_factor = p_dbl(lower = -0.5, upper = 0.5, tags = c("train", "required")) + ) +) #' @template preprocess_torchvision #' @templateVar id trafo_adjust_saturation -register_preproc("trafo_adjust_saturation", torchvision::transform_adjust_saturation, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint +register_preproc("trafo_adjust_saturation", torchvision::transform_adjust_saturation, packages = "torchvision", shapes_out = "infer", rowwise = TRUE, + param_set = ps( + saturation_factor = p_dbl(tags = c("train", "required")) + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id trafo_grayscale -register_preproc("trafo_grayscale", torchvision::transform_grayscale, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint +register_preproc("trafo_grayscale", torchvision::transform_grayscale, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, + param_set = ps( + num_output_channels = p_int(lower = 1L, upper = 3L, tags = c("train", "required")) + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id trafo_rgb_to_grayscale -register_preproc("trafo_rgb_to_grayscale", torchvision::transform_rgb_to_grayscale, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint +register_preproc("trafo_rgb_to_grayscale", torchvision::transform_rgb_to_grayscale, packages = "torchvision", shapes_out = "infer", rowwise = TRUE, + param_set = ps() +) # nolint #' @template preprocess_torchvision #' @templateVar id trafo_normalize -register_preproc("trafo_normalize", torchvision::transform_normalize, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint +register_preproc("trafo_normalize", torchvision::transform_normalize, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, + param_set = ps( + mean = p_uty(tags = c("train", "required")), + std = p_uty(tags = c("train", "required")) + # no inplace parameter as this might be problematic when a preprocessing pipeop's output is connected to multiple + # other pipeops + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id trafo_pad -register_preproc("trafo_pad", torchvision::transform_pad, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint +register_preproc("trafo_pad", torchvision::transform_pad, packages = "torchvision", shapes_out = "infer", rowwise = TRUE, + param_set = ps( + padding = p_uty(tags = c("train", "required")), + fill = p_uty(default = 0, tags = "train"), + padding_mode = p_fct(default = "constant", levels = c("constant", "edge", "reflect", "symmetric"), tags = "train") + ) +) # nolint # Data Augmentation #' @template preprocess_torchvision #' @templateVar id augment_resized_crop -register_preproc("augment_resized_crop", torchvision::transform_resized_crop, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint +register_preproc("augment_resized_crop", torchvision::transform_resized_crop, packages = "torchvision", shapes_out = "infer", rowwise = TRUE, + param_set = ps( + top = p_int(tags = c("train", "required")), + left = p_int(tags = c("train", "required")), + height = p_int(tags = c("train", "required")), + width = p_int(tags = c("train", "required")), + size = p_uty(tags = c("train", "required")), + interpolation = p_int(default = 2L, lower = 0L, upper = 3L, tags = "train") + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id augment_color_jitter -register_preproc("augment_color_jitter", torchvision::transform_color_jitter, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint +register_preproc("augment_color_jitter", torchvision::transform_color_jitter, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, + param_set = ps( + brightness = p_dbl(default = 0, lower = 0, tags = "train"), + contrast = p_dbl(default = 0, lower = 0, tags = "train"), + saturation = p_dbl(default = 0, lower = 0, tags = "train"), + hue = p_dbl(default = 0, lower = 0, tags = "train") + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id augment_random_resized_crop -register_preproc("augment_random_resized_crop", torchvision::transform_random_resized_crop, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint +register_preproc("augment_random_resized_crop", torchvision::transform_random_resized_crop, packages = "torchvision", shapes_out = NULL, rowwise = TRUE, + param_set = ps( + size = p_uty(tags = c("train", "required")), + scale = p_uty(default = c(0.08, 1), tags = "train"), + ratio = p_uty(default = c(3 / 4, 4 / 3), tags = "train"), + interpolation = p_int(default = 2L, lower = 0L, upper = 3L, tags = "train") + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id augment_random_order -register_preproc("augment_random_order", torchvision::transform_random_order, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint +register_preproc("augment_random_order", torchvision::transform_random_order, packages = "torchvision", shapes_out = NULL, rowwise = TRUE, + param_set = ps( + transforms = p_uty(tags = c("train", "required"), custom_check = check_list) + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id augment_hflip -register_preproc("augment_hflip", torchvision::transform_hflip, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint +register_preproc("augment_hflip", torchvision::transform_hflip, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, + param_set = ps() +) # nolint #' @template preprocess_torchvision #' @templateVar id augment_random_horizontal_flip -register_preproc("augment_random_horizontal_flip", torchvision::transform_random_horizontal_flip, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint +register_preproc("augment_random_horizontal_flip", torchvision::transform_random_horizontal_flip, packages = "torchvision", shapes_out = NULL, rowwise = TRUE, + param_set = ps( + p = p_dbl(default = 0.5, lower = 0, upper = 1, tags = "train") + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id augment_crop -register_preproc("augment_crop", torchvision::transform_crop, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint +register_preproc("augment_crop", torchvision::transform_crop, packages = "torchvision", shapes_out = "infer", rowwise = TRUE, + param_set = ps( + top = p_int(tags = c("train", "required")), + left = p_int(tags = c("train", "required")), + height = p_int(tags = c("train", "required")), + width = p_int(tags = c("train", "required")) + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id augment_random_vertical_flip -register_preproc("augment_random_vertical_flip", torchvision::transform_random_vertical_flip, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint +register_preproc("augment_random_vertical_flip", torchvision::transform_random_vertical_flip, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, + param_set = ps( + p = p_dbl(default = 0.5, lower = 0, upper = 1, tags = "train") + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id augment_random_affine -register_preproc("augment_random_affine", torchvision::transform_random_affine, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint +register_preproc("augment_random_affine", torchvision::transform_random_affine, packages = "torchvision", shapes_out = NULL, rowwise = TRUE, + param_set = ps( + degrees = p_uty(tags = c("train", "required")), + translate = p_uty(default = NULL, tags = "train"), + scale = p_uty(default = NULL, tags = "train"), + resample = p_int(default = 0, tags = "train"), + fillcolor = p_uty(default = 0, tags = "train") + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id augment_vflip -register_preproc("augment_vflip", torchvision::transform_vflip, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint +register_preproc("augment_vflip", torchvision::transform_vflip, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, + param_set = ps() +) # nolint #' @template preprocess_torchvision #' @templateVar id augment_random_apply -register_preproc("augment_random_apply", torchvision::transform_random_apply, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint +register_preproc("augment_random_apply", torchvision::transform_random_apply, packages = "torchvision", shapes_out = NULL, rowwise = TRUE, + param_set = ps( + transforms = p_uty(tags = c("train", "required"), custom_check = check_list), + p = p_dbl(default = 0.5, lower = 0, upper = 1, tags = "train") + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id augment_rotate -register_preproc("augment_rotate", torchvision::transform_rotate, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint +register_preproc("augment_rotate", torchvision::transform_rotate, packages = "torchvision", shapes_out = NULL, rowwise = TRUE, + param_set = ps( + angle = p_uty(tags = c("train", "required")), + resample = p_int(default = 0L, tags = "train"), + expand = p_lgl(default = FALSE, tags = "train"), + center = p_uty(default = NULL, tags = "train"), + fill = p_uty(default = NULL, tags = "train") + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id augment_center_crop -register_preproc("augment_center_crop", torchvision::transform_center_crop, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint +register_preproc("augment_center_crop", torchvision::transform_center_crop, packages = "torchvision", shapes_out = "infer", rowwise = TRUE, + param_set = ps( + size = p_uty(tags = c("train", "required")) + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id augment_random_choice -register_preproc("augment_random_choice", torchvision::transform_random_choice, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint +register_preproc("augment_random_choice", torchvision::transform_random_choice, packages = "torchvision", shapes_out = NULL, rowwise = TRUE, + param_set = ps( + transforms = p_uty(custom_check = check_list, tags = c("train", "required")) + ) +) # nolint #' @template preprocess_torchvision #' @templateVar id augment_random_crop -register_preproc("augment_random_crop", torchvision::transform_random_crop, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) +register_preproc("augment_random_crop", torchvision::transform_random_crop, packages = "torchvision", shapes_out = NULL, rowwise = TRUE, + param_set = ps( + size = p_uty(tags = c("train", "required")), + padding = p_uty(default = NULL, tags = "train"), + pad_if_needed = p_lgl(default = FALSE, tags = "train"), + fill = p_uty(default = 0L, tags = "train"), + padding_mode = p_fct(default = "constant", levels = c("constant", "edge", "reflect", "symmetric"), tags = "train") + ) +) ##' @name PipeOpPreprocTorchAugmentRandomRotation diff --git a/R/reset_last_layer.R b/R/reset_last_layer.R index 579fd4be..d6a761f1 100644 --- a/R/reset_last_layer.R +++ b/R/reset_last_layer.R @@ -20,16 +20,18 @@ #' @examples #' \dontrun{ #' # AlexNet -#' model = torchvision::model_alexnet(pretrained = TRUE) -#' model$classifier[[7]]$out_feature -#' model = reset_last_layer(model, 10) -#' model$classifier[[7]]$out_feature +#' if (mlr3misc::requires_namespaces("torchvision")) { +#' model = torchvision::model_alexnet(pretrained = TRUE) +#' model$classifier[[7]]$out_feature +#' model = reset_last_layer(model, 10) +#' model$classifier[[7]]$out_feature #' -#' # ResNet -#' model = torchvision::model_resnet18(pretrained = TRUE) -#' model$fc$out_feature -#' model = reset_last_layer(model, 10) -#' model$fc$out_feature +#' # ResNet +#' model = torchvision::model_resnet18(pretrained = TRUE) +#' model$fc$out_feature +#' model = reset_last_layer(model, 10) +#' model$fc$out_feature +#' } #' } reset_last_layer = function(model, num_classes, bias, freeze) { UseMethod("reset_last_layer") diff --git a/R/task_dataset.R b/R/task_dataset.R index 5e232dcd..296d94b6 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -65,7 +65,7 @@ task_dataset = dataset( if (inherits(merge_result, "try-error")) { # This should basically never happen - lg$warn("Failed to merge data descriptor, this might leady to inefficient preprocessing.") + lg$warn("Failed to merge data descriptor, this might lead to inefficient preprocessing.") # TODO: test that is still works when this triggers } else { self$task$cbind(merge_result) @@ -144,9 +144,6 @@ merge_lazy_tensor_graphs = function(lts) { dataset_ltnsr = function(task, param_vals) { assert_true(length(task$feature_names) == 1L) shape = dd(task$data(cols = task$feature_names)[[1L]])$pointer_shape - if (is.null(shape)) { - stopf("Each row element of the lazy tensor column must be of a known shape, please resize it accordingly.") - } ingress_tokens = list(image = TorchIngressToken(task$feature_names, batchgetter_lazy_tensor, shape)) task_dataset( diff --git a/R/utils.R b/R/utils.R index 9dfdfa25..01956025 100644 --- a/R/utils.R +++ b/R/utils.R @@ -190,6 +190,7 @@ test_equal = function(x, y) { isTRUE(all.equal(x, y)) } + dataset_image = dataset("image_dataset", initialize = function(uris) { self$uris = uris @@ -202,3 +203,6 @@ dataset_image = dataset("image_dataset", } ) +list_to_batch = function(tensors) { + torch_cat(map(tensors, function(x) x$unsqueeze(1)), dim = 1L) +} diff --git a/man/DataDescriptor.Rd b/man/DataDescriptor.Rd index 35a0ee44..5409ded1 100644 --- a/man/DataDescriptor.Rd +++ b/man/DataDescriptor.Rd @@ -112,7 +112,7 @@ Character vector that must have the same length as the input of the graph. Specifies how the data from the \code{dataset} is fed into the preprocessing graph.} \item{\code{pointer}}{(\code{character(2)} | \code{NULL})\cr -Indicating an element on which a model is. Points to an output channel within \code{graph}: +Points to an output channel within \code{graph}: Element 1 is the \code{PipeOp}'s id and element 2 is that \code{PipeOp}'s output channel.} \item{\code{pointer_shape}}{(\code{integer} | \code{NULL})\cr diff --git a/man/PipeOpPreprocTorchAugmentColorJitter.Rd b/man/PipeOpPreprocTorchAugmentColorJitter.Rd index 311f55d1..bf55d6b6 100644 --- a/man/PipeOpPreprocTorchAugmentColorJitter.Rd +++ b/man/PipeOpPreprocTorchAugmentColorJitter.Rd @@ -13,14 +13,14 @@ see there for more information on the parameters. The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - brightness \tab untyped \tab - \tab \cr - contrast \tab untyped \tab - \tab \cr - saturation \tab untyped \tab - \tab \cr - hue \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + brightness \tab numeric \tab 0 \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr + contrast \tab numeric \tab 0 \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr + saturation \tab numeric \tab 0 \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr + hue \tab numeric \tab 0 \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr } } diff --git a/man/PipeOpPreprocTorchAugmentCrop.Rd b/man/PipeOpPreprocTorchAugmentCrop.Rd index f18c1add..15aa7624 100644 --- a/man/PipeOpPreprocTorchAugmentCrop.Rd +++ b/man/PipeOpPreprocTorchAugmentCrop.Rd @@ -13,14 +13,14 @@ see there for more information on the parameters. The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - top \tab untyped \tab - \tab \cr - left \tab untyped \tab - \tab \cr - height \tab untyped \tab - \tab \cr - width \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + top \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + left \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + height \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + width \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr } } diff --git a/man/PipeOpPreprocTorchAugmentRandomAffine.Rd b/man/PipeOpPreprocTorchAugmentRandomAffine.Rd index bb40cc78..043feaab 100644 --- a/man/PipeOpPreprocTorchAugmentRandomAffine.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomAffine.Rd @@ -13,16 +13,15 @@ see there for more information on the parameters. The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - degrees \tab untyped \tab - \tab \cr - translate \tab untyped \tab - \tab \cr - scale \tab untyped \tab - \tab \cr - shear \tab untyped \tab - \tab \cr - resample \tab untyped \tab - \tab \cr - fillcolor \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + degrees \tab untyped \tab - \tab \tab - \cr + translate \tab untyped \tab \tab \tab - \cr + scale \tab untyped \tab \tab \tab - \cr + resample \tab integer \tab 0 \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + fillcolor \tab untyped \tab 0 \tab \tab - \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr } } diff --git a/man/PipeOpPreprocTorchAugmentRandomApply.Rd b/man/PipeOpPreprocTorchAugmentRandomApply.Rd index 63ed26fd..169d6b1c 100644 --- a/man/PipeOpPreprocTorchAugmentRandomApply.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomApply.Rd @@ -13,12 +13,12 @@ see there for more information on the parameters. The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - transforms \tab untyped \tab - \tab \cr - p \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + transforms \tab untyped \tab - \tab \tab - \cr + p \tab numeric \tab 0.5 \tab \tab \eqn{[0, 1]}{[0, 1]} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr } } diff --git a/man/PipeOpPreprocTorchAugmentRandomCrop.Rd b/man/PipeOpPreprocTorchAugmentRandomCrop.Rd index 14271714..c07d5c90 100644 --- a/man/PipeOpPreprocTorchAugmentRandomCrop.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomCrop.Rd @@ -16,10 +16,10 @@ The preprocessing is applied row wise (no batch dimension). \tabular{llll}{ Id \tab Type \tab Default \tab Levels \cr size \tab untyped \tab - \tab \cr - padding \tab untyped \tab - \tab \cr - pad_if_needed \tab untyped \tab - \tab \cr - fill \tab untyped \tab - \tab \cr - padding_mode \tab untyped \tab - \tab \cr + padding \tab untyped \tab \tab \cr + pad_if_needed \tab logical \tab FALSE \tab TRUE, FALSE \cr + fill \tab untyped \tab 0 \tab \cr + padding_mode \tab character \tab constant \tab constant, edge, reflect, symmetric \cr stages \tab character \tab - \tab train, predict, both \cr affect_columns \tab untyped \tab selector_all \tab \cr } diff --git a/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd b/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd index ec59b1ad..49522bb6 100644 --- a/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd @@ -13,11 +13,11 @@ see there for more information on the parameters. The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - p \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + p \tab numeric \tab 0.5 \tab \tab \eqn{[0, 1]}{[0, 1]} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr } } diff --git a/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd b/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd index f33f6dc4..a5f74d63 100644 --- a/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd @@ -13,14 +13,14 @@ see there for more information on the parameters. The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - size \tab untyped \tab - \tab \cr - scale \tab untyped \tab - \tab \cr - ratio \tab untyped \tab - \tab \cr - interpolation \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + size \tab untyped \tab - \tab \tab - \cr + scale \tab untyped \tab c , 0.08, 1 \tab \tab - \cr + ratio \tab untyped \tab c , 3/4, 4/3 \tab \tab - \cr + interpolation \tab integer \tab 2 \tab \tab \eqn{[0, 3]}{[0, 3]} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr } } diff --git a/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd b/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd index 1e2b1280..5781cfba 100644 --- a/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd +++ b/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd @@ -13,11 +13,11 @@ see there for more information on the parameters. The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - p \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + p \tab numeric \tab 0.5 \tab \tab \eqn{[0, 1]}{[0, 1]} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr } } diff --git a/man/PipeOpPreprocTorchAugmentResizedCrop.Rd b/man/PipeOpPreprocTorchAugmentResizedCrop.Rd index 62787725..799dbc10 100644 --- a/man/PipeOpPreprocTorchAugmentResizedCrop.Rd +++ b/man/PipeOpPreprocTorchAugmentResizedCrop.Rd @@ -13,16 +13,16 @@ see there for more information on the parameters. The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - top \tab untyped \tab - \tab \cr - left \tab untyped \tab - \tab \cr - height \tab untyped \tab - \tab \cr - width \tab untyped \tab - \tab \cr - size \tab untyped \tab - \tab \cr - interpolation \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + top \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + left \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + height \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + width \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + size \tab untyped \tab - \tab \tab - \cr + interpolation \tab integer \tab 2 \tab \tab \eqn{[0, 3]}{[0, 3]} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr } } diff --git a/man/PipeOpPreprocTorchAugmentRotate.Rd b/man/PipeOpPreprocTorchAugmentRotate.Rd index 52163486..6508b070 100644 --- a/man/PipeOpPreprocTorchAugmentRotate.Rd +++ b/man/PipeOpPreprocTorchAugmentRotate.Rd @@ -13,15 +13,15 @@ see there for more information on the parameters. The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - angle \tab untyped \tab - \tab \cr - resample \tab untyped \tab - \tab \cr - expand \tab untyped \tab - \tab \cr - center \tab untyped \tab - \tab \cr - fill \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + angle \tab untyped \tab - \tab \tab - \cr + resample \tab integer \tab 0 \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + expand \tab logical \tab FALSE \tab TRUE, FALSE \tab - \cr + center \tab untyped \tab \tab \tab - \cr + fill \tab untyped \tab \tab \tab - \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr } } diff --git a/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd b/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd index 36ead02e..fe636d29 100644 --- a/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd +++ b/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd @@ -13,11 +13,11 @@ see there for more information on the parameters. The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - brightness_factor \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + brightness_factor \tab numeric \tab - \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr } } diff --git a/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd b/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd index 96187f4e..a2bcef11 100644 --- a/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd +++ b/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd @@ -13,12 +13,12 @@ see there for more information on the parameters. The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - gamma \tab untyped \tab - \tab \cr - gain \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + gamma \tab numeric \tab - \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr + gain \tab numeric \tab 1 \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr } } diff --git a/man/PipeOpPreprocTorchTrafoAdjustHue.Rd b/man/PipeOpPreprocTorchTrafoAdjustHue.Rd index 70ee9657..1cc75a96 100644 --- a/man/PipeOpPreprocTorchTrafoAdjustHue.Rd +++ b/man/PipeOpPreprocTorchTrafoAdjustHue.Rd @@ -13,11 +13,11 @@ see there for more information on the parameters. The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - hue_factor \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + hue_factor \tab numeric \tab - \tab \tab \eqn{[-0.5, 0.5]}{[-0.5, 0.5]} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr } } diff --git a/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd b/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd index c3ec9817..ced93824 100644 --- a/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd +++ b/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd @@ -13,11 +13,11 @@ see there for more information on the parameters. The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - saturation_factor \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + saturation_factor \tab numeric \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr } } diff --git a/man/PipeOpPreprocTorchTrafoGrayscale.Rd b/man/PipeOpPreprocTorchTrafoGrayscale.Rd index b1675491..014d8fee 100644 --- a/man/PipeOpPreprocTorchTrafoGrayscale.Rd +++ b/man/PipeOpPreprocTorchTrafoGrayscale.Rd @@ -13,11 +13,11 @@ see there for more information on the parameters. The preprocessing is applied row wise (no batch dimension). } \section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - num_output_channels \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + num_output_channels \tab integer \tab - \tab \tab \eqn{[1, 3]}{[1, 3]} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr } } diff --git a/man/PipeOpPreprocTorchTrafoNormalize.Rd b/man/PipeOpPreprocTorchTrafoNormalize.Rd index 5dd9a9b0..a802514b 100644 --- a/man/PipeOpPreprocTorchTrafoNormalize.Rd +++ b/man/PipeOpPreprocTorchTrafoNormalize.Rd @@ -17,7 +17,6 @@ The preprocessing is applied row wise (no batch dimension). Id \tab Type \tab Default \tab Levels \cr mean \tab untyped \tab - \tab \cr std \tab untyped \tab - \tab \cr - inplace \tab untyped \tab - \tab \cr stages \tab character \tab - \tab train, predict, both \cr affect_columns \tab untyped \tab selector_all \tab \cr } diff --git a/man/PipeOpPreprocTorchTrafoPad.Rd b/man/PipeOpPreprocTorchTrafoPad.Rd index c22ca878..b9c7f1ca 100644 --- a/man/PipeOpPreprocTorchTrafoPad.Rd +++ b/man/PipeOpPreprocTorchTrafoPad.Rd @@ -16,8 +16,8 @@ The preprocessing is applied row wise (no batch dimension). \tabular{llll}{ Id \tab Type \tab Default \tab Levels \cr padding \tab untyped \tab - \tab \cr - fill \tab untyped \tab - \tab \cr - padding_mode \tab untyped \tab - \tab \cr + fill \tab untyped \tab 0 \tab \cr + padding_mode \tab character \tab constant \tab constant, edge, reflect, symmetric \cr stages \tab character \tab - \tab train, predict, both \cr affect_columns \tab untyped \tab selector_all \tab \cr } diff --git a/man/materialize.Rd b/man/materialize.Rd index 995196b3..53749cd0 100644 --- a/man/materialize.Rd +++ b/man/materialize.Rd @@ -19,7 +19,7 @@ The torch device.} \item{rbind}{(\code{logical(1)})\cr Whether to rbind the lazy tensor columns (\code{TRUE}) or return them as a list of tensors (\code{FALSE}). -In the second case, the batch dimension is present for all individual tensors.} +In the second case, there is no batch dimension.} \item{...}{(any)\cr Additional arguments.} diff --git a/man/mlr_pipeops_preproc_torch.Rd b/man/mlr_pipeops_preproc_torch.Rd index 9e2942d9..fb60fb0b 100644 --- a/man/mlr_pipeops_preproc_torch.Rd +++ b/man/mlr_pipeops_preproc_torch.Rd @@ -218,8 +218,9 @@ Creates a new instance of this \code{\link[R6:R6Class]{R6}} class. \subsection{Arguments}{ \if{html}{\out{
}} \describe{ -\item{\code{fn}}{(\code{function})\cr -The preprocessing function. Should not modify its input in-place.} +\item{\code{fn}}{(\code{function} or \code{character(2)})\cr +The preprocessing function. Should not modify its input in-place. +If it is a \code{character(2)}, the first element should be the namespace and thje second element the name.} \item{\code{id}}{(\code{character(1)})\cr The id for of the new object.} diff --git a/man/mlr_pipeops_torch_ingress_ltnsr.Rd b/man/mlr_pipeops_torch_ingress_ltnsr.Rd index 00c53cf5..b6900f8f 100644 --- a/man/mlr_pipeops_torch_ingress_ltnsr.Rd +++ b/man/mlr_pipeops_torch_ingress_ltnsr.Rd @@ -45,7 +45,7 @@ x_batch # Now we try a lazy tensor with unknown shape, i.e. the shapes between the rows can differ ds = dataset( - initialize = function() self$x = list(torch_randn(3, 10, 10), torch_randn(10, 8, 8)), + initialize = function() self$x = list(torch_randn(3, 10, 10), torch_randn(3, 8, 8)), .getitem = function(i) list(x = self$x[[i]]), .length = function() 2)() diff --git a/man/nn_graph.Rd b/man/nn_graph.Rd index 32e682ed..4c7818da 100644 --- a/man/nn_graph.Rd +++ b/man/nn_graph.Rd @@ -26,12 +26,17 @@ Whether output should be a list of tensors. If \code{FALSE} (default), then \cod Represents a neural network using a \code{\link{Graph}} that usually costains mostly \code{\link{PipeOpModule}}s. } \examples{ -graph = po("module_1", module = nn_linear(10, 20)) \%>>\% - po("module_2", module = nn_relu()) \%>>\% - po("module_3", module = nn_linear(20, 1)) +graph = mlr3pipelines::Graph$new() +graph$add_pipeop(po("module_1", module = nn_linear(10, 20)), clone = FALSE) +graph$add_pipeop(po("module_2", module = nn_relu()), clone = FALSE) +graph$add_pipeop(po("module_3", module = nn_linear(20, 1)), clone = FALSE) +graph$add_edge("module_1", "module_2") +graph$add_edge("module_2", "module_3") + network = nn_graph(graph, shapes_in = list(module_1.input = c(NA, 10))) -network + x = torch_randn(16, 10) + network(module_1.input = x) } \seealso{ diff --git a/man/pipeop_preproc_torch.Rd b/man/pipeop_preproc_torch.Rd index 0061261d..d0a52d7b 100644 --- a/man/pipeop_preproc_torch.Rd +++ b/man/pipeop_preproc_torch.Rd @@ -7,7 +7,7 @@ pipeop_preproc_torch( id, fn, - shapes_out, + shapes_out = NULL, param_set = NULL, param_vals = list(), packages = character(0), diff --git a/man/pipeop_preproc_torch_class.Rd b/man/pipeop_preproc_torch_class.Rd index 0074e64f..05f2bcd3 100644 --- a/man/pipeop_preproc_torch_class.Rd +++ b/man/pipeop_preproc_torch_class.Rd @@ -60,7 +60,7 @@ Function to create objects of class \code{\link{PipeOpTaskPreprocTorch}} in a sl Start by reading the documentation of \code{\link{PipeOpTaskPreprocTorch}}. } \examples{ -po_example = pipeop_preproc_torch("preproc_example", function(x, a) x + a) +po_example = pipeop_preproc_torch("preproc_example", function(x, a) x + a, ) po_example po_example$param_set } diff --git a/man/reset_layer.Rd b/man/reset_layer.Rd index a16b71af..27bf47bc 100644 --- a/man/reset_layer.Rd +++ b/man/reset_layer.Rd @@ -36,15 +36,17 @@ As of this, this also freezes the parameters of all but the last layer. \examples{ \dontrun{ # AlexNet -model = torchvision::model_alexnet(pretrained = TRUE) -model$classifier[[7]]$out_feature -model = reset_last_layer(model, 10) -model$classifier[[7]]$out_feature +if (mlr3misc::requires_namespaces("torchvision")) { + model = torchvision::model_alexnet(pretrained = TRUE) + model$classifier[[7]]$out_feature + model = reset_last_layer(model, 10) + model$classifier[[7]]$out_feature -# ResNet -model = torchvision::model_resnet18(pretrained = TRUE) -model$fc$out_feature -model = reset_last_layer(model, 10) -model$fc$out_feature + # ResNet + model = torchvision::model_resnet18(pretrained = TRUE) + model$fc$out_feature + model = reset_last_layer(model, 10) + model$fc$out_feature +} } } diff --git a/tests/testthat/helper_autotest.R b/tests/testthat/helper_autotest.R index 2b2a0f68..252fdf59 100644 --- a/tests/testthat/helper_autotest.R +++ b/tests/testthat/helper_autotest.R @@ -373,7 +373,7 @@ autotest_pipeop_torch_preprocess = function(obj, shapes_in, exclude = character( if (!is.null(shape_out)) { testthat::expect_equal(tnsr_out$shape, shape_out) testthat::expect_equal(tnsr_out$shape[-1L], shape_out_unknown_batch[-1L]) - expect_true(is.na(shape_out_unknown_batch[1L])) + testthat::expect_true(is.na(shape_out_unknown_batch[1L])) } }) } diff --git a/tests/testthat/test_autotests.R b/tests/testthat/test_autotests.R index 897f4aef..be346ace 100644 --- a/tests/testthat/test_autotests.R +++ b/tests/testthat/test_autotests.R @@ -176,20 +176,3 @@ test_that("autotest_torch_callback works", { expect_error(autotest_torch_callback(cbd, check_man = FALSE), regexp = "not equal to") }) - - -test_that("autotest_pipeop_torch", { - # TODO: - -}) - -test_that("autotest_pipeop_torch_preproces", { - # test that: - # a) id * - - - - - autotest_pipeop_torch_preprocess - -}) diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index f0361d7a..891936fc 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -23,7 +23,9 @@ test_that("Unknown shapes work", { expect_class(lt, "lazy_tensor") materialize(lt) expect_true(test_class(lt[1:2], "lazy_tensor")) - expect_true(test_class(lt[[1]], "lazy_tensor")) + expect_class(lt[[1]], "list") + + expect_class(c(lt, lazy_tensor()), "lazy_tensor") ds = random_dataset(10, 3) expect_error(DataDescriptor$new(ds, list(x = NULL))) diff --git a/tests/testthat/test_materialize.R b/tests/testthat/test_materialize.R index 2b3e9881..2a344115 100644 --- a/tests/testthat/test_materialize.R +++ b/tests/testthat/test_materialize.R @@ -8,14 +8,14 @@ test_that("materialize works on lazy_tensor", { expect_true(output$device == torch_device("cpu")) expect_true(torch_equal(output, ds$x)) # the correct elements are returned - expect_torch_equal(ds$.getbatch(1)[[1]], materialize(lt[1])[[1]]) - expect_torch_equal(ds$.getbatch(2)[[1]], materialize(lt[2])[[1]]) + expect_torch_equal(ds$.getbatch(1)[[1]], materialize(lt[1])[[1]]$unsqueeze(1)) + expect_torch_equal(ds$.getbatch(2)[[1]], materialize(lt[2])[[1]]$unsqueeze(1)) expect_torch_equal(ds$.getbatch(2:1)[[1]], materialize(lt[2:1], rbind = TRUE)) output_meta_list = materialize(lt, device = "meta", rbind = FALSE) output_meta_tnsr = materialize(lt, device = "meta", rbind = TRUE) - expect_equal(torch_cat(output_meta_list, dim = 1L)$shape, output_meta_tnsr$shape) + expect_equal(torch_cat(map(output_meta_list, function(x) x$unsqueeze(1)), dim = 1L)$shape, output_meta_tnsr$shape) expect_true(output_meta_tnsr$device == torch_device("meta")) expect_error(materialize(lazy_tensor()), "Cannot materialize ") @@ -50,7 +50,7 @@ test_that("materialize works with same shapes and .getbatch method", { res1cpu = materialize(x, rbind = FALSE) res2cpu = materialize(x, rbind = TRUE) - expect_torch_equal(torch_cat(res1cpu, dim = 1L), res2cpu) + expect_torch_equal(list_to_batch(res1cpu), res2cpu) expect_equal(res2cpu$shape, res2$shape) }) @@ -70,7 +70,7 @@ test_that("materialize works with same shapes and .getitem method", { res1cpu = materialize(x, rbind = FALSE) res2cpu = materialize(x, rbind = TRUE) - expect_torch_equal(torch_cat(res1cpu, dim = 1L), res2cpu) + expect_torch_equal(list_to_batch(res1cpu), res2cpu) expect_equal(res2cpu$shape, res2$shape) }) @@ -82,11 +82,11 @@ test_that("materialize_internal works", { res2 = materialize(x, rbind = TRUE) expect_list(res1, types = "torch_tensor") expect_class(res2, "torch_tensor") - expect_torch_equal(torch_cat(res1, dim = 1L), res2) + expect_torch_equal(list_to_batch(res1), res2) res1cpu = materialize(x, rbind = FALSE) res2cpu = materialize(x, rbind = TRUE) - expect_torch_equal(torch_cat(res1cpu, dim = 1L), res2cpu) + expect_torch_equal(list_to_batch(res1cpu), res2cpu) }) @@ -104,21 +104,6 @@ test_that("materialize.list works", { # c) default = "auto" works as expected # TODO - -}) - -test_that("materialize_internal: caching of graphs works", { - cache = new.env() - task = tsk("lazy_iris") - # need to rename because of a nasty bug in pipelines: - # https://github.com/mlr-org/mlr3pipelines/issues/738` - - dt = task$data(1:2, cols = "x") - dt$x1 = dt$x - names(dt) = c("x1", "x2") - - materialize(dt, rbind = TRUE) - }) test_that("materialize_internal: caching of datasets works", { From bf9212a5fc26dac91b3c91023baa4bc016445bc0 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Mon, 22 Jan 2024 18:51:32 +0100 Subject: [PATCH 25/90] pkgdown --- R/DataDescriptor.R | 39 ++++++------------------------ R/task_dataset.R | 28 ++++++++++++++------- man/DataDescriptor.Rd | 2 +- pkgdown/_pkgdown.yml | 4 --- tests/testthat/test_task_dataset.R | 4 +++ 5 files changed, 31 insertions(+), 46 deletions(-) diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index 188dd59c..157f2ede 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -24,7 +24,7 @@ #' @param pointer (`character(2)` | `NULL`)\cr #' Points to an output channel within `graph`: #' Element 1 is the `PipeOp`'s id and element 2 is that `PipeOp`'s output channel. -#' @param pointer_shape (`integer` | `NULL`)\cr +#' @param pointer_shape (`integer()` | `NULL`)\cr #' Shape of the output indicated by `pointer`. #' @param clone_graph (`logical(1)`)\cr #' Whether to clone the preprocessing graph. @@ -85,9 +85,10 @@ DataDescriptor = R6Class("DataDescriptor", if (is.null(graph)) { if ((length(dataset_shapes) == 1L) && is.null(input_map)) { input_map = names(dataset_shapes) + } else { + assert_true(length(input_map) == 1L) + assert_subset(input_map, names(dataset_shapes)) } - assert_true(length(input_map) == 1L) - assert_subset(input_map, names(dataset_shapes)) graph = as_graph(po("nop", id = paste0(class(dataset)[[1L]], "_", input_map))) pointer = c(graph$output$op.id, graph$output$channel.name) @@ -95,13 +96,11 @@ DataDescriptor = R6Class("DataDescriptor", } else { graph = as_graph(graph, clone = clone_graph) assert_true(length(graph$pipeops) >= 1L) - assert_true(!is.null(input_map)) assert_choice(pointer[[1]], names(graph$pipeops)) assert_choice(pointer[[2]], graph$pipeops[[pointer[[1]]]]$output$name) assert_subset(paste0(pointer, collapse = "."), graph$output$name) assert_shape(pointer_shape, null_ok = TRUE) - assert_subset(input_map, names(dataset_shapes)) assert_true(length(input_map) == length(graph$input$name)) } @@ -120,6 +119,9 @@ DataDescriptor = R6Class("DataDescriptor", self$dataset_hash = dataset_hash self$graph_input = graph$input$name self$pointer_shape_predict = pointer_shape_predict + + # the pointer is not taken into account, because we save the whole output during caching (for which the + # hash is primarily used) self$hash = calculate_hash(self$dataset_hash, self$graph$hash, self$input_map) }, #' @description Prints the object @@ -167,30 +169,3 @@ DataDescriptor = R6Class("DataDescriptor", pointer_shape_predict = NULL ) ) - -#' @include utils.R -data_descriptor_union = function(dd1, dd2) { - # Otherwise it is ugly to do the caching of the data loading - # and this is not really a strong restriction - assert_true(dd1$dataset_hash == dd2$dataset_hash) - g1 = dd1$graph - g2 = dd2$graph - - input_map = unique(c( - set_names(dd1$input_map, g1$input$name), - set_names(dd2$input_map, g2$input$name) - )) - - graph = merge_graphs(g1, g2) # shallow clone, g1 and g2 graphs (not pipeops) are unmodified - - DataDescriptor$new( - dataset = dd1$dataset, - dataset_shapes = dd1$dataset_shapes, - graph = graph, - input_map = input_map, - pointer = dd1$pointer, - pointer_shape = dd1$pointer_shape, - pointer_shape_predict = dd1$pointer_shape_predict, - clone_graph = FALSE - ) -} diff --git a/R/task_dataset.R b/R/task_dataset.R index 296d94b6..50137d1f 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -65,14 +65,17 @@ task_dataset = dataset( if (inherits(merge_result, "try-error")) { # This should basically never happen - lg$warn("Failed to merge data descriptor, this might lead to inefficient preprocessing.") + lg$debug("Failed to merge data descriptor, this might lead to inefficient preprocessing.") # TODO: test that is still works when this triggers } else { self$task$cbind(merge_result) } - } - self$cache_lazy_tensors = length(unique(map_chr(data, function(x) dd(x)$hash))) > 1L + + # we can cache the output (hash) or the data (dataset_hash) + self$cache_lazy_tensors = length(unique(map_chr(data, function(x) dd(x)$hash))) > 1L || + length(unique(map_chr(data, function(x) dd(x)$dataset_hash))) > 1L + }, .getbatch = function(index) { cache = if (self$cache_lazy_tensors) new.env() @@ -94,19 +97,26 @@ task_dataset = dataset( ) merge_lazy_tensor_graphs = function(lts) { - # Otherwise it is ugly to do the caching of the data loading - # and this is not really a strong restriction - assert_true(length(unique(map_chr(lts, function(x) dd(x)$dataset_hash))) == 1L) + names_lts = names(lts) + # we only attempt to merge preprocessing graphs that have the same dataset_hash + groups = map_chr(lts, function(lt) digest::digest(dd(lt)$dataset_hash)) + lts = unlist(map(unique(groups), function(group) { + merge_compatible_lazy_tensor_graphs(lts[, names_lts[groups == group], with = FALSE]) + }), recursive = FALSE) + + as_data_backend(as.data.table(set_names(lts, names_lts))) +} + +merge_compatible_lazy_tensor_graphs = function(lts) { graph = Reduce(merge_graphs, map(lts, function(x) dd(x)$graph)) + input_map = Reduce(c, map(lts, function(lt) { set_names(list(dd(lt)$input_map), dd(lt)$graph$input$name) })) input_map = input_map[unique(names(input_map))] - input_map = unname(unlist(input_map[graph$input$name])) - # some PipeOs that were previously terminal might not be anymore, # for those we add nops and updaate the pointers for their data descriptors map_dtc(lts, function(lt) { @@ -131,7 +141,7 @@ merge_lazy_tensor_graphs = function(lts) { dataset = dd(lts[[1]])$dataset, dataset_shapes = dd(lts[[1L]])$dataset_shapes, graph = graph, - input_map = input_map, + input_map = dd(lts[[1]])$input_map, pointer = pointer, pointer_shape = dd(lt)$pointer_shape, pointer_shape_predict = dd(lt)$pointer_shape_predict, diff --git a/man/DataDescriptor.Rd b/man/DataDescriptor.Rd index 5409ded1..5d015f5f 100644 --- a/man/DataDescriptor.Rd +++ b/man/DataDescriptor.Rd @@ -115,7 +115,7 @@ Specifies how the data from the \code{dataset} is fed into the preprocessing gra Points to an output channel within \code{graph}: Element 1 is the \code{PipeOp}'s id and element 2 is that \code{PipeOp}'s output channel.} -\item{\code{pointer_shape}}{(\code{integer} | \code{NULL})\cr +\item{\code{pointer_shape}}{(\code{integer()} | \code{NULL})\cr Shape of the output indicated by \code{pointer}.} \item{\code{pointer_shape_predict}}{(\code{integer()} or \code{NULL})\cr diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index 921d0d55..2a08a8a7 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -44,10 +44,6 @@ articles: navbar: ~ contents: - get_started -- title: Image Classification - navbar: ~ - contents: - - articles/image_classification - title: Neural Networks as Graphs navbar: ~ contents: diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index 0e76d19e..90e340e5 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -293,3 +293,7 @@ test_that("caching of graph works", { print(env) expect_equal(env$counter, 1) }) + +test_that("merge_compatible_lazy_tensor_graphs", { + # TODO: +}) From 83ff680ca48ac5892dc18e456e350fade426e607 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Mon, 22 Jan 2024 19:16:44 +0100 Subject: [PATCH 26/90] some more fixes --- R/LearnerTorch.R | 32 +++++++---------- R/learner_torch_methods.R | 9 ----- R/task_dataset.R | 2 +- man-roxygen/preprocess_torchvision.R | 2 +- man/mlr_learners.alexnet.Rd | 4 +-- man/mlr_learners.mlp.Rd | 4 +-- man/mlr_learners.torch_featureless.Rd | 4 +-- man/mlr_learners_torch.Rd | 51 ++------------------------- man/mlr_learners_torch_image.Rd | 4 +-- man/mlr_learners_torch_model.Rd | 4 +-- 10 files changed, 28 insertions(+), 88 deletions(-) diff --git a/R/LearnerTorch.R b/R/LearnerTorch.R index 250df067..760f9423 100644 --- a/R/LearnerTorch.R +++ b/R/LearnerTorch.R @@ -199,25 +199,6 @@ LearnerTorch = R6Class("LearnerTorch", if (length(e)) { catn(str_indent("* Errors:", e)) } - }, - #' @description Train the learner. - #' @param task ([`Task`])\cr - #' The task. - #' @param row_ids (`integer()`)\cr - #' Which rows to use for training. - train = function(task, row_ids = NULL) { - private$.verify_train_task(task, row_ids) - super$train(task, row_ids) - }, - #' @description Predict on a task. - #' @param task ([`Task`])\cr - #' The task. - #' @param row_ids (`integer()`)\cr - #' The rows for which to make predictions. - #' @return ([`Prediction`]) - predict = function(task, row_ids = NULL) { - private$.verify_predict_task(task, row_ids) - super$predict(task, row_ids) } ), active = list( @@ -256,6 +237,7 @@ LearnerTorch = R6Class("LearnerTorch", ), private = list( .train = function(task) { + private$.verify_train_task(task) param_vals = self$param_set$get_values(tags = "train") param_vals$device = auto_device(param_vals$device) if (param_vals$seed == "random") param_vals$seed = sample.int(10000000L, 1L) @@ -267,6 +249,7 @@ LearnerTorch = R6Class("LearnerTorch", return(model) }, .predict = function(task) { + private$.verify_predict_task(task) # FIXME: https://github.com/mlr-org/mlr3/issues/946 # This addresses the issues with the facto lrvels and is only a temporary fix # Should be handled outside of mlr3torch @@ -308,6 +291,17 @@ LearnerTorch = R6Class("LearnerTorch", .callbacks = NULL, .verify_train_task = function(task, row_ids) { first_row = task$head(1) + pv = self$param_set$values + measures = c(normalize_to_list(pv$measures_train), normalize_to_list(pv$measures_valid)) + available_predict_types = mlr_reflections$learner_predict_types[[self$task_type]][[self$predict_type]] + walk(measures, function(m) { + if (m$predict_type %nin% available_predict_types) { + stopf(paste0("Measure '%s' requires predict type '%s' but learner has '%s'.\n", + "Change the predict type or select other measures."), + m$id, m$predict_type, self$predict_type) + } + }) + iwalk(first_row, function(x, nm) { if (!is_lazy_tensor(x)) return(NULL) predict_shape = dd(x)$pointer_shape_predict diff --git a/R/learner_torch_methods.R b/R/learner_torch_methods.R index a37ae29b..ea12700e 100644 --- a/R/learner_torch_methods.R +++ b/R/learner_torch_methods.R @@ -60,15 +60,6 @@ learner_torch_train = function(self, private, super, task, param_vals) { NULL } - available_predict_types = mlr_reflections$learner_predict_types[[self$task_type]][[self$predict_type]] - - walk(c(measures_train, measures_valid), function(m) { - if (m$predict_type %nin% available_predict_types) { - stopf("Measure '%s' requires predict type '%s' but learner has '%s'.\n Change the predict type or select other measures.", # nolint - m$id, m$predict_type, self$predict_type) - } - }) - ctx = ContextTorch$new( learner = self, diff --git a/R/task_dataset.R b/R/task_dataset.R index 50137d1f..f71b1e3a 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -100,7 +100,7 @@ merge_lazy_tensor_graphs = function(lts) { names_lts = names(lts) # we only attempt to merge preprocessing graphs that have the same dataset_hash - groups = map_chr(lts, function(lt) digest::digest(dd(lt)$dataset_hash)) + groups = map_chr(lts, function(lt) dd(lt)$dataset_hash) lts = unlist(map(unique(groups), function(group) { merge_compatible_lazy_tensor_graphs(lts[, names_lts[groups == group], with = FALSE]) }), recursive = FALSE) diff --git a/man-roxygen/preprocess_torchvision.R b/man-roxygen/preprocess_torchvision.R index d2a7b287..9a85ec3b 100644 --- a/man-roxygen/preprocess_torchvision.R +++ b/man-roxygen/preprocess_torchvision.R @@ -7,7 +7,7 @@ #' @format [`R6Class`] inheriting from [`PipeOpTaskPreprocTorch`]. #' #' @description -#' Calls [`<%= paste0("torchvision::",gsub("^(augment|trafo)", "transform", id)) %>`], +#' Calls [`<%= paste0("torchvision::", gsub("^(augment|trafo)", "transform", id)) %>`], #' see there for more information on the parameters. #' <%= if (pipeop$rowwise) "The preprocessing is applied row wise (no batch dimension)." else "The preprocessing is applied to the whole batch."%> #' diff --git a/man/mlr_learners.alexnet.Rd b/man/mlr_learners.alexnet.Rd index 542b69ec..c477ef17 100644 --- a/man/mlr_learners.alexnet.Rd +++ b/man/mlr_learners.alexnet.Rd @@ -79,12 +79,12 @@ Other Learner: }} diff --git a/man/mlr_learners.mlp.Rd b/man/mlr_learners.mlp.Rd index b0d79ac3..d443563b 100644 --- a/man/mlr_learners.mlp.Rd +++ b/man/mlr_learners.mlp.Rd @@ -107,12 +107,12 @@ Other Learner: }} diff --git a/man/mlr_learners.torch_featureless.Rd b/man/mlr_learners.torch_featureless.Rd index e80fd342..aaaea71f 100644 --- a/man/mlr_learners.torch_featureless.Rd +++ b/man/mlr_learners.torch_featureless.Rd @@ -96,12 +96,12 @@ Other Learner: }} diff --git a/man/mlr_learners_torch.Rd b/man/mlr_learners_torch.Rd index 90058129..55d72e08 100644 --- a/man/mlr_learners_torch.Rd +++ b/man/mlr_learners_torch.Rd @@ -124,18 +124,18 @@ Shortcut for \code{learner$model$callbacks$history}.} \item \href{#method-LearnerTorch-new}{\code{LearnerTorch$new()}} \item \href{#method-LearnerTorch-format}{\code{LearnerTorch$format()}} \item \href{#method-LearnerTorch-print}{\code{LearnerTorch$print()}} -\item \href{#method-LearnerTorch-train}{\code{LearnerTorch$train()}} -\item \href{#method-LearnerTorch-predict}{\code{LearnerTorch$predict()}} \item \href{#method-LearnerTorch-clone}{\code{LearnerTorch$clone()}} } } \if{html}{\out{ -
Inherited methods +
Inherited methods
}} @@ -250,51 +250,6 @@ Currently unused.} } } \if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-LearnerTorch-train}{}}} -\subsection{Method \code{train()}}{ -Train the learner. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{LearnerTorch$train(task, row_ids = NULL)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{task}}{(\code{\link{Task}})\cr -The task.} - -\item{\code{row_ids}}{(\code{integer()})\cr -Which rows to use for training.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-LearnerTorch-predict}{}}} -\subsection{Method \code{predict()}}{ -Predict on a task. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{LearnerTorch$predict(task, row_ids = NULL)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{task}}{(\code{\link{Task}})\cr -The task.} - -\item{\code{row_ids}}{(\code{integer()})\cr -The rows for which to make predictions.} -} -\if{html}{\out{
}} -} -\subsection{Returns}{ -(\code{\link{Prediction}}) -} -} -\if{html}{\out{
}} \if{html}{\out{}} \if{latex}{\out{\hypertarget{method-LearnerTorch-clone}{}}} \subsection{Method \code{clone()}}{ diff --git a/man/mlr_learners_torch_image.Rd b/man/mlr_learners_torch_image.Rd index a9a9ad17..033e94a5 100644 --- a/man/mlr_learners_torch_image.Rd +++ b/man/mlr_learners_torch_image.Rd @@ -56,12 +56,12 @@ Other Learner:
}} diff --git a/man/mlr_learners_torch_model.Rd b/man/mlr_learners_torch_model.Rd index 82732583..55076a0a 100644 --- a/man/mlr_learners_torch_model.Rd +++ b/man/mlr_learners_torch_model.Rd @@ -78,12 +78,12 @@ Other Graph Network: }} From ad25184c66560e660d1d8775ebc1345ed62bd4c0 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Mon, 22 Jan 2024 20:16:32 +0100 Subject: [PATCH 27/90] specify hash input --- DESCRIPTION | 1 + NAMESPACE | 1 + R/LearnerTorch.R | 2 +- R/lazy_tensor.R | 10 ++++++++++ man/mlr_tasks_lazy_iris.Rd | 10 +--------- tests/testthat/test_LearnerTorch.R | 21 ++++++--------------- 6 files changed, 20 insertions(+), 25 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 662e8819..3e6893f9 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -65,6 +65,7 @@ Suggests: Remotes: r-lib/zip, mlr-org/mlr3, + mlr-org/mlr3misc@feat/custom-hash-info, mlr-org/mlr3pipelines@feat/keep_results, mlverse/torchvision Config/testthat/edition: 3 diff --git a/NAMESPACE b/NAMESPACE index b58ba052..f466be13 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -27,6 +27,7 @@ S3method(as_torch_optimizer,torch_optimizer_generator) S3method(c,lazy_tensor) S3method(col_info,DataBackendLazy) S3method(format,lazy_tensor) +S3method(hash_input,lazy_tensor) S3method(materialize,data.frame) S3method(materialize,lazy_tensor) S3method(materialize,list) diff --git a/R/LearnerTorch.R b/R/LearnerTorch.R index 760f9423..c3577c5d 100644 --- a/R/LearnerTorch.R +++ b/R/LearnerTorch.R @@ -310,7 +310,7 @@ LearnerTorch = R6Class("LearnerTorch", return(NULL) } if (!isTRUE(all.equal(train_shape, predict_shape))) { - stopf("Lazy tensor column '%s' would have a different shape during training (%s) and prediction (%s).", + stopf("Lazy tensor column '%s' has a different shape during training (%s) and prediction (%s).", nm, paste0(train_shape, collapse = "x"), paste0(predict_shape, collapse = "x")) } }) diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index d9e4563a..6a6ce06f 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -245,3 +245,13 @@ transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { new_lazy_tensor(data_descriptor, map_int(lt, 1)) } + +#' @export +hash_input.lazy_tensor = function(x) { + # When the DataBackend calculates the hash of, this function is called + if (length(x)) { + list(map(x, 1L), dd(x)$hash) + } else { + list() + } +} diff --git a/man/mlr_tasks_lazy_iris.Rd b/man/mlr_tasks_lazy_iris.Rd index 3dd7ee28..fa9fbc0a 100644 --- a/man/mlr_tasks_lazy_iris.Rd +++ b/man/mlr_tasks_lazy_iris.Rd @@ -22,15 +22,7 @@ Just like the iris task, but the features are represented as one lazy tensor col \section{Meta Information}{ -\itemize{ -\item Task type: \dQuote{classif} -\item Properties: \dQuote{multiclass} -\item Has Missings: no -\item Target: \dQuote{Species} -\item Features: \dQuote{x} -\item Backend Dimension: 150x3 -\item Default Roles (use / test / holdout): 150, 0, 0 -} +\verb{r rd_info_task_torch("lazy_iris", missings = FALSE)} } \examples{ diff --git a/tests/testthat/test_LearnerTorch.R b/tests/testthat/test_LearnerTorch.R index 8fc74e95..a20a53e5 100644 --- a/tests/testthat/test_LearnerTorch.R +++ b/tests/testthat/test_LearnerTorch.R @@ -396,23 +396,14 @@ test_that("Input verification works during `$train()` (train-predict shapes work # fallback learner cannot help in this case! learner$fallback = lrn("classif.featureless") - expect_error( - learner$train(task_invalid), - "would have a different shape during" - ) - - expect_error( - learner$train(task_valid), - NA - ) + rr_faulty = resample(task_invalid, learner, rsmp("holdout")) + expect_true(nrow(rr_faulty$errors) == 1L) + rr1 = resample(task, learner, rsmp("holdout")) + expect_true(nrow(rr1$errors) == 0L) task_unknown = po("trafo_resize", size = c(10, 10), stages = "train") $train(list(nano_dogs_vs_cats()))[[1L]] - - expect_error( - learner$train(task_unknown), - NA - ) - + rr2 = resample(task_unknown, learner, rsmp("holdout")) + expect_true(nrow(rr2$errors) == 0L) }) test_that("Input verification works during `$predict()` (same column info, problematic fct -> int conversion)", { From 559ade72269af95e7bbffe4e88306341419c28a0 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 09:24:52 +0100 Subject: [PATCH 28/90] fixes --- R/task_dataset.R | 19 ++++++++++++------- man/mlr_tasks_lazy_iris.Rd | 10 +++++++++- pkgdown/_pkgdown.yml | 4 ---- tests/testthat/test_PipeOpTaskPreprocTorch.R | 2 +- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/R/task_dataset.R b/R/task_dataset.R index f71b1e3a..e78cfb3a 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -109,11 +109,16 @@ merge_lazy_tensor_graphs = function(lts) { } merge_compatible_lazy_tensor_graphs = function(lts) { + # all inputs have the same dataset (makes data-loading easier) graph = Reduce(merge_graphs, map(lts, function(x) dd(x)$graph)) + # now we need to calculate the new input map, some of the graphs that were merged have different, + # others the same input pipeops, input_map = Reduce(c, map(lts, function(lt) { set_names(list(dd(lt)$input_map), dd(lt)$graph$input$name) })) + # all input pipeops that share IDs must be identical and hence receive the same data, + # therefore we can remove duplicates input_map = input_map[unique(names(input_map))] input_map = unname(unlist(input_map[graph$input$name])) @@ -138,13 +143,13 @@ merge_compatible_lazy_tensor_graphs = function(lts) { } data_descriptor = DataDescriptor$new( - dataset = dd(lts[[1]])$dataset, - dataset_shapes = dd(lts[[1L]])$dataset_shapes, - graph = graph, - input_map = dd(lts[[1]])$input_map, - pointer = pointer, - pointer_shape = dd(lt)$pointer_shape, - pointer_shape_predict = dd(lt)$pointer_shape_predict, + dataset = dd(lts[[1]])$dataset, # all are the same + dataset_shapes = dd(lts[[1L]])$dataset_shapes, # all are the same + graph = graph, # was merged + input_map = input_map, # was merged + pointer = pointer, # is set per lt + pointer_shape = dd(lt)$pointer_shape, # is set per lt but unused anyway + pointer_shape_predict = dd(lt)$pointer_shape_predict, # is set per lt clone_graph = FALSE ) new_lazy_tensor(data_descriptor, map_int(lt, 1L)) diff --git a/man/mlr_tasks_lazy_iris.Rd b/man/mlr_tasks_lazy_iris.Rd index fa9fbc0a..3dd7ee28 100644 --- a/man/mlr_tasks_lazy_iris.Rd +++ b/man/mlr_tasks_lazy_iris.Rd @@ -22,7 +22,15 @@ Just like the iris task, but the features are represented as one lazy tensor col \section{Meta Information}{ -\verb{r rd_info_task_torch("lazy_iris", missings = FALSE)} +\itemize{ +\item Task type: \dQuote{classif} +\item Properties: \dQuote{multiclass} +\item Has Missings: no +\item Target: \dQuote{Species} +\item Features: \dQuote{x} +\item Backend Dimension: 150x3 +\item Default Roles (use / test / holdout): 150, 0, 0 +} } \examples{ diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index 2a08a8a7..99c0a9b4 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -44,7 +44,3 @@ articles: navbar: ~ contents: - get_started -- title: Neural Networks as Graphs - navbar: ~ - contents: - - pipeop_torch diff --git a/tests/testthat/test_PipeOpTaskPreprocTorch.R b/tests/testthat/test_PipeOpTaskPreprocTorch.R index db5d8a88..1ad33f9a 100644 --- a/tests/testthat/test_PipeOpTaskPreprocTorch.R +++ b/tests/testthat/test_PipeOpTaskPreprocTorch.R @@ -246,5 +246,5 @@ test_that("predict shapes are added during training", { po("torch_loss", "cross_entropy") %>>% po("torch_model_classif", batch_size = 150L, epochs = 1L) - expect_error(graph$train(task), "would have a different shape") + expect_error(graph$train(task), "has a different shape") }) From 6990a2b578ea334627ba2140b0be90dd8a7878d9 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 10:20:41 +0100 Subject: [PATCH 29/90] ... --- R/DataDescriptor.R | 51 ++++++++++++++++++++++--------- man/DataDescriptor.Rd | 4 +-- man/mlr_tasks_lazy_iris.Rd | 10 +----- tests/testthat/test_lazy_tensor.R | 2 +- 4 files changed, 40 insertions(+), 27 deletions(-) diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index 157f2ede..ca2b9b32 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -16,8 +16,8 @@ #' indicate the batch dimension. #' @param graph ([`Graph`])\cr #' The preprocessing graph. -#' If left `NULL`, no preprocessing is applied to the data and `input_map`, `pointer` and `pointer_shape` -#' are inferred in case the dataset returns only one element. +#' If left `NULL`, no preprocessing is applied to the data and `input_map`, `pointer`, `pointer_shape`, and +#' `pointer_shape_predict` are inferred in case the dataset returns only one element. #' @param input_map (`character()`)\cr #' Character vector that must have the same length as the input of the graph. #' Specifies how the data from the `dataset` is fed into the preprocessing graph. @@ -81,29 +81,50 @@ DataDescriptor = R6Class("DataDescriptor", } }) } - if (is.null(graph)) { - if ((length(dataset_shapes) == 1L) && is.null(input_map)) { + # avoid name conflcts + if (is.null(input_map)) { + assert_true(length(dataset_shapes) == 1L) input_map = names(dataset_shapes) - } else { - assert_true(length(input_map) == 1L) - assert_subset(input_map, names(dataset_shapes)) } - - graph = as_graph(po("nop", id = paste0(class(dataset)[[1L]], "_", input_map))) - pointer = c(graph$output$op.id, graph$output$channel.name) - pointer_shape = dataset_shapes[[input_map]] + # get unique ID for input PipeOp + graph = as_graph(po("nop", id = + paste0("nop.", calculate_hash(address(dataset)), ".", input_map) + )) } else { graph = as_graph(graph, clone = clone_graph) assert_true(length(graph$pipeops) >= 1L) - assert_true(!is.null(input_map)) + } + # no preprocessing, dataset returns only a single element (there we can infer a lot) + simple_case = length(graph$pipeops) == 1L && inherits(graph$pipeops[[1L]], "PipeOpNOP") && + length(dataset_shapes) == 1L + + if (is.null(input_map) && simple_case) { + input_map = names(dataset_shapes) + } else { + assert_subset(input_map, names(dataset_shapes)) + } + if (is.null(pointer) && simple_case) { + pointer = c(graph$output$op.id, graph$output$channel.name) + } else { assert_choice(pointer[[1]], names(graph$pipeops)) assert_choice(pointer[[2]], graph$pipeops[[pointer[[1]]]]$output$name) - assert_subset(paste0(pointer, collapse = "."), graph$output$name) + } + if (is.null(pointer_shape) && simple_case) { + pointer_shape = dataset_shapes[[1L]] + } else { assert_shape(pointer_shape, null_ok = TRUE) - assert_subset(input_map, names(dataset_shapes)) - assert_true(length(input_map) == length(graph$input$name)) } + if (is.null(pointer_shape_predict) && simple_case) { + pointer_shape_predict = pointer_shape + } else if (simple_case) { + assert_true(isTRUE(all.equal(pointer_shape, pointer_shape_predict))) + } else { + assert_shape(pointer_shape_predict, null_ok = TRUE) + } + + assert_subset(paste0(pointer, collapse = "."), graph$output$name) + assert_true(length(input_map) == length(graph$input$name)) # We hash the address of the environment, because the hashes of an environment are not stable, # even with a .dataset (that should usually not really have a state), hashes might change due to byte-code diff --git a/man/DataDescriptor.Rd b/man/DataDescriptor.Rd index 5d015f5f..e64dad92 100644 --- a/man/DataDescriptor.Rd +++ b/man/DataDescriptor.Rd @@ -104,8 +104,8 @@ indicate the batch dimension.} \item{\code{graph}}{(\code{\link{Graph}})\cr The preprocessing graph. -If left \code{NULL}, no preprocessing is applied to the data and \code{input_map}, \code{pointer} and \code{pointer_shape} -are inferred in case the dataset returns only one element.} +If left \code{NULL}, no preprocessing is applied to the data and \code{input_map}, \code{pointer}, \code{pointer_shape}, and +\code{pointer_shape_predict} are inferred in case the dataset returns only one element.} \item{\code{input_map}}{(\code{character()})\cr Character vector that must have the same length as the input of the graph. diff --git a/man/mlr_tasks_lazy_iris.Rd b/man/mlr_tasks_lazy_iris.Rd index 3dd7ee28..fa9fbc0a 100644 --- a/man/mlr_tasks_lazy_iris.Rd +++ b/man/mlr_tasks_lazy_iris.Rd @@ -22,15 +22,7 @@ Just like the iris task, but the features are represented as one lazy tensor col \section{Meta Information}{ -\itemize{ -\item Task type: \dQuote{classif} -\item Properties: \dQuote{multiclass} -\item Has Missings: no -\item Target: \dQuote{Species} -\item Features: \dQuote{x} -\item Backend Dimension: 150x3 -\item Default Roles (use / test / holdout): 150, 0, 0 -} +\verb{r rd_info_task_torch("lazy_iris", missings = FALSE)} } \examples{ diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index 891936fc..9018fccc 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -74,7 +74,7 @@ test_that("transform_lazy_tensor works", { dd1 = dd(lt1) expect_equal(dd1$graph$edges, - data.table(src_id = "dataset_x", src_channel = "output", dst_id = "mod", dst_channel = "input") + data.table(src_id = dd1$graph$input$op.id, src_channel = "output", dst_id = "mod", dst_channel = "input") ) dd = dd(lt) From a60abb61075275f8e55d04d8c0ae1f6bc1b34c92 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 10:36:09 +0100 Subject: [PATCH 30/90] ... --- R/DataDescriptor.R | 8 ++-- R/LearnerTorch.R | 89 +++++++++++++++++++------------------- man/DataDescriptor.Rd | 4 +- man/mlr_learners_torch.Rd | 3 ++ man/mlr_tasks_lazy_iris.Rd | 10 ++++- 5 files changed, 63 insertions(+), 51 deletions(-) diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index ca2b9b32..ece97899 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -56,12 +56,12 @@ DataDescriptor = R6Class("DataDescriptor", initialize = function(dataset, dataset_shapes, graph = NULL, input_map = NULL, pointer = NULL, pointer_shape = NULL, pointer_shape_predict = NULL, clone_graph = TRUE) { assert_class(dataset, "dataset") + assert_flag(clone_graph) # If the dataset implements a .getbatch() method the shape must be specified, as it should be the same for # all batches # For simplicity we here require the first dimension of the shape to be NA so we don't have to deal with it, # e.g. during subsetting assert_shapes(dataset_shapes, null_ok = is.null(dataset$.getbatch), unknown_batch = TRUE, named = TRUE) - assert_shape(pointer_shape_predict, null_ok = TRUE, unknown_batch = TRUE) # prevent user from e.g. forgetting to wrap the return in a list example = if (is.null(dataset$.getbatch)) { @@ -82,7 +82,7 @@ DataDescriptor = R6Class("DataDescriptor", }) } if (is.null(graph)) { - # avoid name conflcts + # avoid name conflicts if (is.null(input_map)) { assert_true(length(dataset_shapes) == 1L) input_map = names(dataset_shapes) @@ -170,10 +170,10 @@ DataDescriptor = R6Class("DataDescriptor", #' @field input_map (`character()`)\cr #' The input map from the dataset to the preprocessing graph. input_map = NULL, - #' @field pointer (`character(2)` | `NULL`)\cr + #' @field pointer (`character(2)`)\cr #' The output pointer. pointer = NULL, - #' @field pointer_shape (`integer` | `NULL`)\cr + #' @field pointer_shape (`integer()` | `NULL`)\cr #' The shape of the output indicated by `pointer`. pointer_shape = NULL, #' @field dataset_hash (`character(1)`)\cr diff --git a/R/LearnerTorch.R b/R/LearnerTorch.R index c3577c5d..5114f00c 100644 --- a/R/LearnerTorch.R +++ b/R/LearnerTorch.R @@ -80,6 +80,9 @@ #' or `"cb."`, as these are preserved for the dynamically constructed parameters of the optimizer, the loss function, #' and the callbacks. #' +#' To perform additional input checks on the task, the private `.verify_train_task(task, param_vals)` and +#' `.verify_predict_task(task, param_vals)` can be overwritten. +#' #' @family Learner #' @export LearnerTorch = R6Class("LearnerTorch", @@ -237,8 +240,32 @@ LearnerTorch = R6Class("LearnerTorch", ), private = list( .train = function(task) { - private$.verify_train_task(task) param_vals = self$param_set$get_values(tags = "train") + first_row = task$head(1) + measures = c(normalize_to_list(param_vals$measures_train), normalize_to_list(param_vals$measures_valid)) + available_predict_types = mlr_reflections$learner_predict_types[[self$task_type]][[self$predict_type]] + walk(measures, function(m) { + if (m$predict_type %nin% available_predict_types) { + stopf(paste0("Measure '%s' requires predict type '%s' but learner has '%s'.\n", + "Change the predict type or select other measures."), + m$id, m$predict_type, self$predict_type) + } + }) + + iwalk(first_row, function(x, nm) { + if (!is_lazy_tensor(x)) return(NULL) + predict_shape = dd(x)$pointer_shape_predict + train_shape = dd(x)$pointer_shape + if (is.null(train_shape) || is.null(predict_shape)) { + return(NULL) + } + if (!isTRUE(all.equal(train_shape, predict_shape))) { + stopf("Lazy tensor column '%s' has a different shape during training (%s) and prediction (%s).", + nm, paste0(train_shape, collapse = "x"), paste0(predict_shape, collapse = "x")) + } + }) + private$.verify_train_task(task, param_vals) + param_vals$device = auto_device(param_vals$device) if (param_vals$seed == "random") param_vals$seed = sample.int(10000000L, 1L) @@ -249,13 +276,26 @@ LearnerTorch = R6Class("LearnerTorch", return(model) }, .predict = function(task) { - private$.verify_predict_task(task) + cols = c(task$feature_names, task$target_names) + ci_predict = task$col_info[get("id") %in% cols, c("id", "type", "levels")] + ci_train = self$model$task_col_info[get("id") %in% cols, c("id", "type", "levels")] + # permuted factor levels cause issues, because we are converting fct -> int + if (!test_equal_col_info(ci_train, ci_predict)) { # nolint + stopf(paste0( + "Predict task's column info does not match the train task's column info.\n", + "This migth be handled more gracefully in the future.\n", + "Training column info:\n'%s'\n", + "Prediction column info:\n'%s'"), + paste0(capture.output(ci_train), collapse = "\n"), + paste0(capture.output(ci_predict), collapse = "\n")) + } + param_vals = self$param_set$get_values(tags = "predict") + private$.verify_predict_task(task, param_vals) # FIXME: https://github.com/mlr-org/mlr3/issues/946 # This addresses the issues with the facto lrvels and is only a temporary fix # Should be handled outside of mlr3torch # Ideally we could rely on state$train_task, but there is this bug # https://github.com/mlr-org/mlr3/issues/947 - param_vals = self$param_set$get_values(tags = "predict") param_vals$device = auto_device(param_vals$device) with_torch_settings(seed = self$model$seed, num_threads = param_vals$num_threads, { @@ -289,47 +329,8 @@ LearnerTorch = R6Class("LearnerTorch", .loss = NULL, .param_set_base = NULL, .callbacks = NULL, - .verify_train_task = function(task, row_ids) { - first_row = task$head(1) - pv = self$param_set$values - measures = c(normalize_to_list(pv$measures_train), normalize_to_list(pv$measures_valid)) - available_predict_types = mlr_reflections$learner_predict_types[[self$task_type]][[self$predict_type]] - walk(measures, function(m) { - if (m$predict_type %nin% available_predict_types) { - stopf(paste0("Measure '%s' requires predict type '%s' but learner has '%s'.\n", - "Change the predict type or select other measures."), - m$id, m$predict_type, self$predict_type) - } - }) - - iwalk(first_row, function(x, nm) { - if (!is_lazy_tensor(x)) return(NULL) - predict_shape = dd(x)$pointer_shape_predict - train_shape = dd(x)$pointer_shape - if (is.null(train_shape) || is.null(predict_shape)) { - return(NULL) - } - if (!isTRUE(all.equal(train_shape, predict_shape))) { - stopf("Lazy tensor column '%s' has a different shape during training (%s) and prediction (%s).", - nm, paste0(train_shape, collapse = "x"), paste0(predict_shape, collapse = "x")) - } - }) - }, - .verify_predict_task = function(task, row_ids) { - cols = c(task$feature_names, task$target_names) - ci_predict = task$col_info[get("id") %in% cols, c("id", "type", "levels")] - ci_train = self$model$task_col_info[get("id") %in% cols, c("id", "type", "levels")] - # permuted factor levels cause issues, because we are converting fct -> int - if (!test_equal_col_info(ci_train, ci_predict)) { # nolint - stopf(paste0( - "Predict task's `$col_info` does not match the train task's column info.\n", - "This migth be handled more gracefully in the future.\n", - "Training column info:\n'%s'\n", - "Prediction column info:\n'%s'"), - paste0(capture.output(ci_train), collapse = "\n"), - paste0(capture.output(ci_predict), collapse = "\n")) - } - }, + .verify_train_task = function(task, param_vals) NULL, + .verify_predict_task = function(task, param_vals) NULL, deep_clone = function(name, value) deep_clone(self, private, super, name, value) ) ) diff --git a/man/DataDescriptor.Rd b/man/DataDescriptor.Rd index e64dad92..3eab4374 100644 --- a/man/DataDescriptor.Rd +++ b/man/DataDescriptor.Rd @@ -44,10 +44,10 @@ The shapes of the output.} \item{\code{input_map}}{(\code{character()})\cr The input map from the dataset to the preprocessing graph.} -\item{\code{pointer}}{(\code{character(2)} | \code{NULL})\cr +\item{\code{pointer}}{(\code{character(2)})\cr The output pointer.} -\item{\code{pointer_shape}}{(\code{integer} | \code{NULL})\cr +\item{\code{pointer_shape}}{(\code{integer()} | \code{NULL})\cr The shape of the output indicated by \code{pointer}.} \item{\code{dataset_hash}}{(\code{character(1)})\cr diff --git a/man/mlr_learners_torch.Rd b/man/mlr_learners_torch.Rd index 55d72e08..e447cd5d 100644 --- a/man/mlr_learners_torch.Rd +++ b/man/mlr_learners_torch.Rd @@ -90,6 +90,9 @@ While it is possible to add parameters by specifying the \code{param_set} constr not possible to remove existing parameters, i.e. those listed in section \emph{Parameters}. None of the parameters provided in \code{param_set} can have an id that starts with \code{"loss."}, \verb{"opt.", or }"cb."`, as these are preserved for the dynamically constructed parameters of the optimizer, the loss function, and the callbacks. + +To perform additional input checks on the task, the private \code{.verify_train_task(task, param_vals)} and +\code{.verify_predict_task(task, param_vals)} can be overwritten. } \seealso{ diff --git a/man/mlr_tasks_lazy_iris.Rd b/man/mlr_tasks_lazy_iris.Rd index fa9fbc0a..3dd7ee28 100644 --- a/man/mlr_tasks_lazy_iris.Rd +++ b/man/mlr_tasks_lazy_iris.Rd @@ -22,7 +22,15 @@ Just like the iris task, but the features are represented as one lazy tensor col \section{Meta Information}{ -\verb{r rd_info_task_torch("lazy_iris", missings = FALSE)} +\itemize{ +\item Task type: \dQuote{classif} +\item Properties: \dQuote{multiclass} +\item Has Missings: no +\item Target: \dQuote{Species} +\item Features: \dQuote{x} +\item Backend Dimension: 150x3 +\item Default Roles (use / test / holdout): 150, 0, 0 +} } \examples{ From 75a7274b4911e3fda669f0305ecd7023e07be297 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 11:29:41 +0100 Subject: [PATCH 31/90] fixes --- R/LearnerTorch.R | 4 +-- R/LearnerTorchImage.R | 2 +- R/PipeOpModule.R | 10 +++--- R/PipeOpTorch.R | 16 +++------- R/PipeOpTorchIngress.R | 9 +++--- R/TaskClassif_lazy_iris.R | 2 +- R/TaskClassif_mnist.R | 2 +- R/bibentries.R | 2 +- R/lazy_tensor.R | 42 ++++++++++++++------------ R/nn_graph.R | 3 +- R/preprocess.R | 2 -- R/shape.R | 9 ++---- man/as_lazy_tensor.Rd | 4 +-- man/assert_shape.Rd | 3 +- man/lazy_tensor.Rd | 2 +- man/mlr_pipeops_torch.Rd | 2 +- man/mlr_pipeops_torch_ingress_ltnsr.Rd | 4 +-- man/mlr_tasks_lazy_iris.Rd | 2 +- man/mlr_tasks_mnist.Rd | 2 +- man/nn_graph.Rd | 2 +- tests/testthat/test_lazy_tensor.R | 3 ++ 21 files changed, 58 insertions(+), 69 deletions(-) diff --git a/R/LearnerTorch.R b/R/LearnerTorch.R index 5114f00c..1afe78f2 100644 --- a/R/LearnerTorch.R +++ b/R/LearnerTorch.R @@ -292,9 +292,9 @@ LearnerTorch = R6Class("LearnerTorch", param_vals = self$param_set$get_values(tags = "predict") private$.verify_predict_task(task, param_vals) # FIXME: https://github.com/mlr-org/mlr3/issues/946 - # This addresses the issues with the facto lrvels and is only a temporary fix + # This addresses the issues with the factor levels and is only a temporary fix # Should be handled outside of mlr3torch - # Ideally we could rely on state$train_task, but there is this bug + # Ideally we could rely on state$train_task, but there is this complication # https://github.com/mlr-org/mlr3/issues/947 param_vals$device = auto_device(param_vals$device) diff --git a/R/LearnerTorchImage.R b/R/LearnerTorchImage.R index 024c66b6..70c2a229 100644 --- a/R/LearnerTorchImage.R +++ b/R/LearnerTorchImage.R @@ -70,7 +70,7 @@ LearnerTorchImage = R6Class("LearnerTorchImage", } ), private = list( - .verify_train_task = function(task, row_ids) { + .verify_train_task = function(task, param_vals) { if (length(task$feature_names) != 1L || !identical(task$feature_types$type, "lazy_tensor")) { stopf("Must have exactly one feature of type lazy_tensor.") } diff --git a/R/PipeOpModule.R b/R/PipeOpModule.R index a2670b0a..0de7e8f5 100644 --- a/R/PipeOpModule.R +++ b/R/PipeOpModule.R @@ -84,7 +84,7 @@ #' po_add1$train(input)$output PipeOpModule = R6Class("PipeOpModule", inherit = PipeOp, - # this has no effect because parent class is cloneable, waiting for new R6 release + # FIXME: this has no effect because parent class is cloneable, waiting for new R6 release cloneable = FALSE, public = list( #' @field module ([`nn_module`])\cr @@ -105,7 +105,7 @@ PipeOpModule = R6Class("PipeOpModule", initialize = function(id = "module", module = nn_identity(), inname = "input", outname = "output", param_vals = list(), packages = character(0)) { private$.multi_output = length(outname) > 1L - self$module = assert(check_class(module, "nn_module"), check_class(module, "function"), combine = "or") + assert(check_class(module, "nn_module"), check_class(module, "function"), combine = "or") self$module = module packages = union(c("mlr3torch", "torch"), packages) @@ -145,10 +145,8 @@ PipeOpModule = R6Class("PipeOpModule", list(fn_input, self$input$name, self$output$name, self$packages) }, deep_clone = function(name, value) { - # Waiting for R6 release: https://github.com/r-lib/R6/commit/6ba0dce26b1a7fc9b812bc4d92f09123d3b9648d - stopf("Cannot create a deep clone of PipeOpModule if it wraps an `nn_module`.") - # Note that we could allow to clone methods that wrap functions, but this should basically never be necessary, - # as this PipeOp has not state and just functions as a function + # FIXME: We can implement this, when https://github.com/mlverse/torch/issues/1126 is solved + stopf("Cannot create a deep clone of PipeOpModule.") } ) ) diff --git a/R/PipeOpTorch.R b/R/PipeOpTorch.R index 65d9439d..9988493e 100644 --- a/R/PipeOpTorch.R +++ b/R/PipeOpTorch.R @@ -181,7 +181,7 @@ #' task1 = task$clone()$select(paste0("Sepal.", c("Length", "Width"))) #' task2 = task$clone()$select(paste0("Petal.", c("Length", "Width"))) #' graph = gunion(list(po("torch_ingress_num_1"), po("torch_ingress_num_2"))) -#' mds_in = graph$train( list(task1, task2), single_input = FALSE) +#' mds_in = graph$train(list(task1, task2), single_input = FALSE) #' #' mds_in[[1L]][c("graph", "task", "ingress", "pointer", "pointer_shape")] #' mds_in[[2L]][c("graph", "task", "ingress", "pointer", "pointer_shape")] @@ -221,7 +221,7 @@ #' identical(tasks_out[[1L]], tasks_out[[2L]]) PipeOpTorch = R6Class("PipeOpTorch", inherit = PipeOp, - # this has no effect because parent class is cloneable, waiting for new R6 release + # FIXME: this has no effect because parent class is cloneable, waiting for new R6 release cloneable = FALSE, public = list( #' @field module_generator (`nn_module_generator` or `NULL`)\cr @@ -286,21 +286,13 @@ PipeOpTorch = R6Class("PipeOpTorch", shapes_out = function(shapes_in, task = NULL) { assert_r6(task, "Task", null.ok = TRUE) if (is.numeric(shapes_in)) shapes_in = list(shapes_in) - # batch dimensionc can be known or unknown + # batch dimension can be known or unknown assert_shapes(shapes_in, unknown_batch = NULL) if ("..." %nin% self$input$name) { assert_true(length(shapes_in) == nrow(self$input), .var.name = "number of input shapes equal to number of input channels") } - - s = if (is.null(private$.shapes_out)) { - shapes_in - } else { - pv = self$param_set$get_values() - private$.shapes_out(shapes_in, pv, task = task) - } - - set_names(s, self$output$name) + set_names(private$.shapes_out(shapes_in, self$param_set$get_values(), task = task), self$output$name) } # TODO: printer that calls the nn_module's printer diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index 401c74e4..9b0506e5 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -270,7 +270,7 @@ register_po("torch_ingress_categ", PipeOpTorchIngressCategorical) #' @section Parameters: #' * `shape` :: `integer()`\cr #' The shape of the tensor, where the first dimension (batch) must be `NA`. -#' Whether it is necessary to specify the shape depends on whether the lazy tensor input column has a known shape. +#' When it is not specified, the lazy tensor input column needs to have a known shape. #' #' @section Internals: #' The returned batchgetter materializes the lazy tensor column to a tensor. @@ -285,7 +285,7 @@ register_po("torch_ingress_categ", PipeOpTorchIngressCategorical) #' md = po_ingress$train(list(task))[[1L]] #' #' ingress = md$ingress -#' x_batch = ingress[[1L]]$batchgetter( data = task$data(1, "x"), device = "cpu", cache = NULL) +#' x_batch = ingress[[1L]]$batchgetter(data = task$data(1, "x"), device = "cpu", cache = NULL) #' x_batch #' #' # Now we try a lazy tensor with unknown shape, i.e. the shapes between the rows can differ @@ -329,9 +329,10 @@ PipeOpTorchIngressLazyTensor = R6Class("PipeOpTorchIngressLazyTensor", #' @template params_pipelines initialize = function(id = "torch_ingress_ltnsr", param_vals = list()) { param_set = ps( - shape = p_uty(tags = "train", custom_check = crate( - function(x) check_shape(x, null_ok = FALSE, unknown_batch = TRUE), .parent = topenv())) + shape = p_uty(tags = "train", default = NULL, custom_check = crate( + function(x) check_shape(x, null_ok = TRUE, unknown_batch = TRUE), .parent = topenv())) ) + param_set$set_values(shape = NULL) super$initialize(id = id, param_vals = param_vals, feature_types = "lazy_tensor", param_set = param_set) } ), diff --git a/R/TaskClassif_lazy_iris.R b/R/TaskClassif_lazy_iris.R index 2e7ca8c7..7419ad01 100644 --- a/R/TaskClassif_lazy_iris.R +++ b/R/TaskClassif_lazy_iris.R @@ -2,7 +2,7 @@ #' #' @name mlr_tasks_lazy_iris #' -#' @format [R6::R6Class] inheriting from [TaskClassif]. +#' @format [R6::R6Class] inheriting from [mlr3::TaskClassif]. #' @include zzz.R #' #' @description diff --git a/R/TaskClassif_mnist.R b/R/TaskClassif_mnist.R index 4e3303dc..23db18ae 100644 --- a/R/TaskClassif_mnist.R +++ b/R/TaskClassif_mnist.R @@ -1,7 +1,7 @@ #' @title MNIST Image classification #' @name mlr_tasks_mnist #' @description -#' Classical MNIST image classification. +#' Classic MNIST image classification. #' #' The underlying [`DataBackend`] contains columns `"label"`, `"image"`, `"row_id"`, `"split"`, where the last column #' indicates whether the row belongs to the train or test set. diff --git a/R/bibentries.R b/R/bibentries.R index 452e87e7..80174531 100644 --- a/R/bibentries.R +++ b/R/bibentries.R @@ -1,4 +1,4 @@ -bibentries = c( # nolint start +bibentries = c(# nolint start gorishniy2021revisiting = bibentry("article", title = "Revisiting Deep Learning Models for Tabular Data", author = "Yury Gorishniy and Ivan Rubachev and Valentin Khrulkov and Artem Babenko", diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index 6a6ce06f..dbf0b846 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -5,7 +5,7 @@ #' @param data_descriptor ([`DataDescriptor`] or `NULL`)\cr #' The data descriptor or `NULL` for a lazy tensor of length 0. #' @param ids (`integer()`)\cr -#' The elements of the `data_descriptor` that the created lazy tensor contains. +#' The elements of the `data_descriptor` to be included in the lazy tensor. #' @include DataDescriptor.R #' @export lazy_tensor = function(data_descriptor = NULL, ids = NULL) { @@ -25,14 +25,7 @@ lazy_tensor = function(data_descriptor = NULL, ids = NULL) { new_lazy_tensor = function(data_descriptor, ids) { - # previously, only the id was included and not the hash - # this led to issues with stuff like unlist(), which dropped attribute and suddenly the lazy_tensor column - # was a simple integer vector. (this caused stuff like PipeOpFeatureUnion to go havock and lead to bugs) - # For this reason, we now also include the hash of the data_descriptor - # We can then later also use this to support different DataDescriptors in a single lazy tensor column - - # Note that we just include the hash as an attribute, so c() does not allow to combine lazy tensors whose - # data descriptors have different hashes. + # don't use attributes for data_descriptor, because R will drop it when you don't expect it structure(map(ids, function(id) list(id, data_descriptor)), class = c("lazy_tensor", "list")) } @@ -50,7 +43,15 @@ new_lazy_tensor = function(data_descriptor, ids) { `[<-.lazy_tensor` = function(x, i, value) { assert_true(is_lazy_tensor(value)) # no compatibility check - if (length(x) == 0) return(NextMethod()) + if (length(x) == 0) { + x = unclass(x) + x[i] = value + return(structure(x, class = c("lazy_tensor", "list"))) + } + if (length(value) == 0L) { + assert_true(length(i) == 0L) + return(x) + } assert_true(identical(dd(x)$hash, dd(value)$hash)) x = unclass(x) x[i] = value @@ -60,8 +61,9 @@ new_lazy_tensor = function(data_descriptor, ids) { #' @export `[[<-.lazy_tensor` = function(x, i, value) { assert_true(is_lazy_tensor(value)) - # no compatibility check - if (length(x) == 0) return(NextMethod()) + assert_true(length(value) == 1L) + assert_true(length(i) == 1L) + assert_true(length(x) >= 1L) assert_true(identical(dd(x)$hash), dd(value)$hash) x = unclass(x) x[[i]] = value @@ -116,9 +118,9 @@ dd = function(x) { #' @title Convert to lazy tensor #' @description -#' Convert a object to a [`lazy_tensor()`]. +#' Convert a object to a [`lazy_tensor`]. #' @param x (any)\cr -#' Object to convert to a [`lazy_tensor()`] +#' Object to convert to a [`lazy_tensor`] #' @param ... (any)\cr #' Additional arguments passed to the method. #' @export @@ -181,9 +183,9 @@ is_lazy_tensor = function(x) { #' The pipeop to be added to the preprocessing graph(s) of the lazy tensor. #' Must have one input and one output. #' Is not cloned, so should be cloned beforehand. -#' @param shape (`integer()`)\cr +#' @param shape (`integer()` or `NULL`)\cr #' The shape of the lazy tensor. -#' @param shape_predict (`integer()`)\cr +#' @param shape_predict (`integer()` or `NULL`)\cr #' The shape of the lazy tensor if it was applied during `$predict()`. #' #' @details @@ -193,9 +195,8 @@ is_lazy_tensor = function(x) { #' [`DataDescriptor`]. #' 1. The `pointer` of the [`DataDescriptor`] is updated to point to the new output channel of the `pipeop`. #' 1. The `pointer_shape` of the [`DataDescriptor`] set to the provided `shape`. -#' 1. The `hash` of the [`DataDescriptor`] is updated. -#' Input must be PipeOpModule with exactly one input and one output -#' shape must be shape with NA in first dimension +#' 1. The `pointer_shape_predict` of the [`DataDescriptor`] set to the provided `shape_predict`. +#' 1. A new [`DataDescriptor`] is created #' #' @return [`lazy_tensor`] #' @examples @@ -213,6 +214,7 @@ is_lazy_tensor = function(x) { transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { assert_lazy_tensor(lt) assert_class(pipeop, "PipeOpModule") + # keep it simple for now assert_true(nrow(pipeop$input) == 1L) assert_true(nrow(pipeop$output) == 1L) assert_shape(shape, null_ok = TRUE, unknown_batch = TRUE) @@ -240,7 +242,7 @@ transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { pointer = c(pipeop$id, pipeop$output$name), pointer_shape = shape, pointer_shape_predict = shape_predict, - clone_graph = FALSE + clone_graph = FALSE # graph was already cloned ) new_lazy_tensor(data_descriptor, map_int(lt, 1)) diff --git a/R/nn_graph.R b/R/nn_graph.R index 444f5503..0a89cf54 100644 --- a/R/nn_graph.R +++ b/R/nn_graph.R @@ -4,7 +4,7 @@ #' Represents a neural network using a [`Graph`] that usually costains mostly [`PipeOpModule`]s. #' #' @param graph ([`Graph`][mlr3pipelines::Graph])\cr -#' The [`Graph`][mlr3pipelines::Graph] to wrap. +#' The [`Graph`][mlr3pipelines::Graph] to wrap. Is **not** cloned. #' @param shapes_in (named `integer`)\cr #' Shape info of tensors that go into `graph`. Names must be `graph$input$name`, possibly in different order. #' @param output_map (`character`)\cr @@ -35,7 +35,6 @@ nn_graph = nn_module( self$graph_input_name = graph$input$name # cache this, it is expensive # we do NOT verify the input and type of the graph to be `"torch_tensor"`. - # The reason for this is that the graph, when constructed with the PipeOpTorch Machinery, contains PipeOpNOPs, # which have input and output type *. diff --git a/R/preprocess.R b/R/preprocess.R index 85bac91e..59af348d 100644 --- a/R/preprocess.R +++ b/R/preprocess.R @@ -1,8 +1,6 @@ #' @rawNamespace exportPattern("^PipeOpPreprocTorch") NULL -# FIXME: Better docs, not one for all - #' @template preprocess_torchvision #' @templateVar id trafo_resize register_preproc("trafo_resize", torchvision::transform_resize, diff --git a/R/shape.R b/R/shape.R index ac9f7965..3afe0bb9 100644 --- a/R/shape.R +++ b/R/shape.R @@ -1,5 +1,6 @@ +#' @title Check for Shape #' -#' Checks whether an integer vector is a valid shape. +#' @description Checks whether an integer vector is a valid shape. #' Unknown shapes are represted as `NULL`. #' #' @param shape (`integer()`)\cr @@ -10,6 +11,7 @@ #' @param unknown_batch (`logical(1)`)\cr #' Whether the batch **must** be unknonw, i.e. `NA`. #' If left `NULL` (default), the first dimension can be `NA` or not. +#' @noRd assert_shape = function(shape, null_ok = FALSE, coerce = TRUE, unknown_batch = NULL) { result = check_shape(shape, null_ok = null_ok, unknown_batch = unknown_batch) @@ -22,11 +24,6 @@ assert_shape = function(shape, null_ok = FALSE, coerce = TRUE, unknown_batch = N } -#FIX SHAPE IN FIRST DIM: -# * should not happen for DataDescriptor (subsetting) -# * should not be possible in ModelDescriptor (makes no sense) -# * still, shapes_out() should also handle this case - test_shape = function(shape, null_ok = FALSE, unknown_batch = NULL) { if (is.null(shape) && null_ok) { return(TRUE) diff --git a/man/as_lazy_tensor.Rd b/man/as_lazy_tensor.Rd index 95c17cf1..5452ab75 100644 --- a/man/as_lazy_tensor.Rd +++ b/man/as_lazy_tensor.Rd @@ -8,11 +8,11 @@ as_lazy_tensor(x, ...) } \arguments{ \item{x}{(any)\cr -Object to convert to a \code{\link[=lazy_tensor]{lazy_tensor()}}} +Object to convert to a \code{\link{lazy_tensor}}} \item{...}{(any)\cr Additional arguments passed to the method.} } \description{ -Convert a object to a \code{\link[=lazy_tensor]{lazy_tensor()}}. +Convert a object to a \code{\link{lazy_tensor}}. } diff --git a/man/assert_shape.Rd b/man/assert_shape.Rd index 8a8ebb07..e15592db 100644 --- a/man/assert_shape.Rd +++ b/man/assert_shape.Rd @@ -2,8 +2,7 @@ % Please edit documentation in R/shape.R \name{assert_shape} \alias{assert_shape} -\title{Checks whether an integer vector is a valid shape. -Unknown shapes are represted as \code{NULL}.} +\title{Check for Shape} \usage{ assert_shape(shape, null_ok = FALSE, coerce = TRUE, unknown_batch = NULL) } diff --git a/man/lazy_tensor.Rd b/man/lazy_tensor.Rd index 640aeef9..556439ae 100644 --- a/man/lazy_tensor.Rd +++ b/man/lazy_tensor.Rd @@ -11,7 +11,7 @@ lazy_tensor(data_descriptor = NULL, ids = NULL) The data descriptor or \code{NULL} for a lazy tensor of length 0.} \item{ids}{(\code{integer()})\cr -The elements of the \code{data_descriptor} that the created lazy tensor contains.} +The elements of the \code{data_descriptor} to be included in the lazy tensor.} } \description{ Create a lazy tensor. diff --git a/man/mlr_pipeops_torch.Rd b/man/mlr_pipeops_torch.Rd index f0308fc6..b1e3900e 100644 --- a/man/mlr_pipeops_torch.Rd +++ b/man/mlr_pipeops_torch.Rd @@ -191,7 +191,7 @@ task = tsk("iris") task1 = task$clone()$select(paste0("Sepal.", c("Length", "Width"))) task2 = task$clone()$select(paste0("Petal.", c("Length", "Width"))) graph = gunion(list(po("torch_ingress_num_1"), po("torch_ingress_num_2"))) -mds_in = graph$train( list(task1, task2), single_input = FALSE) +mds_in = graph$train(list(task1, task2), single_input = FALSE) mds_in[[1L]][c("graph", "task", "ingress", "pointer", "pointer_shape")] mds_in[[2L]][c("graph", "task", "ingress", "pointer", "pointer_shape")] diff --git a/man/mlr_pipeops_torch_ingress_ltnsr.Rd b/man/mlr_pipeops_torch_ingress_ltnsr.Rd index b6900f8f..a893cd20 100644 --- a/man/mlr_pipeops_torch_ingress_ltnsr.Rd +++ b/man/mlr_pipeops_torch_ingress_ltnsr.Rd @@ -12,7 +12,7 @@ Ingress for a single \code{\link{lazy_tensor}} column. \itemize{ \item \code{shape} :: \code{integer()}\cr The shape of the tensor, where the first dimension (batch) must be \code{NA}. -Whether it is necessary to specify the shape depends on whether the lazy tensor input column has a known shape. +When it is not specified, the lazy tensor input column needs to have a known shape. } } @@ -39,7 +39,7 @@ task = tsk("lazy_iris") md = po_ingress$train(list(task))[[1L]] ingress = md$ingress -x_batch = ingress[[1L]]$batchgetter( data = task$data(1, "x"), device = "cpu", cache = NULL) +x_batch = ingress[[1L]]$batchgetter(data = task$data(1, "x"), device = "cpu", cache = NULL) x_batch # Now we try a lazy tensor with unknown shape, i.e. the shapes between the rows can differ diff --git a/man/mlr_tasks_lazy_iris.Rd b/man/mlr_tasks_lazy_iris.Rd index 3dd7ee28..a35a9b4c 100644 --- a/man/mlr_tasks_lazy_iris.Rd +++ b/man/mlr_tasks_lazy_iris.Rd @@ -4,7 +4,7 @@ \alias{mlr_tasks_lazy_iris} \title{Iris Classification Task} \format{ -\link[R6:R6Class]{R6::R6Class} inheriting from \link{TaskClassif}. +\link[R6:R6Class]{R6::R6Class} inheriting from \link[mlr3:TaskClassif]{mlr3::TaskClassif}. } \source{ \url{https://en.wikipedia.org/wiki/Iris_flower_data_set} diff --git a/man/mlr_tasks_mnist.Rd b/man/mlr_tasks_mnist.Rd index edaa44e5..27d81b63 100644 --- a/man/mlr_tasks_mnist.Rd +++ b/man/mlr_tasks_mnist.Rd @@ -7,7 +7,7 @@ \url{https://torchvision.mlverse.org/reference/mnist_dataset.html} } \description{ -Classical MNIST image classification. +Classic MNIST image classification. The underlying \code{\link{DataBackend}} contains columns \code{"label"}, \code{"image"}, \code{"row_id"}, \code{"split"}, where the last column indicates whether the row belongs to the train or test set. diff --git a/man/nn_graph.Rd b/man/nn_graph.Rd index 4c7818da..3c077185 100644 --- a/man/nn_graph.Rd +++ b/man/nn_graph.Rd @@ -8,7 +8,7 @@ nn_graph(graph, shapes_in, output_map = graph$output$name, list_output = FALSE) } \arguments{ \item{graph}{(\code{\link[mlr3pipelines:Graph]{Graph}})\cr -The \code{\link[mlr3pipelines:Graph]{Graph}} to wrap.} +The \code{\link[mlr3pipelines:Graph]{Graph}} to wrap. Is \strong{not} cloned.} \item{shapes_in}{(named \code{integer})\cr Shape info of tensors that go into \code{graph}. Names must be \code{graph$input$name}, possibly in different order.} diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index 9018fccc..8581ffa4 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -51,6 +51,9 @@ test_that("lazy_tensor works", { expect_error(is.null(dd(lt1_empty))) expect_class(lt1_empty, "lazy_tensor") + lt1_empty[1] = lt1[1] + expect_class(lt1_empty, "lazy_tensor") + expect_error(materialize(lazy_tensor()), "Cannot materialize") }) From 60e14e8a38ac6cc3b059adc4a9ba13166db6bbb7 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 12:45:30 +0100 Subject: [PATCH 32/90] Update R/PipeOpTaskPreprocTorch.R --- R/PipeOpTaskPreprocTorch.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index f3ec9d80..e9f7d064 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -392,7 +392,7 @@ pipeop_preproc_torch = function(id, fn, shapes_out = NULL, param_set = NULL, par create_ps = function(fn) { fmls = formals(fn) param_names = names(fmls) - # we assume the firs argument is for the tensor + # we assume the first argument is for the tensor param_names = setdiff(param_names[-1L], "...") fmls = fmls[param_names] is_required = map_lgl(fmls, function(x) identical(x, alist(x = )$x)) From 0af2f7a77ae6727a5c453ddb70702dc00574352b Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 12:45:41 +0100 Subject: [PATCH 33/90] Update R/PipeOpTaskPreprocTorch.R --- R/PipeOpTaskPreprocTorch.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index e9f7d064..2d39f25f 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -29,7 +29,7 @@ #' @template param_id #' @template param_param_vals #' @param fn (`function` or `character(2)`)\cr -#' The preprocessing function. Should not modify its input in-place. +#' The preprocessing function. Must not modify its input in-place. #' If it is a `character(2)`, the first element should be the namespace and thje second element the name. #' @param packages (`character()`)\cr #' The packages the preprocessing function depends on. From 1570059b4a53b2b7dc4cd73962ee62ab6dce0950 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 12:45:48 +0100 Subject: [PATCH 34/90] Update R/PipeOpTaskPreprocTorch.R --- R/PipeOpTaskPreprocTorch.R | 1 + 1 file changed, 1 insertion(+) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 2d39f25f..a3f52cda 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -421,6 +421,7 @@ create_ps = function(fn) { #' If "infer", the output shape function is inferred and calculates the output shapes as follows: #' For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is #' applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. +#' If the first dimension is not `NA`, the output shape of applying the preprocessing function is returned. #' #' This should be correct in most cases, but might fail in some edge cases. #' @param param_set ([`ParamSet`] or `NULL`)\cr From d097126722f5f0e8287d7b3d229559879ddf6ecd Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 12:45:54 +0100 Subject: [PATCH 35/90] Update R/PipeOpTaskPreprocTorch.R --- R/PipeOpTaskPreprocTorch.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index a3f52cda..aa0f3ee3 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -30,7 +30,7 @@ #' @template param_param_vals #' @param fn (`function` or `character(2)`)\cr #' The preprocessing function. Must not modify its input in-place. -#' If it is a `character(2)`, the first element should be the namespace and thje second element the name. +#' If it is a `character(2)`, the first element should be the namespace and the second element the name. #' @param packages (`character()`)\cr #' The packages the preprocessing function depends on. #' @param param_set ([`ParamSet`])\cr From b87bfc26971a13993b6907a68f8b872c2939f827 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 12:46:05 +0100 Subject: [PATCH 36/90] Update R/PipeOpTaskPreprocTorch.R --- R/PipeOpTaskPreprocTorch.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index aa0f3ee3..2f487bda 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -36,7 +36,7 @@ #' @param param_set ([`ParamSet`])\cr #' In case the function `fn` takes additional parameter besides a [`torch_tensor`] they can be #' specfied as parameters. None of the parameters can have the `"predict"` tag. -#' All tags should be set to `"train"`. +#' All tags should include `"train"`. #' @param stages_init (`logical(1)`)\cr #' Initial value for the `stages` parameter. #' @param rowwise (`logical(1)`)\cr From e33dc1af85662ca98a7a2aa820dc482c821fb375 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 12:46:18 +0100 Subject: [PATCH 37/90] Update R/PipeOpTaskPreprocTorch.R --- R/PipeOpTaskPreprocTorch.R | 1 - 1 file changed, 1 deletion(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 2f487bda..7e819448 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -57,7 +57,6 @@ #' Can be one of `"train"`, `"predict"` or `"both"`. #' The initial value of this parameter is set to `"train"` when the `PipeOp`'s id starts with `"augment_"` and #' to `"both"` otherwise. -#' o #' Note that the preprocessing that is applied during `$predict()` uses the parameters that were set during #' `$train()` and not those that are set when performing the prediction. #' From 9dc507c5283f486625d87978d923e359df350aac Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 12:46:25 +0100 Subject: [PATCH 38/90] Update R/PipeOpTaskPreprocTorch.R --- R/PipeOpTaskPreprocTorch.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 7e819448..c10eb911 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -427,7 +427,7 @@ create_ps = function(fn) { #' The parameter set. #' If this is left as `NULL` (default) the parameter set is inferred in the following way: #' All parameters but the first and `...` of `fn` are set as untyped parameters with tags 'train' and those that -#' have nod default value are tagged as 'required' as well. +#' have no default value are tagged as 'required' as well. #' Default values are not annotated. #' @param parent_env (`environment`)\cr #' The parent environment for the R6 class. From fbe093f091902a1d300f0b3bfa36292fb55a7ea5 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 12:46:37 +0100 Subject: [PATCH 39/90] Update R/PipeOpTaskPreprocTorch.R --- R/PipeOpTaskPreprocTorch.R | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index c10eb911..e44d5d38 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -399,7 +399,11 @@ create_ps = function(fn) { args = list() args = set_names(map(param_names, function(pn) { - p_uty(tags = if (is_required[pn]) c("train", "required") else "train") + if (is_required[pn]) { + p_uty(tags = c("train", "required")) + } else { + p_uty(default = "", tags = "train") + } }), param_names) invoke(ps, .args = args) From cf380e80146cdb662f2e96d7b2e6357df1988a4d Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 12:46:51 +0100 Subject: [PATCH 40/90] Update R/PipeOpTaskPreprocTorch.R --- R/PipeOpTaskPreprocTorch.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index e44d5d38..5dba87d7 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -74,7 +74,7 @@ #' Then, two branches are created `B -> C` and `B -> D`, creating two preprocessing graphs #' `A -> B -> C` and `A -> B -> D`. When loading the data, we want to run the preprocessing only once, i.e. we don't #' want to run the `A -> B` part twice. For this reason, [`task_dataset()`] will try to merge graphs and cache -#' results from graphs. +#' results from graphs. However, only graphs using the same dataset can currently be merged. #' #' Also, the shapes created during `$train()` and `$predict()` might differ. #' To avoid the creation of graphs where the predict shapes are incompatible with the train shapes, From c44d63c58238b936515e3d74bcaf530b83a5b9fd Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 12:47:04 +0100 Subject: [PATCH 41/90] Update R/PipeOpTaskPreprocTorch.R --- R/PipeOpTaskPreprocTorch.R | 1 - 1 file changed, 1 deletion(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 5dba87d7..d95b55ae 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -181,7 +181,6 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", assert(check_function(fn), check_character(fn, len = 2L)) private$.fn = fn private$.rowwise = assert_flag(rowwise) - param_set = assert_param_set(param_set$clone(deep = TRUE)) param_set$add(ps( From c9f912aa097fcdbf82fcf2d026d80a5e7f202b89 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 12:47:14 +0100 Subject: [PATCH 42/90] Update R/PipeOpTaskPreprocTorch.R --- R/PipeOpTaskPreprocTorch.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index d95b55ae..e913aed9 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -204,7 +204,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' @param shapes_in (`list()` of (`integer()` or `NULL`))\cr #' The input input shapes of the lazy tensors. #' `NULL` indicates that the shape is unknown. - #' First dimension must be `NA`. + #' First dimension must be `NA` (if it is not `NULL`). #' @param stage (`character(1)`)\cr #' The stage: either `"train"` or `"predict"`. #' @param task ([`Task`] or `NULL`)\cr From 6f661a827e985db37e5b222cb01c26147bd9972e Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 12:47:24 +0100 Subject: [PATCH 43/90] Update R/PipeOpTaskPreprocTorch.R --- R/PipeOpTaskPreprocTorch.R | 1 - 1 file changed, 1 deletion(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index e913aed9..94e48a37 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -216,7 +216,6 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", stopf("Predict shapes can only be calculated after training the PipeOp.") } assert_r6(task, "Task", null.ok = TRUE) - # either all shapes are NULL or none are NULL assert_shapes(shapes_in, named = FALSE, null_ok = TRUE) names(shapes_in) = NULL From 47d8e17c9122860584987d6e146f87508ebd9a0e Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 12:47:39 +0100 Subject: [PATCH 44/90] Update R/PipeOpTaskPreprocTorch.R --- R/PipeOpTaskPreprocTorch.R | 1 + 1 file changed, 1 insertion(+) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 94e48a37..e7b6974a 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -360,6 +360,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", formals(self$fn), body(self$fn), address(environment(self$fn)) ) }, + # Default is the most conservative variant, i.e. unknown shapes. .shapes_out = function(shapes_in, param_vals, task) list(NULL), .fn = NULL ) From 0b4ea03139e2a4382865c90a0bbc4aac7db82484 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 12:48:05 +0100 Subject: [PATCH 45/90] stages_init --- R/PipeOpTaskPreprocTorch.R | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index e7b6974a..0ca0cd95 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -176,8 +176,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", public = list( #' @description #' Creates a new instance of this [`R6`][R6::R6Class] class. - initialize = function(fn, id = "preproc_torch", param_vals = list(), param_set = ps(), packages = character(0), - stages_init = "both", rowwise = FALSE) { # nolint + initialize = function(fn, id = "preproc_torch", param_vals = list(), param_set = ps(), packages = character(0), rowwise = FALSE) { # nolint assert(check_function(fn), check_character(fn, len = 2L)) private$.fn = fn private$.rowwise = assert_flag(rowwise) @@ -374,7 +373,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' The parameter values. #' @export pipeop_preproc_torch = function(id, fn, shapes_out = NULL, param_set = NULL, param_vals = list(), packages = character(0), - rowwise = FALSE, parent_env = parent.frame()) { + rowwise = FALSE, parent_env = parent.frame(), stages_init = NULL) { pipeop_preproc_torch_class( id = id, fn = fn, @@ -382,7 +381,8 @@ pipeop_preproc_torch = function(id, fn, shapes_out = NULL, param_set = NULL, par param_set = param_set, packages = packages, rowwise = rowwise, - parent_env = parent_env + parent_env = parent_env, + stages_init = stages_init )$new(param_vals = param_vals) } @@ -436,8 +436,11 @@ create_ps = function(fn) { #' The parent environment for the R6 class. #' @param rowwise (`logical(1)`)\cr #' Whether the preprocessing is applied row-wise. -#' @param init_params (name `list()`)\cr -#' List containing initial parameter values. +#' @param stages_init (`character(1)`)\cr +#' Initial value for the `stages` parameter. +#' If `NULL` (default), will be set to `"both"` in case the `id` starts with `"trafo"` and to `"train"` +#' if it starts with `"augment"`. Otherwise it must specified. +#' @param #' @template param_packages #' @export #' @returns An [`R6Class`][R6::R6Class] instance inheriting from [`PipeOpTaskPreprocTorch`] @@ -446,12 +449,22 @@ create_ps = function(fn) { #' po_example #' po_example$param_set pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, packages = character(0), - init_params = list(), rowwise = FALSE, parent_env = parent.frame()) { + rowwise = FALSE, parent_env = parent.frame(), stages_init = NULL) { assert( check_function(shapes_out, args = c("shapes_in", "param_vals", "task"), null.ok = TRUE), check_choice(shapes_out, c("infer", "unchanged")) ) + if (is.null(stages_init)) { + stages_init = if (startsWith(id, "trafo_")) { + "both" + } else if (startsWith(id, "augment_")) { + "train" + } else { + stopf("stages_init must be specified") + } + } + # we e.g. want torchvision in suggests, so we cannot already access the function. if (identical(shapes_out, "infer")) { shapes_out = crate(function(shapes_in, param_vals, task) { @@ -480,8 +493,6 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack list(sout) }) - # FIXME: NSE issues, we need to evaluate fn in the proper environment, - # I guess we can use this quosure idea that } else if (identical(shapes_out, "unchanged")) { shapes_out = crate(function(shapes_in, param_vals, task_in) shapes_in) } else if (is.function(shapes_out) || is.null(shapes_out)) { @@ -506,7 +517,6 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack } else { param_set = info$param_set$clone(deep = TRUE) } - param_set$values = info$init_params # nolint super$initialize( id = id, packages = info$packages, @@ -523,16 +533,13 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack formals(init_fun)$id = id classname = paste0("PipeOpPreprocTorch", paste0(capitalize(strsplit(id, split = "_")[[1L]]), collapse = "")) - # Note that we don't set default values - private = list( .__construction_info = list( packages = packages, param_set = param_set, fn = fn, rowwise = rowwise, - stages_init = stages_init, - init_params = init_params + stages_init = stages_init ) ) From 3911966e49d7436a3e1b8ed072091081ee7c2842 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 13:15:14 +0100 Subject: [PATCH 46/90] Update R/PipeOpTaskPreprocTorch.R --- R/PipeOpTaskPreprocTorch.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 0ca0cd95..b5ec0887 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -37,7 +37,7 @@ #' In case the function `fn` takes additional parameter besides a [`torch_tensor`] they can be #' specfied as parameters. None of the parameters can have the `"predict"` tag. #' All tags should include `"train"`. -#' @param stages_init (`logical(1)`)\cr +#' @param stages_init (`character(1)`)\cr #' Initial value for the `stages` parameter. #' @param rowwise (`logical(1)`)\cr #' Whether the preprocessing function is applied rowwise (and then concatenated by row) or directly to the whole From 560e9ee2de0d87af1979cb7758a9e93058a7d380 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 13:15:20 +0100 Subject: [PATCH 47/90] Update R/PipeOpTorchIngress.R --- R/PipeOpTorchIngress.R | 1 - 1 file changed, 1 deletion(-) diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index 9b0506e5..c088b32c 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -332,7 +332,6 @@ PipeOpTorchIngressLazyTensor = R6Class("PipeOpTorchIngressLazyTensor", shape = p_uty(tags = "train", default = NULL, custom_check = crate( function(x) check_shape(x, null_ok = TRUE, unknown_batch = TRUE), .parent = topenv())) ) - param_set$set_values(shape = NULL) super$initialize(id = id, param_vals = param_vals, feature_types = "lazy_tensor", param_set = param_set) } ), From 0f98936d5150b6a152678dfa3d23a27d40659ef3 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 13:15:28 +0100 Subject: [PATCH 48/90] Update R/shape.R --- R/shape.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/shape.R b/R/shape.R index 3afe0bb9..4b5bdc36 100644 --- a/R/shape.R +++ b/R/shape.R @@ -48,7 +48,7 @@ check_shape = function(shape, null_ok = FALSE, unknown_batch = NULL) { if (test_shape(shape, null_ok = null_ok, unknown_batch = unknown_batch)) { return(TRUE) } - stopf("Invalid shape: %s.", paste0(format(shape), collapse = ", ")) + sprintf("Invalid shape: %s.", paste0(format(shape), collapse = ", ")) } assert_shapes = function(shapes, coerce = TRUE, named = FALSE, null_ok = FALSE, unknown_batch = NULL) { # nolint ok = test_list(shapes, names = if (named && !identical(unique(names(shapes)), "...")) "unique", min.len = 1L) From ed6b014bf4e6643ecbc9f8eddf9fe2e745f79a28 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 13:15:34 +0100 Subject: [PATCH 49/90] Update R/shape.R --- R/shape.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/shape.R b/R/shape.R index 4b5bdc36..ad98a28b 100644 --- a/R/shape.R +++ b/R/shape.R @@ -28,7 +28,7 @@ test_shape = function(shape, null_ok = FALSE, unknown_batch = NULL) { if (is.null(shape) && null_ok) { return(TRUE) } - ok = test_integerish(shape, min.len = 2L, all.missing = TRUE) + ok = test_integerish(shape, min.len = 2L, all.missing = FALSE, any.missing = TRUE) if (!ok) { return(FALSE) From 9b2b1e4becf7b2c7f7a3ea9c903f636c1e1e914a Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 13:32:42 +0100 Subject: [PATCH 50/90] ... --- R/PipeOpTaskPreprocTorch.R | 6 ++--- R/shape.R | 5 +++- R/task_dataset.R | 13 +++------- man/assert_shape.Rd | 25 -------------------- man/mlr_pipeops_preproc_torch.Rd | 21 ++++++++-------- man/pipeop_preproc_torch.Rd | 11 +++++++-- man/pipeop_preproc_torch_class.Rd | 15 +++++++----- tests/testthat/test_PipeOpTaskPreprocTorch.R | 22 ++++++++++------- tests/testthat/test_materialize.R | 2 +- 9 files changed, 52 insertions(+), 68 deletions(-) delete mode 100644 man/assert_shape.Rd diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index b5ec0887..b35168d1 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -176,7 +176,8 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", public = list( #' @description #' Creates a new instance of this [`R6`][R6::R6Class] class. - initialize = function(fn, id = "preproc_torch", param_vals = list(), param_set = ps(), packages = character(0), rowwise = FALSE) { # nolint + initialize = function(fn, id = "preproc_torch", param_vals = list(), param_set = ps(), packages = character(0), rowwise = FALSE, + stages_init = NULL) { # nolint assert(check_function(fn), check_character(fn, len = 2L)) private$.fn = fn private$.rowwise = assert_flag(rowwise) @@ -440,7 +441,6 @@ create_ps = function(fn) { #' Initial value for the `stages` parameter. #' If `NULL` (default), will be set to `"both"` in case the `id` starts with `"trafo"` and to `"train"` #' if it starts with `"augment"`. Otherwise it must specified. -#' @param #' @template param_packages #' @export #' @returns An [`R6Class`][R6::R6Class] instance inheriting from [`PipeOpTaskPreprocTorch`] @@ -460,8 +460,6 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack "both" } else if (startsWith(id, "augment_")) { "train" - } else { - stopf("stages_init must be specified") } } diff --git a/R/shape.R b/R/shape.R index ad98a28b..4d983638 100644 --- a/R/shape.R +++ b/R/shape.R @@ -51,7 +51,10 @@ check_shape = function(shape, null_ok = FALSE, unknown_batch = NULL) { sprintf("Invalid shape: %s.", paste0(format(shape), collapse = ", ")) } assert_shapes = function(shapes, coerce = TRUE, named = FALSE, null_ok = FALSE, unknown_batch = NULL) { # nolint - ok = test_list(shapes, names = if (named && !identical(unique(names(shapes)), "...")) "unique", min.len = 1L) + ok = test_list(shapes, min.len = 1L) + if (named) { + assert_names(setdiff(names(shapes), "..."), type = "unique") + } if (!ok) { stopf("Invalid shape") } diff --git a/R/task_dataset.R b/R/task_dataset.R index e78cfb3a..b9b0ce72 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -61,15 +61,8 @@ task_dataset = dataset( # Here, we could have multiple `lazy_tensor` columns that share parts of the graph # We try to merge those graphs if possible if (length(lazy_tensor_features) > 1L) { - merge_result = try(merge_lazy_tensor_graphs(data), silent = TRUE) - - if (inherits(merge_result, "try-error")) { - # This should basically never happen - lg$debug("Failed to merge data descriptor, this might lead to inefficient preprocessing.") - # TODO: test that is still works when this triggers - } else { - self$task$cbind(merge_result) - } + merge_result = merge_lazy_tensor_graphs(data) + self$task$cbind(merge_result) } # we can cache the output (hash) or the data (dataset_hash) @@ -123,7 +116,7 @@ merge_compatible_lazy_tensor_graphs = function(lts) { input_map = unname(unlist(input_map[graph$input$name])) # some PipeOs that were previously terminal might not be anymore, - # for those we add nops and updaate the pointers for their data descriptors + # for those we add nops and update the pointers for their data descriptors map_dtc(lts, function(lt) { pointer_name = paste0(dd(lt)$pointer, collapse = ".") diff --git a/man/assert_shape.Rd b/man/assert_shape.Rd deleted file mode 100644 index e15592db..00000000 --- a/man/assert_shape.Rd +++ /dev/null @@ -1,25 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/shape.R -\name{assert_shape} -\alias{assert_shape} -\title{Check for Shape} -\usage{ -assert_shape(shape, null_ok = FALSE, coerce = TRUE, unknown_batch = NULL) -} -\arguments{ -\item{shape}{(\code{integer()})\cr} - -\item{null_ok}{(\code{logical(1)})\cr -Whether \code{NULL} is a valid shape.} - -\item{coerce}{(\code{logical(1)})\cr -Whether to coerce the input to an \code{integer()} if possible.} - -\item{unknown_batch}{(\code{logical(1)})\cr -Whether the batch \strong{must} be unknonw, i.e. \code{NA}. -If left \code{NULL} (default), the first dimension can be \code{NA} or not.} -} -\description{ -Checks whether an integer vector is a valid shape. -Unknown shapes are represted as \code{NULL}. -} diff --git a/man/mlr_pipeops_preproc_torch.Rd b/man/mlr_pipeops_preproc_torch.Rd index fb60fb0b..3cec742f 100644 --- a/man/mlr_pipeops_preproc_torch.Rd +++ b/man/mlr_pipeops_preproc_torch.Rd @@ -50,7 +50,6 @@ The stages during which to apply the preprocessing. Can be one of \code{"train"}, \code{"predict"} or \code{"both"}. The initial value of this parameter is set to \code{"train"} when the \code{PipeOp}'s id starts with \code{"augment_"} and to \code{"both"} otherwise. -o Note that the preprocessing that is applied during \verb{$predict()} uses the parameters that were set during \verb{$train()} and not those that are set when performing the prediction. } @@ -71,7 +70,7 @@ One lazy tensor column's preprocessing graph is \code{A -> B}. Then, two branches are created \code{B -> C} and \code{B -> D}, creating two preprocessing graphs \code{A -> B -> C} and \code{A -> B -> D}. When loading the data, we want to run the preprocessing only once, i.e. we don't want to run the \code{A -> B} part twice. For this reason, \code{\link[=task_dataset]{task_dataset()}} will try to merge graphs and cache -results from graphs. +results from graphs. However, only graphs using the same dataset can currently be merged. Also, the shapes created during \verb{$train()} and \verb{$predict()} might differ. To avoid the creation of graphs where the predict shapes are incompatible with the train shapes, @@ -210,8 +209,8 @@ Creates a new instance of this \code{\link[R6:R6Class]{R6}} class. param_vals = list(), param_set = ps(), packages = character(0), - stages_init = "both", - rowwise = FALSE + rowwise = FALSE, + stages_init = NULL )}\if{html}{\out{
}} } @@ -219,8 +218,8 @@ Creates a new instance of this \code{\link[R6:R6Class]{R6}} class. \if{html}{\out{
}} \describe{ \item{\code{fn}}{(\code{function} or \code{character(2)})\cr -The preprocessing function. Should not modify its input in-place. -If it is a \code{character(2)}, the first element should be the namespace and thje second element the name.} +The preprocessing function. Must not modify its input in-place. +If it is a \code{character(2)}, the first element should be the namespace and the second element the name.} \item{\code{id}}{(\code{character(1)})\cr The id for of the new object.} @@ -231,17 +230,17 @@ Parameter values to be set after construction.} \item{\code{param_set}}{(\code{\link{ParamSet}})\cr In case the function \code{fn} takes additional parameter besides a \code{\link{torch_tensor}} they can be specfied as parameters. None of the parameters can have the \code{"predict"} tag. -All tags should be set to \code{"train"}.} +All tags should include \code{"train"}.} \item{\code{packages}}{(\code{character()})\cr The packages the preprocessing function depends on.} -\item{\code{stages_init}}{(\code{logical(1)})\cr -Initial value for the \code{stages} parameter.} - \item{\code{rowwise}}{(\code{logical(1)})\cr Whether the preprocessing function is applied rowwise (and then concatenated by row) or directly to the whole tensor. In the first case there is no batch dimension.} + +\item{\code{stages_init}}{(\code{character(1)})\cr +Initial value for the \code{stages} parameter.} } \if{html}{\out{
}} } @@ -264,7 +263,7 @@ It uses the parameter values that are currently set. \item{\code{shapes_in}}{(\code{list()} of (\code{integer()} or \code{NULL}))\cr The input input shapes of the lazy tensors. \code{NULL} indicates that the shape is unknown. -First dimension must be \code{NA}.} +First dimension must be \code{NA} (if it is not \code{NULL}).} \item{\code{stage}}{(\code{character(1)})\cr The stage: either \code{"train"} or \code{"predict"}.} diff --git a/man/pipeop_preproc_torch.Rd b/man/pipeop_preproc_torch.Rd index d0a52d7b..060db76d 100644 --- a/man/pipeop_preproc_torch.Rd +++ b/man/pipeop_preproc_torch.Rd @@ -12,7 +12,8 @@ pipeop_preproc_torch( param_vals = list(), packages = character(0), rowwise = FALSE, - parent_env = parent.frame() + parent_env = parent.frame(), + stages_init = NULL ) } \arguments{ @@ -30,6 +31,7 @@ If \code{NULL}, the output shapes are unknown. If "infer", the output shape function is inferred and calculates the output shapes as follows: For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. +If the first dimension is not \code{NA}, the output shape of applying the preprocessing function is returned. This should be correct in most cases, but might fail in some edge cases.} @@ -37,7 +39,7 @@ This should be correct in most cases, but might fail in some edge cases.} The parameter set. If this is left as \code{NULL} (default) the parameter set is inferred in the following way: All parameters but the first and \code{...} of \code{fn} are set as untyped parameters with tags 'train' and those that -have nod default value are tagged as 'required' as well. +have no default value are tagged as 'required' as well. Default values are not annotated.} \item{param_vals}{(\code{list()})\cr @@ -51,6 +53,11 @@ Whether the preprocessing is applied row-wise.} \item{parent_env}{(\code{environment})\cr The parent environment for the R6 class.} + +\item{stages_init}{(\code{character(1)})\cr +Initial value for the \code{stages} parameter. +If \code{NULL} (default), will be set to \code{"both"} in case the \code{id} starts with \code{"trafo"} and to \code{"train"} +if it starts with \code{"augment"}. Otherwise it must specified.} } \description{ Calls \code{\link{pipeop_preproc_torch_class}} and instantiates the instance with the given parameter values. diff --git a/man/pipeop_preproc_torch_class.Rd b/man/pipeop_preproc_torch_class.Rd index 05f2bcd3..6b225fb9 100644 --- a/man/pipeop_preproc_torch_class.Rd +++ b/man/pipeop_preproc_torch_class.Rd @@ -10,9 +10,9 @@ pipeop_preproc_torch_class( shapes_out, param_set = NULL, packages = character(0), - init_params = list(), rowwise = FALSE, - parent_env = parent.frame() + parent_env = parent.frame(), + stages_init = NULL ) } \arguments{ @@ -30,6 +30,7 @@ If \code{NULL}, the output shapes are unknown. If "infer", the output shape function is inferred and calculates the output shapes as follows: For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. +If the first dimension is not \code{NA}, the output shape of applying the preprocessing function is returned. This should be correct in most cases, but might fail in some edge cases.} @@ -37,20 +38,22 @@ This should be correct in most cases, but might fail in some edge cases.} The parameter set. If this is left as \code{NULL} (default) the parameter set is inferred in the following way: All parameters but the first and \code{...} of \code{fn} are set as untyped parameters with tags 'train' and those that -have nod default value are tagged as 'required' as well. +have no default value are tagged as 'required' as well. Default values are not annotated.} \item{packages}{(\code{character()})\cr The R packages this object depends on.} -\item{init_params}{(name \code{list()})\cr -List containing initial parameter values.} - \item{rowwise}{(\code{logical(1)})\cr Whether the preprocessing is applied row-wise.} \item{parent_env}{(\code{environment})\cr The parent environment for the R6 class.} + +\item{stages_init}{(\code{character(1)})\cr +Initial value for the \code{stages} parameter. +If \code{NULL} (default), will be set to \code{"both"} in case the \code{id} starts with \code{"trafo"} and to \code{"train"} +if it starts with \code{"augment"}. Otherwise it must specified.} } \value{ An \code{\link[R6:R6Class]{R6Class}} instance inheriting from \code{\link{PipeOpTaskPreprocTorch}} diff --git a/tests/testthat/test_PipeOpTaskPreprocTorch.R b/tests/testthat/test_PipeOpTaskPreprocTorch.R index 1ad33f9a..154e4c22 100644 --- a/tests/testthat/test_PipeOpTaskPreprocTorch.R +++ b/tests/testthat/test_PipeOpTaskPreprocTorch.R @@ -1,5 +1,5 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { - po_test = po("preproc_torch", identity, packages = "R6") + po_test = po("preproc_torch", identity, packages = "R6", stages_init = "both") expect_pipeop(po_test) expect_equal(po_test$feature_types, "lazy_tensor") expect_true(po_test$innum == 1L) @@ -16,7 +16,8 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { super$initialize( id = id, param_vals = param_vals, - fn = function(x) -x + fn = function(x) -x, + stages_init = "both" ) } ), @@ -65,7 +66,8 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { param_set = param_set, id = id, param_vals = param_vals, - fn = function(x, a = 2) x * a + fn = function(x, a = 2) x * a, + stages_init = "both" ) } ) @@ -108,8 +110,12 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { # need to finish the augment -> stages transition, i.e. add tests and "both", then finish the preprocess implementation add the tests and test the preprocess autotest # also test that the rowwise parameter works - po_test3 = pipeop_preproc_torch("test3", rowwise = FALSE, fn = function(x) x$reshape(-1), shapes_out = NULL) - po_test4 = pipeop_preproc_torch("test4", rowwise = TRUE, fn = function(x) x$reshape(-1), shapes_out = NULL) + po_test3 = pipeop_preproc_torch("test3", rowwise = FALSE, fn = function(x) x$reshape(-1), shapes_out = NULL, + stages_init = "both" + ) + po_test4 = pipeop_preproc_torch("test4", rowwise = TRUE, fn = function(x) x$reshape(-1), shapes_out = NULL, + stages_init = "both" + ) expect_equal( materialize(po_test3$train(list(task))[[1L]]$data(cols = "x1")$x1, rbind = TRUE)$shape, @@ -120,8 +126,8 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { c(10, 1) ) - expect_true(pipeop_preproc_torch("test3", identity, rowwise = TRUE, shapes_out = NULL)$rowwise) - expect_false(pipeop_preproc_torch("test3", identity, rowwise = FALSE, shapes_out = NULL)$rowwise) + expect_true(pipeop_preproc_torch("test3", identity, rowwise = TRUE, shapes_out = NULL, stages_init = "both")$rowwise) + expect_false(pipeop_preproc_torch("test3", identity, rowwise = FALSE, shapes_out = NULL, stages_init = "both")$rowwise) # stages_init works }) @@ -155,7 +161,7 @@ test_that("PipeOpTaskPreprocTorch modifies the underlying lazy tensor columns co taskin = as_task_regr(d, target = "y") po_test = po("preproc_torch", fn = crate(function(x, a) x + a), param_set = ps(a = p_int(tags = c("train", "required"))), - a = -10, rowwise = FALSE) + a = -10, rowwise = FALSE, stages_init = "both") taskout_train = po_test$train(list(taskin))[[1L]] taskout_pred = po_test$predict(list(taskin))[[1L]] diff --git a/tests/testthat/test_materialize.R b/tests/testthat/test_materialize.R index 2a344115..b263eb78 100644 --- a/tests/testthat/test_materialize.R +++ b/tests/testthat/test_materialize.R @@ -155,7 +155,7 @@ test_that("PipeOpFeatureUnion can properly check whether two lazy tensors are id task = tsk("lazy_iris") graph = po("nop") %>>% - list(po("preproc_torch", function(x) x + 1), po("trafo_nop")) %>>% + list(po("preproc_torch", function(x) x + 1, stages_init = "both"), po("trafo_nop")) %>>% po("featureunion") expect_error(graph$train(task), "cannot aggregate different features sharing") From 6d80fbe5006d486d34583daee359cd6c2250e6dc Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 15:00:28 +0100 Subject: [PATCH 51/90] ... --- R/PipeOpTaskPreprocTorch.R | 5 +- R/task_dataset.R | 19 ++++--- R/zzz.R | 14 +---- man/mlr_pipeops_preproc_torch.Rd | 3 +- tests/testthat/helper_autotest.R | 1 - tests/testthat/helper_functions.R | 9 ++-- tests/testthat/test_PipeOpTaskPreprocTorch.R | 57 ++++++++++++++------ 7 files changed, 60 insertions(+), 48 deletions(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index b35168d1..b33a6347 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -147,7 +147,8 @@ #' id = id, #' packages = character(0), #' param_vals = param_vals, -#' param_set = param_set +#' param_set = param_set, +#' stages_init = "both" #' ) #' } #' ), @@ -501,8 +502,6 @@ pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, pack param_set = param_set %??% create_ps(fn) - stages_init = if (startsWith(id, "augment_")) "train" else "both" - # the .__construction info construct is used to not having to rely on NSE init_fun = crate(function(id = id, param_vals = list()) { # nolint info = private$.__construction_info diff --git a/R/task_dataset.R b/R/task_dataset.R index b9b0ce72..25fe9801 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -67,7 +67,7 @@ task_dataset = dataset( # we can cache the output (hash) or the data (dataset_hash) self$cache_lazy_tensors = length(unique(map_chr(data, function(x) dd(x)$hash))) > 1L || - length(unique(map_chr(data, function(x) dd(x)$dataset_hash))) > 1L + length(unique(map_chr(data, function(x) dd(x)$dataset_hash))) > 1L }, .getbatch = function(index) { @@ -93,9 +93,9 @@ merge_lazy_tensor_graphs = function(lts) { names_lts = names(lts) # we only attempt to merge preprocessing graphs that have the same dataset_hash - groups = map_chr(lts, function(lt) dd(lt)$dataset_hash) - lts = unlist(map(unique(groups), function(group) { - merge_compatible_lazy_tensor_graphs(lts[, names_lts[groups == group], with = FALSE]) + hashes = map_chr(lts, function(lt) dd(lt)$dataset_hash) + lts = unlist(map(unique(hashes), function(hash) { + merge_compatible_lazy_tensor_graphs(lts[, names_lts[hashes == hash], with = FALSE]) }), recursive = FALSE) as_data_backend(as.data.table(set_names(lts, names_lts))) @@ -106,7 +106,7 @@ merge_compatible_lazy_tensor_graphs = function(lts) { graph = Reduce(merge_graphs, map(lts, function(x) dd(x)$graph)) # now we need to calculate the new input map, some of the graphs that were merged have different, - # others the same input pipeops, + # others the same input pipeops input_map = Reduce(c, map(lts, function(lt) { set_names(list(dd(lt)$input_map), dd(lt)$graph$input$name) })) @@ -115,11 +115,10 @@ merge_compatible_lazy_tensor_graphs = function(lts) { input_map = input_map[unique(names(input_map))] input_map = unname(unlist(input_map[graph$input$name])) - # some PipeOs that were previously terminal might not be anymore, - # for those we add nops and update the pointers for their data descriptors map_dtc(lts, function(lt) { pointer_name = paste0(dd(lt)$pointer, collapse = ".") - + # some PipeOs that were previously terminal might not be anymore, + # for those we add nops and update the pointers for their data descriptors pointer = if (pointer_name %nin% graph$output$name) { po_terminal = po("nop", id = uniqueify(pointer_name, graph$ids())) graph$add_pipeop(po_terminal, clone = FALSE) @@ -141,9 +140,9 @@ merge_compatible_lazy_tensor_graphs = function(lts) { graph = graph, # was merged input_map = input_map, # was merged pointer = pointer, # is set per lt - pointer_shape = dd(lt)$pointer_shape, # is set per lt but unused anyway + pointer_shape = dd(lt)$pointer_shape, # is set per lt pointer_shape_predict = dd(lt)$pointer_shape_predict, # is set per lt - clone_graph = FALSE + clone_graph = FALSE # shallow clone already created above ) new_lazy_tensor(data_descriptor, map_int(lt, 1L)) }) diff --git a/R/zzz.R b/R/zzz.R index 9c408090..8f7f09e4 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -110,24 +110,13 @@ register_mlr3pipelines = function() { backports::import(pkgname, "R_user_dir", force = TRUE) # Configure Logger: - lg = lgr::get_logger(pkgname) - assign("lg", lg, envir = parent.env(environment())) - f = function(event) { - event$msg = paste0("[mlr3torch] ", event$msg) - TRUE - } - lg$set_filters(list(f)) + assign("lg", lgr::get_logger("mlr3"), envir = parent.env(environment())) if (Sys.getenv("IN_PKGDOWN") == "true") { lg$set_threshold("warn") } register_namespace_callback(pkgname, "mlr3", register_mlr3) register_namespace_callback(pkgname, "mlr3pipelines", register_mlr3pipelines) - - assign("lg", lgr::get_logger(pkgname), envir = parent.env(environment())) - if (Sys.getenv("IN_PKGDOWN") == "true") { - lg$set_threshold("warn") - } } .onUnload = function(libPaths) { # nolint @@ -140,4 +129,3 @@ register_mlr3pipelines = function() { } leanify_package() - diff --git a/man/mlr_pipeops_preproc_torch.Rd b/man/mlr_pipeops_preproc_torch.Rd index 3cec742f..0963f3b7 100644 --- a/man/mlr_pipeops_preproc_torch.Rd +++ b/man/mlr_pipeops_preproc_torch.Rd @@ -142,7 +142,8 @@ PipeOpPreprocTorchPoly = R6::R6Class("PipeOpPreprocTorchPoly", id = id, packages = character(0), param_vals = param_vals, - param_set = param_set + param_set = param_set, + stages_init = "both" ) } ), diff --git a/tests/testthat/helper_autotest.R b/tests/testthat/helper_autotest.R index 252fdf59..f3219bbf 100644 --- a/tests/testthat/helper_autotest.R +++ b/tests/testthat/helper_autotest.R @@ -179,7 +179,6 @@ collapse_char_list = function(x) { #' @title Parameter Test #' @description #' Tests that parameters are correctly implemented -#'k #' @param x ([`ParamSet`] or object with field `$param_set`)\cr #' The parameter set to check. #' @param fns (`list()` of `function`s)\cr diff --git a/tests/testthat/helper_functions.R b/tests/testthat/helper_functions.R index f5051b77..c4b26b1d 100644 --- a/tests/testthat/helper_functions.R +++ b/tests/testthat/helper_functions.R @@ -53,10 +53,11 @@ expect_deep_clone = function(one, two) { visited[[addr_a]] = path visited_b[[addr_b]] = path - # TODO: Take care of torch parameters tensors and buffers and torch optimizer and nn module etc. - - if (inherits(a, "nn_module_generator") || inherits(a, "torch_optimizer_generator") || inherits(a, "R6ClassGenerator")) { - return(invisible(NULL)) + #if (inherits(a, "nn_module_generator") || inherits(a, "torch_optimizer_generator")) { + # stopf("Not implemented yet") + #} + if (inherits(a, "R6ClassGenerator")) { + return(NULL) } # follow attributes, even for non-recursive objects diff --git a/tests/testthat/test_PipeOpTaskPreprocTorch.R b/tests/testthat/test_PipeOpTaskPreprocTorch.R index 154e4c22..c0af8e72 100644 --- a/tests/testthat/test_PipeOpTaskPreprocTorch.R +++ b/tests/testthat/test_PipeOpTaskPreprocTorch.R @@ -106,10 +106,6 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { materialize(po_test$train(list(task))[[1L]]$data(cols = "x1")[[1L]], rbind = TRUE) ) - # TODO: - # need to finish the augment -> stages transition, i.e. add tests and "both", then finish the preprocess implementation add the tests and test the preprocess autotest - # also test that the rowwise parameter works - po_test3 = pipeop_preproc_torch("test3", rowwise = FALSE, fn = function(x) x$reshape(-1), shapes_out = NULL, stages_init = "both" ) @@ -125,11 +121,26 @@ test_that("PipeOpTaskPreprocTorch: basic checks", { materialize(po_test4$train(list(task))[[1L]]$data(cols = "x1")$x1, rbind = TRUE)$shape, c(10, 1) ) +}) - expect_true(pipeop_preproc_torch("test3", identity, rowwise = TRUE, shapes_out = NULL, stages_init = "both")$rowwise) - expect_false(pipeop_preproc_torch("test3", identity, rowwise = FALSE, shapes_out = NULL, stages_init = "both")$rowwise) - - # stages_init works +test_that("rowwise works", { + task = tsk("lazy_iris") + fn_rowwise = function(x) { + expect_true(nrow(x) == 150L) + x + } + po_rowwise = pipeop_preproc_torch("test3", fn = fn_rowwise, rowwise = FALSE, shapes_out = NULL, stages_init = "both") + + taskout = po_rowwise$train(list(task))[[1L]] + expect_error(materialize(taskout$data()$x), regexp = NA) + + fn_batchwise = function(x) { + expect_true(all.equal(x$shape, 4)) + x + } + po_batchwise = pipeop_preproc_torch("test3", fn = fn_batchwise, rowwise = TRUE, shapes_out = NULL, stages_init = "both") + taskout2 = po_batchwise$train(list(task))[[1L]] + expect_error(materialize(taskout2$data()$x), regexp = NA) }) test_that("PipeOptaskPreprocTorch: shapes_out() works", { @@ -189,8 +200,7 @@ test_that("PipeOpTaskPreprocTorch modifies the underlying lazy tensor columns co test_that("pipeop_preproc_torch", { expect_error( - pipeop_preproc_torch("trafo_abc", function(x) NULL, shapes_out = function(shapes) NULL), - "Must have formal arguments" + pipeop_preproc_torch("trafo_abc", function(x) NULL, shapes_out = function(shapes) NULL) ) rowwise = sample(c(TRUE, FALSE), 1L) @@ -200,7 +210,8 @@ test_that("pipeop_preproc_torch", { s[2] = 2L s list(s) - } + }, + stages_init = "both" ) expect_true("required" %in% po_test$param_set$tags$a) @@ -224,21 +235,35 @@ test_that("pipeop_preproc_torch", { expect_torch_equal(x[1, 2]$item(), 1) po_test1 = pipeop_preproc_torch("test1", torchvision::transform_resize, shapes_out = "infer", - param_vals = list(size = c(10, 10)) + param_vals = list(size = c(10, 10)), stages_init = "both" ) size = po_test1$shapes_out(list(c(NA, 20, 20)), "train") expect_equal(size, list(c(NA, 10, 10))) + + expect_true(pipeop_preproc_torch("test3", identity, rowwise = TRUE, shapes_out = NULL, stages_init = "both")$rowwise) + expect_false(pipeop_preproc_torch("test3", identity, rowwise = FALSE, shapes_out = NULL, stages_init = "both")$rowwise) + + # stages_init works + expect_equal(pipeop_preproc_torch( + "test3", identity, rowwise = TRUE, shapes_out = NULL, stages_init = "both")$param_set$values$stages, + "both" + ) + expect_equal(pipeop_preproc_torch( + "test3", identity, rowwise = TRUE, shapes_out = NULL, stages_init = "train")$param_set$values$stages, + "train" + ) }) test_that("can pass variable to fn", { - fn = function(x) x - po_test = pipeop_preproc_torch("test", fn = fn, shapes_out = "infer") - expect_pipeop(po_test) + fn = function(x, a) x + a + po_test = pipeop_preproc_torch("test", fn = fn, shapes_out = "infer", stages_init = "train", param_vals = list(a = 1000)) + x = po_test$train(list(tsk("lazy_iris")$filter(1)))[[1L]]$data()$x + expect_true(all(as_array(materialize(x, rbind = TRUE)) >= 50)) }) test_that("predict shapes are added during training", { - fn = po_test = pipeop_preproc_torch("test", fn = function(x) torch_cat(list(x, x * 2), dim = 2), shapes_out = "infer") + po_test = pipeop_preproc_torch("test", fn = function(x) torch_cat(list(x, x * 2), dim = 2), shapes_out = "infer") po_test$param_set$set_values( stages = "train" From d13d986bc2cf2d0db2fc504d0cc88fbad15a0f36 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 17:10:55 +0100 Subject: [PATCH 52/90] address remaining issues --- R/DataDescriptor.R | 5 +- R/PipeOpTaskPreprocTorch.R | 4 +- R/materialize.R | 12 ++--- R/task_dataset.R | 5 +- R/utils.R | 4 ++ man/materialize.Rd | 3 +- tests/testthat/test_PipeOpTorchIngress.R | 1 + tests/testthat/test_autotests.R | 2 - tests/testthat/test_cache.R | 2 +- tests/testthat/test_materialize.R | 44 ++++++++++++----- tests/testthat/test_task_dataset.R | 60 ++++++++++++++++++++++-- tests/testthat/test_utils.R | 19 ++++++++ 12 files changed, 127 insertions(+), 34 deletions(-) diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index ece97899..c458835f 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -99,14 +99,15 @@ DataDescriptor = R6Class("DataDescriptor", simple_case = length(graph$pipeops) == 1L && inherits(graph$pipeops[[1L]], "PipeOpNOP") && length(dataset_shapes) == 1L - if (is.null(input_map) && simple_case) { - input_map = names(dataset_shapes) + if (is.null(input_map) && nrow(graph$input) == 1L && length(dataset_shapes) == 1L) { + input_map = names(dataset_shapes) } else { assert_subset(input_map, names(dataset_shapes)) } if (is.null(pointer) && simple_case) { pointer = c(graph$output$op.id, graph$output$channel.name) } else { + assert_character(pointer, len = 2L) assert_choice(pointer[[1]], names(graph$pipeops)) assert_choice(pointer[[2]], graph$pipeops[[pointer[[1]]]]$output$name) } diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index b33a6347..77650e3d 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -315,8 +315,8 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", } else { if (private$.rowwise) { crate(function(x) { - torch_cat(map(seq_len(nrow(x)), function(i) trafo(x[i, ..])$unsqueeze(1L)), dim = 1L) - }, trafo, .parent = topenv()) + torch_cat(mlr3misc::map(seq_len(nrow(x)), function(i) trafo(x[i, ..])$unsqueeze(1L)), dim = 1L) + }, trafo, .parent = environment(trafo)) } else { trafo } diff --git a/R/materialize.R b/R/materialize.R index a703b9b9..486d8e42 100644 --- a/R/materialize.R +++ b/R/materialize.R @@ -50,19 +50,17 @@ materialize = function(x, device = "cpu", rbind = FALSE, ...) { #' @rdname materialize #' @param cache (`character(1)` or `environment()` or `NULL`)\cr #' Optional cache for (intermediate) materialization results. -#' Per default, caching will be enabled when the same dataset / graph is used for more than one lazy tensor column. +#' Per default, caching will be enabled when the same dataset or data descriptor (with different output pointer) +#' is used for more than one lazy tensor columns. #' @export materialize.list = function(x, device = "cpu", rbind = FALSE, cache = "auto", ...) { # nolint x_lt = x[map_lgl(x, is_lazy_tensor)] assert(check_choice(cache, "auto"), check_environment(cache, null.ok = TRUE)) if (identical(cache, "auto")) { - data_hashes = map_chr(x_lt, function(x) dd(x)$dataset_hash) - hashes = map_chr(x_lt, function(x) dd(x)$hash) - cache = if (uniqueN(data_hashes) > 1L || uniqueN(hashes) > 1L) { - new.env() - } + cache = if (auto_cache_lazy_tensors(x_lt)) new.env() } + map(x, function(col) { if (is_lazy_tensor(col)) { materialize_internal(col, device = device, cache = cache, rbind = rbind) @@ -112,7 +110,7 @@ get_output = function(input, graph, varying_shapes, rbind, device) { # now we get it in the right output format and convert it to the requested device output = if (rbind) { if (varying_shapes) { # need to convert from list of tensors to tensor - output = map(output, list_to_batch) + output = map(output, function(tensors) torch_cat(tensors, dim = 1L)) } map(output, function(x) x$to(device = device)) } else { diff --git a/R/task_dataset.R b/R/task_dataset.R index 25fe9801..255aca7b 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -65,10 +65,7 @@ task_dataset = dataset( self$task$cbind(merge_result) } - # we can cache the output (hash) or the data (dataset_hash) - self$cache_lazy_tensors = length(unique(map_chr(data, function(x) dd(x)$hash))) > 1L || - length(unique(map_chr(data, function(x) dd(x)$dataset_hash))) > 1L - + self$cache_lazy_tensors = auto_cache_lazy_tensors(data) }, .getbatch = function(index) { cache = if (self$cache_lazy_tensors) new.env() diff --git a/R/utils.R b/R/utils.R index 01956025..de644bf5 100644 --- a/R/utils.R +++ b/R/utils.R @@ -206,3 +206,7 @@ dataset_image = dataset("image_dataset", list_to_batch = function(tensors) { torch_cat(map(tensors, function(x) x$unsqueeze(1)), dim = 1L) } + +auto_cache_lazy_tensors = function(lts) { + any(duplicated(map_chr(lts, function(x) dd(x)$dataset_hash))) +} diff --git a/man/materialize.Rd b/man/materialize.Rd index 53749cd0..6a0324ae 100644 --- a/man/materialize.Rd +++ b/man/materialize.Rd @@ -26,7 +26,8 @@ Additional arguments.} \item{cache}{(\code{character(1)} or \code{environment()} or \code{NULL})\cr Optional cache for (intermediate) materialization results. -Per default, caching will be enabled when the same dataset / graph is used for more than one lazy tensor column.} +Per default, caching will be enabled when the same dataset or data descriptor (with different output pointer) +is used for more than one lazy tensor columns.} } \value{ (\code{list()} of \code{\link{lazy_tensor}}s or a \code{\link{lazy_tensor}}) diff --git a/tests/testthat/test_PipeOpTorchIngress.R b/tests/testthat/test_PipeOpTorchIngress.R index 6834af15..c4855888 100644 --- a/tests/testthat/test_PipeOpTorchIngress.R +++ b/tests/testthat/test_PipeOpTorchIngress.R @@ -46,4 +46,5 @@ test_that("PipeOpTorchIngressLazyTensor", { expect_po_ingress(po_ingress, task) expect_error(po_ingress$param_set$set_values(shape = c(22, 4))) + expect_error(po_ingress$param_set$set_values(shape = c(NA, 22, 4)), regexp = NA) }) diff --git a/tests/testthat/test_autotests.R b/tests/testthat/test_autotests.R index be346ace..69cdd657 100644 --- a/tests/testthat/test_autotests.R +++ b/tests/testthat/test_autotests.R @@ -1,6 +1,4 @@ test_that("auto_paramtest works", { - # ficx - # captures missing parameters f1 = function(x, y) NULL ps1 = ps(x = p_uty()) diff --git a/tests/testthat/test_cache.R b/tests/testthat/test_cache.R index bc85ea13..7c6934fa 100644 --- a/tests/testthat/test_cache.R +++ b/tests/testthat/test_cache.R @@ -1,4 +1,4 @@ -test_that("cache works if mlr3torch.cache is set to false", { +test_that("cache works if mlr3torch.cache is set to FALSE", { # if we disable caching, we expect the folder structure of the tempfile() to be: # raw: # - data.csv (the "downloaded" data) diff --git a/tests/testthat/test_materialize.R b/tests/testthat/test_materialize.R index b263eb78..46807452 100644 --- a/tests/testthat/test_materialize.R +++ b/tests/testthat/test_materialize.R @@ -98,12 +98,6 @@ test_that("materialize.list works", { expect_equal(names(out), "image") expect_class(out$image, "torch_tensor") expect_equal(out$image$shape, c(10, 1, 28, 28)) - - # to check: - # a) caching works when en / disabling cache manually - # c) default = "auto" works as expected - - # TODO }) test_that("materialize_internal: caching of datasets works", { @@ -145,9 +139,39 @@ test_that("materialize_internal: caching of datasets works", { expect_true(ds$count == 10) }) -test_that("materialize_internal with varying shapes", { - - +test_that("materialize with varying shapes", { + task = nano_dogs_vs_cats()$filter(1:2) + x = materialize(task$data()$x, rbind = FALSE) + expect_list(x, types = "torch_tensor") + expect_equal(x[[1]]$shape[1L], 3) + expect_equal(x[[2]]$shape[1L], 3) + + # shapes don't fit together + expect_error(materialize(task$data()$x, rbind = TRUE)) + + e = new.env() + e$a = 2L + + # depending on whether we apply this per row or per batch, we will get different results + # (second's sum(abs()) is either zero or non-zero) + fn = crate(function(x) { + a <<- a - 1 + x * a + }, .parent = e) + po_test = pipeop_preproc_torch("trafo_test", fn = fn) + # is processed batch-wise -> + task2 = po_test$train(list(nano_mnist()$filter(1:2)))[[1L]] + + x2 = materialize(task2$data()$image, rbind = TRUE) + expect_true(as.logical(sum(abs(x2[2, ..])) != 0)) + + e$a = 2 + x2 = materialize(task2$data()$image, rbind = FALSE) + expect_true(as.logical(sum(abs(x2[[2L]])) != 0)) + + e$a = 2 + x3 = materialize(po_test$train(list(task))[[1L]]$data()$x) + expect_true(as.logical(sum(abs(x3[[2L]])) == 0L)) }) test_that("PipeOpFeatureUnion can properly check whether two lazy tensors are identical", { @@ -160,5 +184,3 @@ test_that("PipeOpFeatureUnion can properly check whether two lazy tensors are id expect_error(graph$train(task), "cannot aggregate different features sharing") }) - - diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index 90e340e5..f9a80b01 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -268,7 +268,7 @@ test_that("caching of graph works", { env$counter = env$counter + 1L x + 1 }, env) - po_test = pipeop_preproc_torch("test", fn = fn, shapes_out = "unchanged") + po_test = pipeop_preproc_torch("test", fn = fn, shapes_out = "unchanged", stages_init = "both") expect_true(is.function(po_test$fn)) @@ -290,10 +290,62 @@ test_that("caching of graph works", { ds = task_dataset(task, ingress_tokens, device = "cpu") ds$.getbatch(1) - print(env) expect_equal(env$counter, 1) }) -test_that("merge_compatible_lazy_tensor_graphs", { - # TODO: +test_that("merging of graphs behaves as expected", { + task = tsk("lazy_iris") + + e = new.env() + e$a = 0 + fn = crate(function(x) { + a <<- a + 1 + x + }, .parent = e) + graph = pipeop_preproc_torch("trafo_counter", fn = fn) %>>% + list( + po("renamecolumns", renaming = c(x = "x1"), id = "a1") %>>% po("trafo_nop", id = "nop1"), + po("renamecolumns", renaming = c(x = "x2"), id = "a2") %>>% po("trafo_nop", id = "nop2") + ) + + tasks = graph$train(task) + task = tasks[[1]] + + task$cbind(tasks[[2]]$data(cols = "x2"))$filter(1:2) + + cols = task$data(cols = task$feature_names) + + ds = task_dataset( + task, + list( + x1 = TorchIngressToken("x1", batchgetter_lazy_tensor, c(NA, 4)), + x2 = TorchIngressToken("x2", batchgetter_lazy_tensor, c(NA, 4)) + ), + device = "cpu" + ) + + ds$.getbatch(1) + expect_true(e$a == 1L) + + # now we ensure that the addition of this unrelated columns (has a different dataset hash) + # does not intefer with the merging of the other columns + task$cbind(data.table(x3 = as_lazy_tensor(runif(150)), ..row_id = 1:150)) + + ds2 = task_dataset( + task, + list( + x1 = TorchIngressToken("x1", batchgetter_lazy_tensor, c(NA, 4)), + x2 = TorchIngressToken("x2", batchgetter_lazy_tensor, c(NA, 4)), + x3 = TorchIngressToken("x3", batchgetter_lazy_tensor, c(NA, 1)) + ), + device = "cpu" + ) + + e$a = 0 + ds2$.getbatch(1) + g1 = dd(ds2$task$data(cols = "x1")$x1)$graph + g2 = dd(ds2$task$data(cols = "x2")$x2)$graph + expect_true(identical(g1, g2)) + + expect_true(e$a == 1L) }) diff --git a/tests/testthat/test_utils.R b/tests/testthat/test_utils.R index 43b38c13..2c3c819c 100644 --- a/tests/testthat/test_utils.R +++ b/tests/testthat/test_utils.R @@ -30,3 +30,22 @@ test_that("get_nout works", { test_that("uniqueify works", { expect_equal(uniqueify("a", "a"), "a_1") }) + +test_that("auto_cache_lazy_tensors", { + ds = random_dataset(10, 3) + ds2 = random_dataset(10, 3) + + # 1) Duplicated dataset_hash + x1 = list( + as_lazy_tensor(ds, dataset_shapes = list(x = c(NA, 3)), ids = 1:3), + as_lazy_tensor(ds, dataset_shapes = list(x = c(NA, 3)), ids = 1:3) + ) + expect_true(auto_cache_lazy_tensors(x1)) + + # 2) Duplicated hash + x2 = list( + as_lazy_tensor(ds, dataset_shapes = list(x = c(NA, 3)), ids = 1:3), + as_lazy_tensor(ds2, dataset_shapes = list(x = c(NA, 3)), ids = 1:3) + ) + expect_false(auto_cache_lazy_tensors(x2)) +}) From 8c36923194049eb51ad62b534b06f58742c6f811 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 17:32:37 +0100 Subject: [PATCH 53/90] ... --- R/LearnerTorchImage.R | 6 ++++++ R/PipeOpTorchIngress.R | 1 - R/task_dataset.R | 23 ++++++++++++----------- tests/testthat/test_task_dataset.R | 6 +++--- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/R/LearnerTorchImage.R b/R/LearnerTorchImage.R index 70c2a229..617372a0 100644 --- a/R/LearnerTorchImage.R +++ b/R/LearnerTorchImage.R @@ -53,6 +53,11 @@ LearnerTorchImage = R6Class("LearnerTorchImage", ) assert_param_set(param_set) + param_set$add(ps( + shape = p_uty(tags = "train", default = NULL, custom_check = crate( + function(x) check_shape(x, null_ok = TRUE, unknown_batch = TRUE), .parent = topenv())) + )) + super$initialize( id = id, task_type = task_type, @@ -78,5 +83,6 @@ LearnerTorchImage = R6Class("LearnerTorchImage", .dataset = function(task, param_vals) { dataset_ltnsr(task, param_vals) } + ) ) diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index c088b32c..65935fb4 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -198,7 +198,6 @@ PipeOpTorchIngressNumeric = R6Class("PipeOpTorchIngressNumeric", ), private = list( .shape = function(task, param_vals) { - # TODO: check that task is legit c(NA, length(task$feature_types$type)) }, diff --git a/R/task_dataset.R b/R/task_dataset.R index 255aca7b..c47bbeda 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -146,25 +146,26 @@ merge_compatible_lazy_tensor_graphs = function(lts) { } dataset_ltnsr = function(task, param_vals) { - assert_true(length(task$feature_names) == 1L) - shape = dd(task$data(cols = task$feature_names)[[1L]])$pointer_shape - ingress_tokens = list(image = TorchIngressToken(task$feature_names, batchgetter_lazy_tensor, shape)) - + po_ingress = po("torch_ingress_ltnsr", shape = param_vals$shape) + md = po_ingress$train(list(task))[[1L]] + ingress = md$ingress + names(ingress) = "input" task_dataset( - task, - feature_ingress_tokens = ingress_tokens, + task = task, + feature_ingress_tokens = ingress, target_batchgetter = get_target_batchgetter(task$task_type), device = param_vals$device ) } dataset_num = function(task, param_vals) { - num_features = task$feature_types[get("type") %in% c("numeric", "integer"), "id"][[1L]] - ingress = TorchIngressToken(num_features, batchgetter_num, c(NA, length(task$feature_names))) - + po_ingress = po("torch_ingress_num") + md = po_ingress$train(list(task))[[1L]] + ingress = md$ingress + names(ingress) = "input" task_dataset( - task, - feature_ingress_tokens = list(input = ingress), + task = task, + feature_ingress_tokens = ingress, target_batchgetter = get_target_batchgetter(task$task_type), device = param_vals$device ) diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index f9a80b01..41644856 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -157,8 +157,8 @@ test_that("dataset_num works for classification and regression", { expected = torch_tensor(as.matrix(task$data(1:2, task$feature_names))) - expect_true(torch_equal(torch_tensor(expected), batch$x$input)) - expect_true(torch_equal(torch_tensor(expected), batch$x$input)) + expect_true(torch_equal(torch_tensor(expected), batch$x[[1]])) + expect_true(torch_equal(torch_tensor(expected), batch$x[[1]])) # regression ids = 2:4 @@ -167,7 +167,7 @@ test_that("dataset_num works for classification and regression", { batch = ds$.getbatch(seq_len(length(ids))) expected = torch_tensor(as.matrix(task$data(2:4, task$feature_names))) - expect_true(torch_equal(torch_tensor(expected), batch$x$input)) + expect_true(torch_equal(torch_tensor(expected), batch$x[[1]])) }) test_that("batchgetter_categ works", { From 1e3d3a74eb3423efe1d9873c392413688eb566bd Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 17:34:38 +0100 Subject: [PATCH 54/90] fix test on macOS --- tests/testthat/test_with_torch_settings.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test_with_torch_settings.R b/tests/testthat/test_with_torch_settings.R index 8030cf2e..2ff327a3 100644 --- a/tests/testthat/test_with_torch_settings.R +++ b/tests/testthat/test_with_torch_settings.R @@ -5,7 +5,7 @@ test_that("with_torch_settings leaves global state untouched", { prev_num_threads = 10 torch_set_num_threads(prev_num_threads) } else { - prev_num_threads = 1 + prev_num_threads = torch_get_num_threads() } prev_seed = get0(".Random.seed", globalenv(), mode = "integer", inherits = FALSE) prev_torch_rng_state = torch_get_rng_state() From 5896e0692e53a111bef27b27707d7f5d25ccaafc Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 18:36:16 +0100 Subject: [PATCH 55/90] more tests --- NAMESPACE | 2 +- R/lazy_tensor.R | 2 +- tests/testthat/test_lazy_tensor.R | 32 +++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index f466be13..64fc4014 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -27,7 +27,6 @@ S3method(as_torch_optimizer,torch_optimizer_generator) S3method(c,lazy_tensor) S3method(col_info,DataBackendLazy) S3method(format,lazy_tensor) -S3method(hash_input,lazy_tensor) S3method(materialize,data.frame) S3method(materialize,lazy_tensor) S3method(materialize,list) @@ -138,6 +137,7 @@ export(as_torch_optimizer) export(batchgetter_categ) export(batchgetter_num) export(callback_set) +export(hash_input.lazy_tensor) export(is_lazy_tensor) export(lazy_tensor) export(materialize) diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index dbf0b846..dc660482 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -17,7 +17,7 @@ lazy_tensor = function(data_descriptor = NULL, ids = NULL) { if (is.null(ids)) { ids = seq_along(data_descriptor$dataset) } else { - assert_integerish(ids, lower = 1L, upper = length(data_descriptor$dataset), any.missing = FALSE) + ids = assert_integerish(ids, lower = 1L, upper = length(data_descriptor$dataset), any.missing = FALSE, coerce = TRUE) } new_lazy_tensor(data_descriptor, ids) diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index 8581ffa4..e4805056 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -118,3 +118,35 @@ test_that("pofu identifies identical columns", { expect_set_equal(taskout$feature_names, "z") }) + +test_that("as_lazy_tensor for dataset", { + ds = random_dataset(10, 3) + x = as_lazy_tensor(ds, dataset_shapes = list(x = c(NA, 3)), ids = 1:5) + expect_class(x, "lazy_tensor") + expect_torch_equal(ds$.getbatch(1:5)$x, materialize(x, rbind = TRUE)) +}) + +test_that("as_lazy_tensor for DataDescriptor", { + ds = random_dataset(10, 3) + dd = DataDescriptor$new( + dataset = ds, + dataset_shapes = list(x = c(NA, 3)) + ) + x = as_lazy_tensor(dd, ids = c(1, 5)) + expect_class(x, "lazy_tensor") + expect_torch_equal(ds$.getbatch(c(1, 5))$x, materialize(x, rbind = TRUE)) +}) + +test_that("as_lazy_tensor for tensor", { + tnsr = torch_randn(10, 1) + x = as_lazy_tensor(tnsr) + expect_class(x, "lazy_tensor") + expect_torch_equal(tnsr, materialize(x, rbind = TRUE)) + +}) + +test_that("as_lazy_tensor for numeric", { + x = as_lazy_tensor(1:10) + expect_class(x, "lazy_tensor") + expect_equal(1:10, as.numeric(as_array(materialize(x, rbind = TRUE)))) +}) From 6b8755ae4fad635a4503503c77aaa8c9a7cdc2c4 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 23 Jan 2024 18:52:39 +0100 Subject: [PATCH 56/90] refactor lazy_tensor tests --- tests/testthat/test_lazy_tensor.R | 67 ++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index e4805056..228b46b7 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -1,4 +1,4 @@ -test_that("Unknown shapes work", { +test_that("Unknown shapes", { ds = dataset( initialize = function() { self$x = list( @@ -21,7 +21,7 @@ test_that("Unknown shapes work", { lt = as_lazy_tensor(dd) expect_class(lt, "lazy_tensor") - materialize(lt) + expect_error(materialize(lt), regexp = NA) expect_true(test_class(lt[1:2], "lazy_tensor")) expect_class(lt[[1]], "list") @@ -31,33 +31,49 @@ test_that("Unknown shapes work", { expect_error(DataDescriptor$new(ds, list(x = NULL))) }) -test_that("lazy_tensor works", { - dd1 = DataDescriptor$new(random_dataset(5, 4), list(x = c(NA, 5, 4))) - dd2 = DataDescriptor$new(random_dataset(5, 4), list(x = c(NA, 5, 4))) +test_that("assignment", { + x = as_lazy_tensor(1:2) + x[2] = x[1] + expect_class(x, "lazy_tensor") + expect_torch_equal( + materialize(x[1], rbind = TRUE), + materialize(x[2], rbind = TRUE) + ) - lt = lazy_tensor() - expect_class(lt, "lazy_tensor") - expect_true(length(lt) == 0L) - expect_error(is.null(dd(lt)$data_descriptor)) + expect_error({x[1] = as_lazy_tensor(1)}) # nolint +}) - lt1 = lazy_tensor(dd1) - lt2 = lazy_tensor(dd2) - expect_error(c(lt1, lt2), "Can only concatenate") +test_that("concatenation", { + x1 = as_lazy_tensor(1) + x2 = as_lazy_tensor(1) + expect_error(c(x1, x2), regexp = "Can only") - expect_error({lt1[1] = lt2[1]}) # nolint + x = c(x1, x1) + expect_class(x, "lazy_tensor") + expect_equal(length(x), 2) +}) - lt1_empty = lt1[integer(0)] - expect_error(is.null(dd(lt1_empty))) - expect_class(lt1_empty, "lazy_tensor") +test_that("subsetting and indexing", { + x = as_lazy_tensor(1:3) + expect_class(x[1:2], "lazy_tensor") + expect_equal(length(x[1:2]), 2) + expect_list(x[[1]], len = 2L) + expect_class(x[integer(0)], "lazy_tensor") + expect_equal(length(x[integer(0)]), 0) +}) - lt1_empty[1] = lt1[1] - expect_class(lt1_empty, "lazy_tensor") + +test_that("prototype", { + proto = lazy_tensor() + expect_class(proto, "lazy_tensor") + expect_true(length(proto) == 0L) + expect_error(dd(proto)) expect_error(materialize(lazy_tensor()), "Cannot materialize") }) -test_that("transform_lazy_tensor works", { +test_that("transform_lazy_tensor", { lt = as_lazy_tensor(torch_randn(16, 2, 5)) lt_mat = materialize(lt, rbind = TRUE) @@ -150,3 +166,16 @@ test_that("as_lazy_tensor for numeric", { expect_class(x, "lazy_tensor") expect_equal(1:10, as.numeric(as_array(materialize(x, rbind = TRUE)))) }) + +test_that("format", { + expect_equal(format(lazy_tensor()), character(0)) + expect_equal(format(as_lazy_tensor(1)), "") + expect_equal(format(as_lazy_tensor(1:2)), c("", "")) +}) + +test_that("printer", { + expect_equal( + capture.output(as_lazy_tensor(1:2)), + c("", "[1] ") + ) +}) From 20e7e7c21ece1590b7bb19523642bb055671d148 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 24 Jan 2024 11:30:15 +0100 Subject: [PATCH 57/90] better tests --- NAMESPACE | 2 +- R/DataDescriptor.R | 13 ++++--- R/lazy_tensor.R | 5 +++ man/hash_input.lazy_tensor.Rd | 15 +++++++ tests/testthat/helper_pipeop.R | 6 +++ tests/testthat/test_DataDescriptor.R | 41 ++++++++++++-------- tests/testthat/test_PipeOpTaskPreprocTorch.R | 6 +-- tests/testthat/test_task_dataset.R | 23 +++++++++-- 8 files changed, 83 insertions(+), 28 deletions(-) create mode 100644 man/hash_input.lazy_tensor.Rd diff --git a/NAMESPACE b/NAMESPACE index 64fc4014..f466be13 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -27,6 +27,7 @@ S3method(as_torch_optimizer,torch_optimizer_generator) S3method(c,lazy_tensor) S3method(col_info,DataBackendLazy) S3method(format,lazy_tensor) +S3method(hash_input,lazy_tensor) S3method(materialize,data.frame) S3method(materialize,lazy_tensor) S3method(materialize,list) @@ -137,7 +138,6 @@ export(as_torch_optimizer) export(batchgetter_categ) export(batchgetter_num) export(callback_set) -export(hash_input.lazy_tensor) export(is_lazy_tensor) export(lazy_tensor) export(materialize) diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index c458835f..aad09d92 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -75,12 +75,15 @@ DataDescriptor = R6Class("DataDescriptor", } if (!test_list(example, names = "unique") || !test_permutation(names(example), names(dataset_shapes))) { stopf("Dataset must return a list with named elements that are a permutation of the dataset_shapes names.") - iwalk(dataset_shapes, function(dataset_shape, name) { - if (!is.null(dataset_shape) && !test_equal(dataset_shapes[[name]][-1], example[[name]]$shape[-1L])) { - stopf("First batch from dataset is incompatible with the provided dataset_shapes.") - } - }) } + iwalk(dataset_shapes, function(dataset_shape, name) { + if (!is.null(dataset_shape) && !test_equal(dataset_shapes[[name]][-1], example[[name]]$shape[-1L])) { + stopf(paste0("First batch from dataset is incompatible with the provided dataset_shapes:\n", + "* Provided shape (%s): %s.\n* Observed shape (%s): %s."), name, name, + shape_to_str(unname(dataset_shapes[name])), shape_to_str(list(example[[name]]$shape) + )) + } + }) if (is.null(graph)) { # avoid name conflicts if (is.null(input_map)) { diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index dc660482..ded5e087 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -248,6 +248,11 @@ transform_lazy_tensor = function(lt, pipeop, shape, shape_predict = NULL) { new_lazy_tensor(data_descriptor, map_int(lt, 1)) } +#' @title Hash Input for Lazy Tensor +#' @description +#' Returns the a list containing the IDs and the data descriprot's hash. +#' @param x (any)\cr +#' Object for which to retrieve hash input. #' @export hash_input.lazy_tensor = function(x) { # When the DataBackend calculates the hash of, this function is called diff --git a/man/hash_input.lazy_tensor.Rd b/man/hash_input.lazy_tensor.Rd new file mode 100644 index 00000000..2af04c6f --- /dev/null +++ b/man/hash_input.lazy_tensor.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lazy_tensor.R +\name{hash_input.lazy_tensor} +\alias{hash_input.lazy_tensor} +\title{Hash Input for Lazy Tensor} +\usage{ +\method{hash_input}{lazy_tensor}(x) +} +\arguments{ +\item{x}{(any)\cr +Object for which to retrieve hash input.} +} +\description{ +Returns the a list containing the IDs and the data descriprot's hash. +} diff --git a/tests/testthat/helper_pipeop.R b/tests/testthat/helper_pipeop.R index 99c73dff..156decec 100644 --- a/tests/testthat/helper_pipeop.R +++ b/tests/testthat/helper_pipeop.R @@ -44,3 +44,9 @@ PipeOpTorchDebug = R6Class("PipeOpTorchDebug", } ) ) + +PipeOpPreprocTorchAddSome = pipeop_preproc_torch_class("trafo_some", + param_set = ps(some = p_dbl(default = 1L, tags = "train")), + fn = crate(function(x, some = 1L) x + some), + shapes_out = "unchanged" +) diff --git a/tests/testthat/test_DataDescriptor.R b/tests/testthat/test_DataDescriptor.R index 74298d38..de174012 100644 --- a/tests/testthat/test_DataDescriptor.R +++ b/tests/testthat/test_DataDescriptor.R @@ -1,16 +1,5 @@ -test_that("DataDescriptor works", { - ds = dataset( - initialize = function() { - self$x = torch_randn(10, 5, 3) - }, - .getitem = function(i) { - list(x = self$x[i, ..]) - }, - .length = function() { - nrow(self$x) - } - )() - +test_that("Basic checks", { + ds = random_dataset(5, 3) dd = DataDescriptor$new(ds, dataset_shapes = list(x = c(NA, 5, 3))) expect_class(dd, "DataDescriptor") expect_equal(dd$pointer_shape, c(NA, 5, 3)) @@ -23,14 +12,34 @@ test_that("DataDescriptor works", { dd1 = DataDescriptor$new(ds, dataset_shapes = list(x = c(NA, 5, 3))) expect_equal(dd$dataset_shapes, dd1$dataset_shapes) +}) +test_that("input verification", { + dataset = random_dataset(10, 5, 3) + expect_error(DataDescriptor$new(dataset, list(y = c(NA, 5, 3))), "must return a list") + expect_error(DataDescriptor$new(dataset, list(x = c(NA, 10, 5, 4))), "First batch") + expect_error(DataDescriptor$new(dataset, list(x = c(NA, 10, 5, 3)), input_map = "aaa"), "aaa") + dataset1 = dataset( + initialize = function() NULL, + .getitem = function(i) list(x = torch_tensor(1), y = torch_tensor(1)), + .length = function() 1)() + expect_error(DataDescriptor$new(dataset1, list(x = c(NA, 10, 5, 3)), input_map = c("x", "y")), + regexp = "that are a permutation") # dataset shapes must be provided - expect_error(DataDescriptor$new(ds), "missing") + expect_error(DataDescriptor$new(dataset), "missing") # batch must always be NA - expect_error(DataDescriptor$new(ds, dataset_shapes = c(10, 5, 3))) + expect_error(DataDescriptor$new(dataset, dataset_shapes = c(10, 10, 5, 3))) graph = as_graph(po("nop", id = "nop")) - expect_error(DataDescriptor$new(ds, dataset_shapes = list(x = c(NA, 5, 4)), "When passing a graph")) }) +test_that("can infer the simple case", { + dataset = random_dataset(5) + dd = DataDescriptor$new(dataset, list(x = c(NA, 5))) + expect_equal(dd$input_map, "x") + expect_equal(dd$pointer_shape, c(NA, 5)) + expect_equal(dd$pointer_shape_predict, c(NA, 5)) + expect_equal(dd$pointer, c(dd$graph$output$op.id, dd$graph$output$channel.name)) +}) + diff --git a/tests/testthat/test_PipeOpTaskPreprocTorch.R b/tests/testthat/test_PipeOpTaskPreprocTorch.R index c0af8e72..dfb4f011 100644 --- a/tests/testthat/test_PipeOpTaskPreprocTorch.R +++ b/tests/testthat/test_PipeOpTaskPreprocTorch.R @@ -1,4 +1,4 @@ -test_that("PipeOpTaskPreprocTorch: basic checks", { +test_that("basic", { po_test = po("preproc_torch", identity, packages = "R6", stages_init = "both") expect_pipeop(po_test) expect_equal(po_test$feature_types, "lazy_tensor") @@ -143,7 +143,7 @@ test_that("rowwise works", { expect_error(materialize(taskout2$data()$x), regexp = NA) }) -test_that("PipeOptaskPreprocTorch: shapes_out() works", { +test_that("shapes_out", { task = nano_dogs_vs_cats() po_resize = po("trafo_resize", size = c(10, 10)) expect_identical(po_resize$shapes_out(list(x = NULL), stage = "train"), list(NULL)) @@ -163,7 +163,7 @@ test_that("PipeOptaskPreprocTorch: shapes_out() works", { expect_identical(po_resize$shapes_out(list(x = NULL, y = c(NA, 3, 5, 5)), stage = "predict"), list(NULL, c(NA, 3, 10, 10))) }) -test_that("PipeOpTaskPreprocTorch modifies the underlying lazy tensor columns correctly", { +test_that("lazy tensor modified as expected", { d = data.table( y = 1:10, x = as_lazy_tensor(rnorm(10)) diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index 41644856..82e98517 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -1,4 +1,4 @@ -test_that("task_dataset basic tests", { +test_that("basic", { task = tsk("german_credit") ds = task_dataset( task = task, @@ -135,7 +135,7 @@ test_that("task_dataset respects the device", { f("meta") }) -test_that("batchgetter_num works", { +test_that("batchgetter_num", { data = data.table(x_int = 1:3, x_dbl = runif(3)) x = batchgetter_num(data, "cpu") expect_class(x, "torch_tensor") @@ -261,7 +261,7 @@ test_that("default target batchgetter works: classification", { expect_equal(y_loaded1$device$type, "meta") }) -test_that("caching of graph works", { +test_that("cachine of graph", { env = new.env() env$counter = 0L fn = crate(function(x) { @@ -349,3 +349,20 @@ test_that("merging of graphs behaves as expected", { expect_true(e$a == 1L) }) + +test_that("nop added for non-terminal pipeop", { + po_add = PipeOpPreprocTorchAddSome$new() + + task = tsk("lazy_iris") + graph = po("trafo_nop") %>>% + list( + po("renamecolumns", renaming = c(x = "y")) %>>% po("torch_ingress_ltnsr_1"), + po_add %>>% po("torch_ingress_ltnsr_2")) %>>% + po("nn_merge_sum") + + task = graph$train(task)[[1L]]$task + + res = materialize(task$data()[1, ], rbind = TRUE) + expect_torch_equal(res$y + 1, res$x) + +}) From 41bc9c130ecc0e34a3657707cbb60d72012affeb Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Thu, 25 Jan 2024 16:11:14 +0100 Subject: [PATCH 58/90] tags --- R/PipeOpTaskPreprocTorch.R | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 77650e3d..6900c9cc 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -178,7 +178,7 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' @description #' Creates a new instance of this [`R6`][R6::R6Class] class. initialize = function(fn, id = "preproc_torch", param_vals = list(), param_set = ps(), packages = character(0), rowwise = FALSE, - stages_init = NULL) { # nolint + stages_init = NULL, tags = "torch") { # nolint assert(check_function(fn), check_character(fn, len = 2L)) private$.fn = fn private$.rowwise = assert_flag(rowwise) @@ -194,7 +194,8 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", param_vals = param_vals, param_set = param_set, feature_types = "lazy_tensor", - packages = packages + packages = packages, + tags = tags ) }, #' @description From 4f32e59c4533f0bcab2faae4cf3c5ea917fa0e78 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Thu, 25 Jan 2024 19:00:00 +0100 Subject: [PATCH 59/90] fix tests --- man/mlr_pipeops_preproc_torch.Rd | 3 ++- tests/testthat/test_lazy_tensor.R | 4 ++-- tests/testthat/test_utils.R | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/man/mlr_pipeops_preproc_torch.Rd b/man/mlr_pipeops_preproc_torch.Rd index 0963f3b7..f54be8f8 100644 --- a/man/mlr_pipeops_preproc_torch.Rd +++ b/man/mlr_pipeops_preproc_torch.Rd @@ -211,7 +211,8 @@ Creates a new instance of this \code{\link[R6:R6Class]{R6}} class. param_set = ps(), packages = character(0), rowwise = FALSE, - stages_init = NULL + stages_init = NULL, + tags = "torch" )}\if{html}{\out{}} } diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index 228b46b7..e98ee0c5 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -136,14 +136,14 @@ test_that("pofu identifies identical columns", { }) test_that("as_lazy_tensor for dataset", { - ds = random_dataset(10, 3) + ds = random_dataset(3) x = as_lazy_tensor(ds, dataset_shapes = list(x = c(NA, 3)), ids = 1:5) expect_class(x, "lazy_tensor") expect_torch_equal(ds$.getbatch(1:5)$x, materialize(x, rbind = TRUE)) }) test_that("as_lazy_tensor for DataDescriptor", { - ds = random_dataset(10, 3) + ds = random_dataset(3) dd = DataDescriptor$new( dataset = ds, dataset_shapes = list(x = c(NA, 3)) diff --git a/tests/testthat/test_utils.R b/tests/testthat/test_utils.R index 2c3c819c..083b9950 100644 --- a/tests/testthat/test_utils.R +++ b/tests/testthat/test_utils.R @@ -32,8 +32,8 @@ test_that("uniqueify works", { }) test_that("auto_cache_lazy_tensors", { - ds = random_dataset(10, 3) - ds2 = random_dataset(10, 3) + ds = random_dataset(3) + ds2 = random_dataset(3) # 1) Duplicated dataset_hash x1 = list( From a1e86534f3774dbac2aa10dc212ac55611e67ac0 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Thu, 25 Jan 2024 20:08:43 +0100 Subject: [PATCH 60/90] add missing docs --- R/PipeOpTaskPreprocTorch.R | 4 ++-- man/pipeop_preproc_torch.Rd | 2 +- man/pipeop_preproc_torch_class.Rd | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 6157ec16..695e4f4a 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -376,8 +376,6 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", #' @template param_param_vals #' @param param_vals (`list()`)\cr #' The parameter values. -#' @param tags (`character()`)\cr -#' Tags for the pipeop. #' @export pipeop_preproc_torch = function(id, fn, shapes_out = NULL, param_set = NULL, param_vals = list(), packages = character(0), rowwise = FALSE, parent_env = parent.frame(), stages_init = NULL, tags = NULL) { @@ -449,6 +447,8 @@ create_ps = function(fn) { #' If `NULL` (default), will be set to `"both"` in case the `id` starts with `"trafo"` and to `"train"` #' if it starts with `"augment"`. Otherwise it must specified. #' @template param_packages +#' @param tags (`character()`)\cr +#' Tags for the pipeop #' @export #' @returns An [`R6Class`][R6::R6Class] instance inheriting from [`PipeOpTaskPreprocTorch`] #' @examples diff --git a/man/pipeop_preproc_torch.Rd b/man/pipeop_preproc_torch.Rd index 49297a5d..beceb500 100644 --- a/man/pipeop_preproc_torch.Rd +++ b/man/pipeop_preproc_torch.Rd @@ -61,7 +61,7 @@ If \code{NULL} (default), will be set to \code{"both"} in case the \code{id} sta if it starts with \code{"augment"}. Otherwise it must specified.} \item{tags}{(\code{character()})\cr -Tags for the pipeop.} +Tags for the pipeop} } \description{ Calls \code{\link{pipeop_preproc_torch_class}} and instantiates the instance with the given parameter values. diff --git a/man/pipeop_preproc_torch_class.Rd b/man/pipeop_preproc_torch_class.Rd index 8d4a23b6..2a757d42 100644 --- a/man/pipeop_preproc_torch_class.Rd +++ b/man/pipeop_preproc_torch_class.Rd @@ -55,6 +55,9 @@ The parent environment for the R6 class.} Initial value for the \code{stages} parameter. If \code{NULL} (default), will be set to \code{"both"} in case the \code{id} starts with \code{"trafo"} and to \code{"train"} if it starts with \code{"augment"}. Otherwise it must specified.} + +\item{tags}{(\code{character()})\cr +Tags for the pipeop} } \value{ An \code{\link[R6:R6Class]{R6Class}} instance inheriting from \code{\link{PipeOpTaskPreprocTorch}} From d744cbd25509d2250df8fd6aed446adf44bf7e40 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Thu, 25 Jan 2024 20:38:54 +0100 Subject: [PATCH 61/90] ... --- R/DataBackendLazy.R | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/R/DataBackendLazy.R b/R/DataBackendLazy.R index 3e25095a..a679534b 100644 --- a/R/DataBackendLazy.R +++ b/R/DataBackendLazy.R @@ -187,10 +187,9 @@ DataBackendLazy = R6Class("DataBackendLazy", } } - # test_equal does not exist so we abuse test_permutation for primary_key - f(test_permutation, private$.backend$primary_key, self$primary_key, "primary key") + f(function(x, y) isTRUE(all.equal(x, y)), private$.backend$primary_key, self$primary_key, "primary key") f(test_permutation, private$.backend$rownames, self$rownames, "row identifiers") - f(test_permutation, private$.backend$colnames, private$.colnames, "column names") + f(function(x, y) isTRUE(all.equal(x, y)), private$.backend$colnames, private$.colnames, "column names") f(test_equal_col_info, col_info(private$.backend), private$.col_info, "column information") # need to reverse the order for correct error message f(function(x, y) test_subset(y, x), private$.backend$data_formats, self$data_formats, "data formats") From b2ae57510f5db38e9e241411b995fcb49dc363da Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Thu, 25 Jan 2024 20:46:48 +0100 Subject: [PATCH 62/90] ... --- R/DataBackendLazy.R | 2 -- R/TaskClassif_mnist.R | 6 ------ R/TaskClassif_tiny_imagenet.R | 9 ++------- man/mlr_backends_lazy.Rd | 2 -- 4 files changed, 2 insertions(+), 17 deletions(-) diff --git a/R/DataBackendLazy.R b/R/DataBackendLazy.R index a679534b..d055ef5d 100644 --- a/R/DataBackendLazy.R +++ b/R/DataBackendLazy.R @@ -28,8 +28,6 @@ #' #' When the constructor generates `factor()` variables it is important that the ordering of the levels in data #' corresponds to the ordering of the levels in the `col_info` argument. -#' Because the ordering of the level depends on the locale, it is recommended to e.g. use the `C` locale in the -#' `constructor` function, e.g. with `withr::with_locale()`. #' #' @param constructor (`function`)\cr #' A function with no arguments, whose return value must be the actual backend. diff --git a/R/TaskClassif_mnist.R b/R/TaskClassif_mnist.R index 23db18ae..ebbf9976 100644 --- a/R/TaskClassif_mnist.R +++ b/R/TaskClassif_mnist.R @@ -49,12 +49,6 @@ constructor_mnist = function(path) { load_task_mnist = function(id = "mnist") { cached_constructor = function() { - # factor level ordering can depend on locale - # in this case, nothing should go wrong but we keep it here as a reminder (is e.g. needed in tiny imagenet) - withr::with_locale(c(LC_COLLATE = "C"), { - data = cached(constructor_mnist, "datasets", "mnist")$data - }) - ds = dataset( initialize = function(images) { self$images = torch_tensor(images, dtype = torch_float32()) diff --git a/R/TaskClassif_tiny_imagenet.R b/R/TaskClassif_tiny_imagenet.R index 6fd79326..cc7f3fe2 100644 --- a/R/TaskClassif_tiny_imagenet.R +++ b/R/TaskClassif_tiny_imagenet.R @@ -70,22 +70,17 @@ constructor_tiny_imagenet = function(path) { valid_res = get_uris(download_folder, "val") test_uris = list.files(file.path(download_folder, "test", "images"), full.names = TRUE) + ci = load_col_info("tiny_imagenet") classes = c(train_res$labels, valid_res$labels, rep(NA_character_, length(test_uris))) uris = c(train_res$uris, valid_res$uris, test_uris) splits = rep(c("train", "valid", "test"), times = map_int(list(train_res$labels, valid_res$labels, test_uris), length)) - data.table(class = as.factor(classes), image = uris, split = factor(splits)) + data.table(class = factor(classes, levels = ci[id == "image", "levelsl"][[1L]]), image = uris, split = factor(splits)) } #' @include utils.R load_task_tiny_imagenet = function(id = "tiny_imagenet") { cached_constructor = crate(function() { - # We need this as otherwise the factor level are differently ordered, - # which causes the hard-coded col-info to be wrong for some locales - # (whether a < A or A > a depends on the locale) - withr::with_locale(c(LC_COLLATE = "C"), { - dt = cached(constructor_tiny_imagenet, "datasets", "tiny_imagenet")$data - }) dt$image = as_lazy_tensor(dataset_image(dt$image), dataset_shapes = list(x = c(NA, 3, 64, 64))) dt$..row_id = seq_len(nrow(dt)) diff --git a/man/mlr_backends_lazy.Rd b/man/mlr_backends_lazy.Rd index 84f07beb..0a0c46d1 100644 --- a/man/mlr_backends_lazy.Rd +++ b/man/mlr_backends_lazy.Rd @@ -32,8 +32,6 @@ of this class has nothing to do with the \code{\link{lazy_tensor}} data type. When the constructor generates \code{factor()} variables it is important that the ordering of the levels in data corresponds to the ordering of the levels in the \code{col_info} argument. -Because the ordering of the level depends on the locale, it is recommended to e.g. use the \code{C} locale in the -\code{constructor} function, e.g. with \code{withr::with_locale()}. } \examples{ # We first define a backend constructor From f52922e32899c727e540408594ab133be0594e56 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Thu, 25 Jan 2024 20:57:52 +0100 Subject: [PATCH 63/90] fix dumb bug --- R/TaskClassif_mnist.R | 1 + R/TaskClassif_tiny_imagenet.R | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/R/TaskClassif_mnist.R b/R/TaskClassif_mnist.R index ebbf9976..b492abff 100644 --- a/R/TaskClassif_mnist.R +++ b/R/TaskClassif_mnist.R @@ -49,6 +49,7 @@ constructor_mnist = function(path) { load_task_mnist = function(id = "mnist") { cached_constructor = function() { + data = cached(constructor_mnist, "datasets", "mnist")$data ds = dataset( initialize = function(images) { self$images = torch_tensor(images, dtype = torch_float32()) diff --git a/R/TaskClassif_tiny_imagenet.R b/R/TaskClassif_tiny_imagenet.R index cc7f3fe2..41bfd0f0 100644 --- a/R/TaskClassif_tiny_imagenet.R +++ b/R/TaskClassif_tiny_imagenet.R @@ -41,6 +41,8 @@ constructor_tiny_imagenet = function(path) { colnames(lookup) = c("id", "label") + + get_uris = function(dir, set) { folder_names = list.files(file.path(dir, set)) folder_names = folder_names[folder_names != "val_annotations.txt"] @@ -75,12 +77,13 @@ constructor_tiny_imagenet = function(path) { uris = c(train_res$uris, valid_res$uris, test_uris) splits = rep(c("train", "valid", "test"), times = map_int(list(train_res$labels, valid_res$labels, test_uris), length)) - data.table(class = factor(classes, levels = ci[id == "image", "levelsl"][[1L]]), image = uris, split = factor(splits)) + data.table(class = factor(classes, levels = ci[list("image"), "levelsl", on = "id"][[1L]]), image = uris, split = factor(splits)) } #' @include utils.R load_task_tiny_imagenet = function(id = "tiny_imagenet") { cached_constructor = crate(function() { + dt = cached(constructor_tiny_imagenet, "datasets", "tiny_imagenet")$data dt$image = as_lazy_tensor(dataset_image(dt$image), dataset_shapes = list(x = c(NA, 3, 64, 64))) dt$..row_id = seq_len(nrow(dt)) From 62e4f44a174cb0661e55ef2cabd3a0459d6aaa90 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Thu, 25 Jan 2024 21:07:27 +0100 Subject: [PATCH 64/90] ... --- R/TaskClassif_tiny_imagenet.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/TaskClassif_tiny_imagenet.R b/R/TaskClassif_tiny_imagenet.R index 41bfd0f0..296b8e58 100644 --- a/R/TaskClassif_tiny_imagenet.R +++ b/R/TaskClassif_tiny_imagenet.R @@ -77,7 +77,7 @@ constructor_tiny_imagenet = function(path) { uris = c(train_res$uris, valid_res$uris, test_uris) splits = rep(c("train", "valid", "test"), times = map_int(list(train_res$labels, valid_res$labels, test_uris), length)) - data.table(class = factor(classes, levels = ci[list("image"), "levelsl", on = "id"][[1L]]), image = uris, split = factor(splits)) + data.table(class = factor(classes, levels = ci[list("image"), "levels", on = "id"][[1L]]), image = uris, split = factor(splits)) } #' @include utils.R From b2730c3934437703c9eb4671e57e3eea7596ed7a Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 26 Jan 2024 08:35:44 +0100 Subject: [PATCH 65/90] ... --- R/DataBackendLazy.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/DataBackendLazy.R b/R/DataBackendLazy.R index d055ef5d..d2d41f57 100644 --- a/R/DataBackendLazy.R +++ b/R/DataBackendLazy.R @@ -186,8 +186,8 @@ DataBackendLazy = R6Class("DataBackendLazy", } f(function(x, y) isTRUE(all.equal(x, y)), private$.backend$primary_key, self$primary_key, "primary key") - f(test_permutation, private$.backend$rownames, self$rownames, "row identifiers") - f(function(x, y) isTRUE(all.equal(x, y)), private$.backend$colnames, private$.colnames, "column names") + f(function(x, y) isTRUE(all.equal(x, y)), private$.backend$rownames, self$rownames, "row identifiers") + f(test_permutation, private$.backend$colnames, private$.colnames, "column names") f(test_equal_col_info, col_info(private$.backend), private$.col_info, "column information") # need to reverse the order for correct error message f(function(x, y) test_subset(y, x), private$.backend$data_formats, self$data_formats, "data formats") From 05451e527e509363a55bcd77e923f62075868f2e Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 26 Jan 2024 10:08:45 +0100 Subject: [PATCH 66/90] rcmdcheck passing --- R/DataBackendLazy.R | 12 +++++------ R/TaskClassif_mnist.R | 11 +++++----- R/TaskClassif_tiny_imagenet.R | 18 +++++++++-------- R/cache.R | 11 ++++++---- inst/col_info/mnist.rds | Bin 276 -> 257 bytes inst/col_info/tiny_imagenet.rds | Bin 2794 -> 2770 bytes man/mlr_backends_lazy.Rd | 4 ++-- man/mlr_tasks_mnist.Rd | 2 +- man/mlr_tasks_tiny_imagenet.Rd | 2 +- tests/testthat/test_DataBackendLazy.R | 19 +++++++++++++----- .../testthat/test_TaskClassif_tiny_imagenet.R | 2 +- 11 files changed, 47 insertions(+), 34 deletions(-) diff --git a/R/DataBackendLazy.R b/R/DataBackendLazy.R index d2d41f57..3808b9e1 100644 --- a/R/DataBackendLazy.R +++ b/R/DataBackendLazy.R @@ -30,7 +30,7 @@ #' corresponds to the ordering of the levels in the `col_info` argument. #' #' @param constructor (`function`)\cr -#' A function with no arguments, whose return value must be the actual backend. +#' A function with argument `backend` (the lazy backend), whose return value must be the actual backend. #' This function is called the first time the field `$backend` is accessed. #' @param rownames (`integer()`)\cr #' The row names. Must be a permutation of the rownames of the lazily constructed backend. @@ -54,7 +54,7 @@ #' @export #' @examples #' # We first define a backend constructor -#' constructor = function() { +#' constructor = function(backend) { #' cat("Data is constructed!\n") #' DataBackendDataTable$new( #' data.table(x = rnorm(10), y = rnorm(10), row_id = 1:10), @@ -101,7 +101,7 @@ DataBackendLazy = R6Class("DataBackendLazy", assert_choice(primary_key, col_info$id) private$.colnames = col_info$id assert_choice(primary_key, col_info$id) - private$.constructor = assert_function(constructor, nargs = 0) + private$.constructor = assert_function(constructor, args = "backend") super$initialize(data = NULL, primary_key = primary_key, data_formats = data_formats) }, @@ -173,7 +173,7 @@ DataBackendLazy = R6Class("DataBackendLazy", backend = function(rhs) { assert_ro_binding(rhs) if (is.null(private$.backend)) { - private$.backend = assert_backend(private$.constructor()) + private$.backend = assert_backend(private$.constructor(self)) f = function(test, x, y, var_name) { if (!test(x, y)) { @@ -185,8 +185,8 @@ DataBackendLazy = R6Class("DataBackendLazy", } } - f(function(x, y) isTRUE(all.equal(x, y)), private$.backend$primary_key, self$primary_key, "primary key") - f(function(x, y) isTRUE(all.equal(x, y)), private$.backend$rownames, self$rownames, "row identifiers") + f(identical, private$.backend$primary_key, self$primary_key, "primary key") + f(test_permutation, private$.backend$rownames, self$rownames, "row identifiers") f(test_permutation, private$.backend$colnames, private$.colnames, "column names") f(test_equal_col_info, col_info(private$.backend), private$.col_info, "column information") # need to reverse the order for correct error message diff --git a/R/TaskClassif_mnist.R b/R/TaskClassif_mnist.R index b492abff..0f58eeec 100644 --- a/R/TaskClassif_mnist.R +++ b/R/TaskClassif_mnist.R @@ -42,14 +42,14 @@ constructor_mnist = function(path) { images = array(NA, dim = c(70000, 1, 28, 28)) images[1:60000, , , ] = images_train images[60001:70000, , , ] = images_test - labels = factor(c(d_train$targets, d_test$targets), levels = 1:10, labels = as.character(0:9)) - list(label = labels, image = images) + list(label = c(d_train$targets, d_test$targets), image = images) } load_task_mnist = function(id = "mnist") { - cached_constructor = function() { + cached_constructor = function(backend) { data = cached(constructor_mnist, "datasets", "mnist")$data + labels = factor(data$label, levels = 1:10, labels = as.character(0:9)) ds = dataset( initialize = function(images) { self$images = torch_tensor(images, dtype = torch_float32()) @@ -64,9 +64,8 @@ load_task_mnist = function(id = "mnist") { dt = data.table( image = lazy_tensor(data_descriptor), - label = data$label, - ..row_id = seq_along(data$label), - split = factor(c(rep("train", 60000), rep("test", 10000))) + label = labels, + ..row_id = seq_along(labels) ) DataBackendDataTable$new(data = dt, primary_key = "..row_id") diff --git a/R/TaskClassif_tiny_imagenet.R b/R/TaskClassif_tiny_imagenet.R index 296b8e58..463d4073 100644 --- a/R/TaskClassif_tiny_imagenet.R +++ b/R/TaskClassif_tiny_imagenet.R @@ -41,8 +41,6 @@ constructor_tiny_imagenet = function(path) { colnames(lookup) = c("id", "label") - - get_uris = function(dir, set) { folder_names = list.files(file.path(dir, set)) folder_names = folder_names[folder_names != "val_annotations.txt"] @@ -72,21 +70,25 @@ constructor_tiny_imagenet = function(path) { valid_res = get_uris(download_folder, "val") test_uris = list.files(file.path(download_folder, "test", "images"), full.names = TRUE) - ci = load_col_info("tiny_imagenet") classes = c(train_res$labels, valid_res$labels, rep(NA_character_, length(test_uris))) uris = c(train_res$uris, valid_res$uris, test_uris) - splits = rep(c("train", "valid", "test"), times = map_int(list(train_res$labels, valid_res$labels, test_uris), length)) - data.table(class = factor(classes, levels = ci[list("image"), "levels", on = "id"][[1L]]), image = uris, split = factor(splits)) + data.frame( + class = classes, + image = uris + ) } #' @include utils.R load_task_tiny_imagenet = function(id = "tiny_imagenet") { - cached_constructor = crate(function() { + cached_constructor = crate(function(backend) { dt = cached(constructor_tiny_imagenet, "datasets", "tiny_imagenet")$data + setDT(dt) - dt$image = as_lazy_tensor(dataset_image(dt$image), dataset_shapes = list(x = c(NA, 3, 64, 64))) - dt$..row_id = seq_len(nrow(dt)) + ci = col_info(backend) + set(dt, j = "class", value = factor(dt$class, levels = ci[list("class"), "levels", on = "id"][[1L]][[1L]])) + set(dt, j = "image", value = as_lazy_tensor(dataset_image(dt$image), dataset_shapes = list(x = c(NA, 3, 64, 64)))) + set(dt, j = "..row_id", value = seq_len(nrow(dt))) DataBackendDataTable$new(data = dt, primary_key = "..row_id") }, .parent = topenv()) diff --git a/R/cache.R b/R/cache.R index 2e6a47b0..21bdc312 100644 --- a/R/cache.R +++ b/R/cache.R @@ -88,11 +88,14 @@ cached = function(constructor, type, name) { if (do_caching && dir.exists(path)) { # we cache and there is a cache hit - data = readRDS(file.path(path, "data.rds")) - output = list(data = data, path = path) - return(output) + data = try(readRDS(file.path(path, "data.rds")), silent = TRUE) + if (!inherits(data, "try-error")) { + return(list(data = data, path = path)) + } + lg$debug("Cache hit failed, removing cache", path = path) + lapply(list.files(path, full.names = TRUE), unlink) } - # We either don't cache or there is no cache hit + # We either don't cache, there is no cache hit or cache retrieval failed data = try({ path_raw = file.path(path, "raw") if (!dir.exists(path_raw)) { diff --git a/inst/col_info/mnist.rds b/inst/col_info/mnist.rds index 6f307c5040d1467abed8e2f6404c6819f18fda75..ec56fa05e22f8eba7e509d918562963bc56d135c 100644 GIT binary patch literal 257 zcmV+c0sj6UiwFP!000001D%mgP6IIvh28lp9fSlz>Me+X7AP0s1XN;IxgAe6k~>97 z1S%^o4uc0`)MnX5lFu*6bL_m70FXkKCXnWWkk6l=u4bZL{%!!A{~dsltS83U?fass zLYy}nT$2WjOXBFpuxUN5$%gQh@ng5})Vi%oMU5*j5rAg=4x{%e!>Pfw!i~bM!bD-J zaHnvu@SreLcm&9j9`yMwZpcN?PyS2I{O(mNEtuYjU1Ttl))+N8>o0%G)OFogoN2}A zG*c49vOsjWCh1{bF9s%?>tBd#sgB96n@@7^(G6!JBms^Bo#a}eJjykw}{ HF9HAnRLgt@ literal 276 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 \describe{ \item{\code{constructor}}{(\code{function})\cr -A function with no arguments, whose return value must be the actual backend. +A function with argument \code{backend} (the lazy backend), whose return value must be the actual backend. This function is called the first time the field \verb{$backend} is accessed.} \item{\code{rownames}}{(\code{integer()})\cr diff --git a/man/mlr_tasks_mnist.Rd b/man/mlr_tasks_mnist.Rd index 27d81b63..6af1a5d8 100644 --- a/man/mlr_tasks_mnist.Rd +++ b/man/mlr_tasks_mnist.Rd @@ -37,7 +37,7 @@ as the cache directory. \item Has Missings: no \item Target: \dQuote{label} \item Features: \dQuote{image} -\item Backend Dimension: 70000x4 +\item Backend Dimension: 70000x3 \item Default Roles (use / test / holdout): 60000, 10000, 0 } } diff --git a/man/mlr_tasks_tiny_imagenet.Rd b/man/mlr_tasks_tiny_imagenet.Rd index 7a99bd6c..12730832 100644 --- a/man/mlr_tasks_tiny_imagenet.Rd +++ b/man/mlr_tasks_tiny_imagenet.Rd @@ -29,7 +29,7 @@ indicates whether the row belongs to the train, validation or test set. \item Has Missings: no \item Target: \dQuote{class} \item Features: \dQuote{image} -\item Backend Dimension: 120000x4 +\item Backend Dimension: 120000x3 \item Default Roles (use / test / holdout): 100000, 10000, 10000 } } diff --git a/tests/testthat/test_DataBackendLazy.R b/tests/testthat/test_DataBackendLazy.R index 8bfd5211..f2df2161 100644 --- a/tests/testthat/test_DataBackendLazy.R +++ b/tests/testthat/test_DataBackendLazy.R @@ -1,6 +1,6 @@ test_that("DataBackendLazy works", { n = 5 - constructor = function() { + constructor = function(backend) { dt = data.table( y = c(0.1, 0.2, 0.3, 0.4, 0.5), x_fct = factor(letters[1:n]), @@ -40,7 +40,6 @@ test_that("DataBackendLazy works", { expect_r6(backend_lazy$backend, c("DataBackend", "DataBackendDataTable")) expect_true(backend_lazy$is_constructed) - expect_true(any(grepl(capture.output(backend_lazy), pattern = "x_fct"))) expect_equal(backend_lazy$data(rows = 1, cols = "y")[[1L]], 0.5) @@ -60,7 +59,7 @@ test_that("DataBackendLazy works", { constructor_constructor = function(colnames = letters[1:3], rownames = 1:10, letter = "a") { ncol = length(colnames) - function() { + function(backend) { cols = lapply(colnames[1:(length(colnames) - 1)], function(x) { dt = data.table(rownames) names(dt) = x @@ -112,7 +111,7 @@ test_that("DataBackendLazy works", { test_that("primary_key must be in col_info", { expect_error(DataBackendLazy$new( - constructor = function() NULL, + constructor = function(backend) NULL, col_info = data.table(id = "a", type = "integer", levels = list(NULL)), rownames = 1, primary_key = "b", @@ -121,7 +120,7 @@ test_that("primary_key must be in col_info", { }) test_that("primary_key must be the same for backends", { - constructor = function() { + constructor = function(backend) { DataBackendDataTable$new( data.table(y = 1:5, x = 1:5), primary_key = "x" @@ -136,3 +135,13 @@ test_that("primary_key must be the same for backends", { ) expect_error(backend_lazy$backend, "primary key") }) + +test_that("constructor must have argument backend", { + expect_error(DataBackendLazy$new( + constructor = function() NULL, + col_info = data.table(id = c("x", "y"), type = rep("integer", 2), levels = list(NULL, NULL)), + rownames = 1:5, + primary_key = "y", + data_formats = "data.table" + ), regexp = "formal arguments") +}) diff --git a/tests/testthat/test_TaskClassif_tiny_imagenet.R b/tests/testthat/test_TaskClassif_tiny_imagenet.R index 4b3b1b84..0c99f48d 100644 --- a/tests/testthat/test_TaskClassif_tiny_imagenet.R +++ b/tests/testthat/test_TaskClassif_tiny_imagenet.R @@ -18,5 +18,5 @@ test_that("tiny_imagenet works", { expect_true("tiny-imagenet-200" %in% list.files(file.path(get_cache_dir(), "datasets", "tiny_imagenet", "raw"))) expect_true("data.rds" %in% list.files(file.path(get_cache_dir(), "datasets", "tiny_imagenet"))) expect_equal(task$backend$nrow, 120000) - expect_equal(task$backend$ncol, 4) + expect_equal(task$backend$ncol, 3) }) From 132326c21028157fb888bf8583a47762a04f48b2 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 26 Jan 2024 11:00:57 +0100 Subject: [PATCH 67/90] support mps in auto_device --- R/utils.R | 33 ++++++--------------------- man-roxygen/paramset_torchlearner.R | 3 ++- man/mlr_learners.alexnet.Rd | 2 ++ man/mlr_learners.mlp.Rd | 2 ++ man/mlr_learners.torch_featureless.Rd | 2 ++ man/mlr_learners_torch.Rd | 5 +++- man/mlr_learners_torch_image.Rd | 2 ++ man/mlr_learners_torch_model.Rd | 2 ++ man/mlr_pipeops_torch_model.Rd | 3 ++- 9 files changed, 25 insertions(+), 29 deletions(-) diff --git a/R/utils.R b/R/utils.R index de644bf5..3345e7af 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1,6 +1,12 @@ auto_device = function(device = NULL) { if (device == "auto") { - device = if (cuda_is_available()) "cuda" else "cpu" + device = if (cuda_is_available()) { + "cuda" + } else if (backends_mps_is_available()) { + "mps" + } else { + "cpu" + } lg$debug("Auto-detected device '%s'.", device) } return(device) @@ -43,31 +49,6 @@ check_function_or_null = function(x) check_function(x, null.ok = TRUE) check_integerish_or_null = function(x) check_integerish(x, null.ok = TRUE) -broadcast = function(shape1, shape2) { - assert_true(!anyNA(shape1) && !anyNA(shape2)) - d = abs(length(shape1) - length(shape2)) - if (d != 0) { - if (length(shape1) > length(shape2)) { - x = c(rep(1L, d), shape1) - } else { - y = c(rep(1L, d), shape2) - } - } - pmax(shape1, shape2) -} - -broadcast_list = function(...) { - Reduce(broadcast, list(...)) -} - -check_nn_module_generator = function(x) { - if (inherits(x, "nn_module_generator")) { - return(TRUE) - } - - "Most be module generator." -} - assert_inherits_classname = function(class_generator, classname) { assert_class(class_generator, "R6ClassGenerator") while (!is.null(class_generator)) { diff --git a/man-roxygen/paramset_torchlearner.R b/man-roxygen/paramset_torchlearner.R index 89f5bb76..60b0d049 100644 --- a/man-roxygen/paramset_torchlearner.R +++ b/man-roxygen/paramset_torchlearner.R @@ -6,7 +6,8 @@ #' The number of epochs. #' * `device` :: `character(1)`\cr #' The device. One of `"auto"`, `"cpu"`, or `"cuda"` or other values defined in `mlr_reflections$torch$devices`. -#' The value is initialized to `"auto"`, which will select `"cuda"` if possible and `"cpu"` otherwise. +#' The value is initialized to `"auto"`, which will select `"cuda"` if possible, then try `"mps"`, and otherwise +#' will fall back to `"cpu"`. #' * `measures_train` :: [`Measure`] or `list()` of [`Measure`]s. #' Measures to be evaluated during training. #' * `measures_valid` :: [`Measure`] or `list()` of [`Measure`]s. diff --git a/man/mlr_learners.alexnet.Rd b/man/mlr_learners.alexnet.Rd index c477ef17..2b800a3c 100644 --- a/man/mlr_learners.alexnet.Rd +++ b/man/mlr_learners.alexnet.Rd @@ -78,11 +78,13 @@ Other Learner:
Inherited methods diff --git a/man/mlr_learners.mlp.Rd b/man/mlr_learners.mlp.Rd index d443563b..86c71288 100644 --- a/man/mlr_learners.mlp.Rd +++ b/man/mlr_learners.mlp.Rd @@ -106,11 +106,13 @@ Other Learner:
Inherited methods diff --git a/man/mlr_learners.torch_featureless.Rd b/man/mlr_learners.torch_featureless.Rd index aaaea71f..9e4a602c 100644 --- a/man/mlr_learners.torch_featureless.Rd +++ b/man/mlr_learners.torch_featureless.Rd @@ -95,11 +95,13 @@ Other Learner:
Inherited methods diff --git a/man/mlr_learners_torch.Rd b/man/mlr_learners_torch.Rd index e447cd5d..9ac265e2 100644 --- a/man/mlr_learners_torch.Rd +++ b/man/mlr_learners_torch.Rd @@ -24,7 +24,8 @@ The batch size. The number of epochs. \item \code{device} :: \code{character(1)}\cr The device. One of \code{"auto"}, \code{"cpu"}, or \code{"cuda"} or other values defined in \code{mlr_reflections$torch$devices}. -The value is initialized to \code{"auto"}, which will select \code{"cuda"} if possible and \code{"cpu"} otherwise. +The value is initialized to \code{"auto"}, which will select \code{"cuda"} if possible, then try \code{"mps"}, and otherwise +will fall back to \code{"cpu"}. \item \code{measures_train} :: \code{\link{Measure}} or \code{list()} of \code{\link{Measure}}s. Measures to be evaluated during training. \item \code{measures_valid} :: \code{\link{Measure}} or \code{list()} of \code{\link{Measure}}s. @@ -134,11 +135,13 @@ Shortcut for \code{learner$model$callbacks$history}.}
Inherited methods
}} diff --git a/man/mlr_learners_torch_image.Rd b/man/mlr_learners_torch_image.Rd index 033e94a5..bb090266 100644 --- a/man/mlr_learners_torch_image.Rd +++ b/man/mlr_learners_torch_image.Rd @@ -55,11 +55,13 @@ Other Learner:
Inherited methods diff --git a/man/mlr_learners_torch_model.Rd b/man/mlr_learners_torch_model.Rd index 55076a0a..ff6dba60 100644 --- a/man/mlr_learners_torch_model.Rd +++ b/man/mlr_learners_torch_model.Rd @@ -77,11 +77,13 @@ Other Graph Network:
Inherited methods diff --git a/man/mlr_pipeops_torch_model.Rd b/man/mlr_pipeops_torch_model.Rd index 3978d5cc..3bdbbac3 100644 --- a/man/mlr_pipeops_torch_model.Rd +++ b/man/mlr_pipeops_torch_model.Rd @@ -29,7 +29,8 @@ The batch size. The number of epochs. \item \code{device} :: \code{character(1)}\cr The device. One of \code{"auto"}, \code{"cpu"}, or \code{"cuda"} or other values defined in \code{mlr_reflections$torch$devices}. -The value is initialized to \code{"auto"}, which will select \code{"cuda"} if possible and \code{"cpu"} otherwise. +The value is initialized to \code{"auto"}, which will select \code{"cuda"} if possible, then try \code{"mps"}, and otherwise +will fall back to \code{"cpu"}. \item \code{measures_train} :: \code{\link{Measure}} or \code{list()} of \code{\link{Measure}}s. Measures to be evaluated during training. \item \code{measures_valid} :: \code{\link{Measure}} or \code{list()} of \code{\link{Measure}}s. From 88ad6981a5b880653e0b360697d5759316fc5162 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 26 Jan 2024 11:51:52 +0100 Subject: [PATCH 68/90] disable mps in gha tests --- NAMESPACE | 1 + R/utils.R | 7 +++++++ man/auto_device.Rd | 15 +++++++++++++++ man/mlr_learners_torch.Rd | 4 ++-- man/mlr_pipeops_torch_model.Rd | 4 ++-- tests/testthat/setup.R | 23 +++++++++++++++++++++++ tests/testthat/teardown.R | 2 ++ tests/testthat/test_LearnerTorch.R | 3 ++- 8 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 man/auto_device.Rd diff --git a/NAMESPACE b/NAMESPACE index f466be13..5ee8d543 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -135,6 +135,7 @@ export(as_torch_callback) export(as_torch_callbacks) export(as_torch_loss) export(as_torch_optimizer) +export(auto_device) export(batchgetter_categ) export(batchgetter_num) export(callback_set) diff --git a/R/utils.R b/R/utils.R index 3345e7af..fae42321 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1,3 +1,10 @@ +#' Auto Device +#' +#' First tries cuda, then mp, then cpu. +#' +#' @param device (`character(1)`)\cr +#' The device. If not `NULL`, is returned as is. +#' @export auto_device = function(device = NULL) { if (device == "auto") { device = if (cuda_is_available()) { diff --git a/man/auto_device.Rd b/man/auto_device.Rd new file mode 100644 index 00000000..cdf002a5 --- /dev/null +++ b/man/auto_device.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{auto_device} +\alias{auto_device} +\title{Auto Device} +\usage{ +auto_device(device = NULL) +} +\arguments{ +\item{device}{(\code{character(1)})\cr +The device. If not \code{NULL}, is returned as is.} +} +\description{ +First tries cuda, then mp, then cpu. +} diff --git a/man/mlr_learners_torch.Rd b/man/mlr_learners_torch.Rd index 9ac265e2..971ddf78 100644 --- a/man/mlr_learners_torch.Rd +++ b/man/mlr_learners_torch.Rd @@ -24,8 +24,8 @@ The batch size. The number of epochs. \item \code{device} :: \code{character(1)}\cr The device. One of \code{"auto"}, \code{"cpu"}, or \code{"cuda"} or other values defined in \code{mlr_reflections$torch$devices}. -The value is initialized to \code{"auto"}, which will select \code{"cuda"} if possible, then try \code{"mps"}, and otherwise -will fall back to \code{"cpu"}. +The value is initialized to \code{"auto"}, which will select \code{"cuda"} if possible, then try \code{"mps"} and otherwise +fall back to \code{"cpu"}. \item \code{measures_train} :: \code{\link{Measure}} or \code{list()} of \code{\link{Measure}}s. Measures to be evaluated during training. \item \code{measures_valid} :: \code{\link{Measure}} or \code{list()} of \code{\link{Measure}}s. diff --git a/man/mlr_pipeops_torch_model.Rd b/man/mlr_pipeops_torch_model.Rd index 3bdbbac3..62c0b767 100644 --- a/man/mlr_pipeops_torch_model.Rd +++ b/man/mlr_pipeops_torch_model.Rd @@ -29,8 +29,8 @@ The batch size. The number of epochs. \item \code{device} :: \code{character(1)}\cr The device. One of \code{"auto"}, \code{"cpu"}, or \code{"cuda"} or other values defined in \code{mlr_reflections$torch$devices}. -The value is initialized to \code{"auto"}, which will select \code{"cuda"} if possible, then try \code{"mps"}, and otherwise -will fall back to \code{"cpu"}. +The value is initialized to \code{"auto"}, which will select \code{"cuda"} if possible, then try \code{"mps"} and otherwise +fall back to \code{"cpu"}. \item \code{measures_train} :: \code{\link{Measure}} or \code{list()} of \code{\link{Measure}}s. Measures to be evaluated during training. \item \code{measures_valid} :: \code{\link{Measure}} or \code{list()} of \code{\link{Measure}}s. diff --git a/tests/testthat/setup.R b/tests/testthat/setup.R index 9fde85e8..210a285c 100644 --- a/tests/testthat/setup.R +++ b/tests/testthat/setup.R @@ -15,3 +15,26 @@ old_threshold = lg$threshold old_plan = future::plan() lg$set_threshold("warn") future::plan("sequential") + +prev_auto_device = mlr3torch::auto_device + +assignInNamespace(ns = "mlr3torch", x = "auto_device", value = function(device = NULL) { + if (device == "auto") { + device = if (cuda_is_available()) { + "cuda" + } else if (backends_mps_is_available() && identical(Sys.getenv("GITHUB_ACTIONS"), "true")) { + stop() + # We are not the only ones experiencing issues: + # https://discuss.pytorch.org/t/mps-back-end-out-of-memory-on-github-action/189773 + if (identical(Sys.getenv("GITHUB_ACTIONS"), "true") && nzchar(Sys.getenv("_R_CHECK_PACKAGE_NAME_", ""))) { + "cpu" + } else { + "mps" + } + } else { + "cpu" + } + lg$debug("Auto-detected device '%s'.", device) + } + return(device) +}) diff --git a/tests/testthat/teardown.R b/tests/testthat/teardown.R index 69101ac9..d9a7e54f 100644 --- a/tests/testthat/teardown.R +++ b/tests/testthat/teardown.R @@ -1,3 +1,5 @@ lg$set_threshold(old_threshold) future::plan(old_plan) lg_mlr3$set_threshold(old_threshold_mlr3) + +assignInNamespace(ns = "mlr3torch", x = "auto_device", value = prev_auto_device) diff --git a/tests/testthat/test_LearnerTorch.R b/tests/testthat/test_LearnerTorch.R index a20a53e5..18adc0d5 100644 --- a/tests/testthat/test_LearnerTorch.R +++ b/tests/testthat/test_LearnerTorch.R @@ -216,7 +216,8 @@ test_that("train parameters do what they should: classification and regression", seed = seed, measures_train = measures_train, measures_valid = measures_valid, - predict_type = switch(task_type, classif = "prob", regr = "response") + predict_type = switch(task_type, classif = "prob", regr = "response"), + device = "cpu" ) From 2f66af16edf64561978184fe3293a1f745df9f54 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 26 Jan 2024 12:09:33 +0100 Subject: [PATCH 69/90] ... --- tests/testthat/setup.R | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/testthat/setup.R b/tests/testthat/setup.R index 210a285c..8d1083a1 100644 --- a/tests/testthat/setup.R +++ b/tests/testthat/setup.R @@ -23,7 +23,6 @@ assignInNamespace(ns = "mlr3torch", x = "auto_device", value = function(device device = if (cuda_is_available()) { "cuda" } else if (backends_mps_is_available() && identical(Sys.getenv("GITHUB_ACTIONS"), "true")) { - stop() # We are not the only ones experiencing issues: # https://discuss.pytorch.org/t/mps-back-end-out-of-memory-on-github-action/189773 if (identical(Sys.getenv("GITHUB_ACTIONS"), "true") && nzchar(Sys.getenv("_R_CHECK_PACKAGE_NAME_", ""))) { From 285736c19d8ec82f48dc26671fe7095a8b56d73f Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 26 Jan 2024 12:47:15 +0100 Subject: [PATCH 70/90] run examples on cpu --- man-roxygen/learner_example.R | 2 +- man/mlr_learners.mlp.Rd | 2 +- man/mlr_learners.torch_featureless.Rd | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/man-roxygen/learner_example.R b/man-roxygen/learner_example.R index 2b7ab447..18637b8b 100644 --- a/man-roxygen/learner_example.R +++ b/man-roxygen/learner_example.R @@ -7,7 +7,7 @@ #' # Define the Learner and set parameter values #' <%= sprintf("learner = lrn(\"%s\")", id)%> #' learner$param_set$set_values( -#' <%= paste0(" ", paste0(c(param_vals, "batch_size = 1", "epochs = 1"), collapse = ", "))%> +#' <%= paste0(" ", paste0(c(param_vals, "batch_size = 1", "epochs = 1", device = "cpu"), collapse = ", "))%> #' ) #' #' # Define a Task diff --git a/man/mlr_learners.mlp.Rd b/man/mlr_learners.mlp.Rd index 86c71288..9366ff0c 100644 --- a/man/mlr_learners.mlp.Rd +++ b/man/mlr_learners.mlp.Rd @@ -65,7 +65,7 @@ Is initialized to \code{0.5}. # Define the Learner and set parameter values learner = lrn("classif.mlp") learner$param_set$set_values( - layers = 1, d_hidden = 10, batch_size = 1, epochs = 1 + layers = 1, d_hidden = 10, batch_size = 1, epochs = 1, cpu ) # Define a Task diff --git a/man/mlr_learners.torch_featureless.Rd b/man/mlr_learners.torch_featureless.Rd index 9e4a602c..974503f5 100644 --- a/man/mlr_learners.torch_featureless.Rd +++ b/man/mlr_learners.torch_featureless.Rd @@ -54,7 +54,7 @@ Only those from \code{\link{LearnerTorch}}. # Define the Learner and set parameter values learner = lrn("classif.torch_featureless") learner$param_set$set_values( - batch_size = 1, epochs = 1 + batch_size = 1, epochs = 1, cpu ) # Define a Task From 19aca8b701fe802b206c87c7844c571aceb2d384 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 26 Jan 2024 12:54:09 +0100 Subject: [PATCH 71/90] ... --- man-roxygen/learner_example.R | 2 +- man/mlr_learners.mlp.Rd | 2 +- man/mlr_learners.torch_featureless.Rd | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/man-roxygen/learner_example.R b/man-roxygen/learner_example.R index 18637b8b..f3e11c88 100644 --- a/man-roxygen/learner_example.R +++ b/man-roxygen/learner_example.R @@ -7,7 +7,7 @@ #' # Define the Learner and set parameter values #' <%= sprintf("learner = lrn(\"%s\")", id)%> #' learner$param_set$set_values( -#' <%= paste0(" ", paste0(c(param_vals, "batch_size = 1", "epochs = 1", device = "cpu"), collapse = ", "))%> +#' <%= paste0(" ", paste0(c(param_vals, "batch_size = 1", "epochs = 1", "device = \"cpu\""), collapse = ", "))%> #' ) #' #' # Define a Task diff --git a/man/mlr_learners.mlp.Rd b/man/mlr_learners.mlp.Rd index 9366ff0c..f6e9b0d7 100644 --- a/man/mlr_learners.mlp.Rd +++ b/man/mlr_learners.mlp.Rd @@ -65,7 +65,7 @@ Is initialized to \code{0.5}. # Define the Learner and set parameter values learner = lrn("classif.mlp") learner$param_set$set_values( - layers = 1, d_hidden = 10, batch_size = 1, epochs = 1, cpu + layers = 1, d_hidden = 10, batch_size = 1, epochs = 1, device = "cpu" ) # Define a Task diff --git a/man/mlr_learners.torch_featureless.Rd b/man/mlr_learners.torch_featureless.Rd index 974503f5..8b86364f 100644 --- a/man/mlr_learners.torch_featureless.Rd +++ b/man/mlr_learners.torch_featureless.Rd @@ -54,7 +54,7 @@ Only those from \code{\link{LearnerTorch}}. # Define the Learner and set parameter values learner = lrn("classif.torch_featureless") learner$param_set$set_values( - batch_size = 1, epochs = 1, cpu + batch_size = 1, epochs = 1, device = "cpu" ) # Define a Task From 466b4a07f7f249584f7c114c163032cdde49817b Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Fri, 26 Jan 2024 14:07:37 +0100 Subject: [PATCH 72/90] please run on macos --- R/LearnerTorchModel.R | 3 ++- R/TorchCallback.R | 3 ++- man/mlr_learners_torch_model.Rd | 3 ++- man/torch_callback.Rd | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/R/LearnerTorchModel.R b/R/LearnerTorchModel.R index b560d24a..41e4dea3 100644 --- a/R/LearnerTorchModel.R +++ b/R/LearnerTorchModel.R @@ -45,7 +45,8 @@ #' network = network, #' ingress_tokens = ingress_tokens, #' batch_size = 16, -#' epochs = 1 +#' epochs = 1, +#' device = "cpu" #' ) #' #' # A simple train-predict diff --git a/R/TorchCallback.R b/R/TorchCallback.R index f67de1e5..37ca32f8 100644 --- a/R/TorchCallback.R +++ b/R/TorchCallback.R @@ -264,7 +264,8 @@ TorchCallback = R6Class("TorchCallback", #' batch_size = 16, #' epochs = 1, #' callbacks = custom_tcb, -#' cb.custom.name = "Marie" +#' cb.custom.name = "Marie", +#' device = "cpu" #' ) #' task = tsk("iris") #' learner$train(task) diff --git a/man/mlr_learners_torch_model.Rd b/man/mlr_learners_torch_model.Rd index ff6dba60..f203aae8 100644 --- a/man/mlr_learners_torch_model.Rd +++ b/man/mlr_learners_torch_model.Rd @@ -31,7 +31,8 @@ learner = lrn("classif.torch_model", network = network, ingress_tokens = ingress_tokens, batch_size = 16, - epochs = 1 + epochs = 1, + device = "cpu" ) # A simple train-predict diff --git a/man/torch_callback.Rd b/man/torch_callback.Rd index a2ad80e6..2699389d 100644 --- a/man/torch_callback.Rd +++ b/man/torch_callback.Rd @@ -119,7 +119,8 @@ learner = lrn("classif.torch_featureless", batch_size = 16, epochs = 1, callbacks = custom_tcb, - cb.custom.name = "Marie" + cb.custom.name = "Marie", + device = "cpu" ) task = tsk("iris") learner$train(task) From 9992ab9d883c8d9f32e889c6a4cc279115c4a9e5 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Sat, 27 Jan 2024 18:53:04 +0100 Subject: [PATCH 73/90] clone is FALSE --- R/DataDescriptor.R | 2 +- R/PipeOpTorchIngress.R | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index aad09d92..a98743b2 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -93,7 +93,7 @@ DataDescriptor = R6Class("DataDescriptor", # get unique ID for input PipeOp graph = as_graph(po("nop", id = paste0("nop.", calculate_hash(address(dataset)), ".", input_map) - )) + ), clone = FALSE) } else { graph = as_graph(graph, clone = clone_graph) assert_true(length(graph$pipeops) >= 1L) diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index 65935fb4..1483bc6d 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -57,7 +57,7 @@ PipeOpTorchIngress = R6Class("PipeOpTorchIngress", stopf("No missing values allowed in task '%s'.", task$id) } param_vals = self$param_set$get_values() - graph = as_graph(po("nop", id = self$id)) + graph = as_graph(po("nop", id = self$id), clone = FALSE) batchgetter = private$.get_batchgetter(task, param_vals) # In case the user is tempted to do things that will break in bad ways... From 9f2450a451db483a5615dc7023e94bded302cb14 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 30 Jan 2024 09:35:43 +0100 Subject: [PATCH 74/90] lazy tensor --- NAMESPACE | 3 +- R/PipeOpTaskPreprocTorch.R | 41 +++-------- R/lazy_tensor.R | 63 +++++++++++++---- R/utils.R | 4 -- man/assert_lazy_tensor.Rd | 15 ++++ man/equals-.lazy_tensor.Rd | 20 ++++++ man/mlr_learners.alexnet.Rd | 2 - man/mlr_learners.mlp.Rd | 2 - man/mlr_learners.torch_featureless.Rd | 2 - man/mlr_learners_torch.Rd | 2 - man/mlr_learners_torch_image.Rd | 2 - man/mlr_learners_torch_model.Rd | 2 - man/mlr_pipeops_preproc_torch.Rd | 2 +- man/pipeop_preproc_torch.Rd | 18 +++-- man/pipeop_preproc_torch_class.Rd | 73 -------------------- tests/testthat/helper_pipeop.R | 2 +- tests/testthat/test_PipeOpTaskPreprocTorch.R | 28 ++++---- tests/testthat/test_lazy_tensor.R | 54 ++++++++++++--- tests/testthat/test_materialize.R | 2 +- tests/testthat/test_task_dataset.R | 4 +- 20 files changed, 168 insertions(+), 173 deletions(-) create mode 100644 man/assert_lazy_tensor.Rd create mode 100644 man/equals-.lazy_tensor.Rd delete mode 100644 man/pipeop_preproc_torch_class.Rd diff --git a/NAMESPACE b/NAMESPACE index 5ee8d543..0333a793 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,6 @@ # Generated by roxygen2: do not edit by hand +S3method("==",lazy_tensor) S3method("[",lazy_tensor) S3method("[<-",lazy_tensor) S3method("[[",lazy_tensor) @@ -135,6 +136,7 @@ export(as_torch_callback) export(as_torch_callbacks) export(as_torch_loss) export(as_torch_optimizer) +export(assert_lazy_tensor) export(auto_device) export(batchgetter_categ) export(batchgetter_num) @@ -156,7 +158,6 @@ export(nn_reshape) export(nn_squeeze) export(nn_unsqueeze) export(pipeop_preproc_torch) -export(pipeop_preproc_torch_class) export(reset_last_layer) export(t_clbk) export(t_clbks) diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 695e4f4a..f723164f 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -8,7 +8,7 @@ #' The preprocessing is done per column, i.e. the number of lazy tensor output columns is equal #' to the number of lazy tensor input columns. #' -#' To create custom preprocessing `PipeOp`s you can use [`pipeop_preproc_torch`] / [`pipeop_preproc_torch_class`]. +#' To create custom preprocessing `PipeOp`s you can use [`pipeop_preproc_torch`]. #' #' @section Inheriting: #' In addition to specifying the construction arguments, you can overwrite the private `.shapes_out()` method. @@ -369,29 +369,6 @@ PipeOpTaskPreprocTorch = R6Class("PipeOpTaskPreprocTorch", .fn = NULL ) ) -#' @title Create Torch Preprocessing PipeOps -#' @description -#' Calls [`pipeop_preproc_torch_class`] and instantiates the instance with the given parameter values. -#' @inheritParams pipeop_preproc_torch_class -#' @template param_param_vals -#' @param param_vals (`list()`)\cr -#' The parameter values. -#' @export -pipeop_preproc_torch = function(id, fn, shapes_out = NULL, param_set = NULL, param_vals = list(), packages = character(0), - rowwise = FALSE, parent_env = parent.frame(), stages_init = NULL, tags = NULL) { - pipeop_preproc_torch_class( - id = id, - fn = fn, - shapes_out = shapes_out, - param_set = param_set, - packages = packages, - rowwise = rowwise, - parent_env = parent_env, - stages_init = stages_init, - tags = tags - )$new(param_vals = param_vals) -} - create_ps = function(fn) { fmls = formals(fn) @@ -416,8 +393,9 @@ create_ps = function(fn) { #' @title Create Torch Preprocessing PipeOps #' @description -#' Function to create objects of class [`PipeOpTaskPreprocTorch`] in a slightly more convenient way. +#' Function to create objects of class [`PipeOpTaskPreprocTorch`] in a more convenient way. #' Start by reading the documentation of [`PipeOpTaskPreprocTorch`]. +#' #' @template param_id #' @param fn (`function`)\cr #' The preprocessing function. @@ -429,9 +407,8 @@ create_ps = function(fn) { #' If "infer", the output shape function is inferred and calculates the output shapes as follows: #' For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is #' applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. -#' If the first dimension is not `NA`, the output shape of applying the preprocessing function is returned. -#' -#' This should be correct in most cases, but might fail in some edge cases. +#' If the first dimension is not `NA`, the output shape of applying the preprocessing function is returned. +#' Method `"infer"` should be correct in most cases, but might fail in some edge cases. #' @param param_set ([`ParamSet`] or `NULL`)\cr #' The parameter set. #' If this is left as `NULL` (default) the parameter set is inferred in the following way: @@ -452,10 +429,10 @@ create_ps = function(fn) { #' @export #' @returns An [`R6Class`][R6::R6Class] instance inheriting from [`PipeOpTaskPreprocTorch`] #' @examples -#' po_example = pipeop_preproc_torch("preproc_example", function(x, a) x + a, ) -#' po_example +#' PipeOpPreprocExample = pipeop_preproc_torch("preproc_example", function(x, a) x + a, ) +#' po_example = PipeOpPreprocExample$new() #' po_example$param_set -pipeop_preproc_torch_class = function(id, fn, shapes_out, param_set = NULL, packages = character(0), +pipeop_preproc_torch = function(id, fn, shapes_out = NULL, param_set = NULL, packages = character(0), rowwise = FALSE, parent_env = parent.frame(), stages_init = NULL, tags = NULL) { assert( check_function(shapes_out, args = c("shapes_in", "param_vals", "task"), null.ok = TRUE), @@ -570,7 +547,7 @@ register_preproc = function(id, fn, param_set = NULL, shapes_out = NULL, package fn = as.character(as.list(fn_call)[-1L]) } - Class = pipeop_preproc_torch_class(id, fn, param_set = param_set, shapes_out = shapes_out, + Class = pipeop_preproc_torch(id, fn, param_set = param_set, shapes_out = shapes_out, packages = packages, rowwise = rowwise, parent_env = parent.frame()) assign(Class$classname, Class, parent.frame()) register_po(id, Class) diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index ded5e087..bf198c3d 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -41,18 +41,15 @@ new_lazy_tensor = function(data_descriptor, ids) { #' @export `[<-.lazy_tensor` = function(x, i, value) { - assert_true(is_lazy_tensor(value)) - # no compatibility check - if (length(x) == 0) { - x = unclass(x) - x[i] = value - return(structure(x, class = c("lazy_tensor", "list"))) - } - if (length(value) == 0L) { - assert_true(length(i) == 0L) - return(x) + # avoid degenerate lazy tensors after assignment + assert_lazy_tensor(value) + assert_integerish(i) + assert_true(max(i) <= length(x)) # otherwise checks get ugly + + if (!(length(x) == 0 || length(value) == 0) && !identical(dd(x), dd(value))) { + stopf("Cannot assign lazy tensor with different data descriptor") } - assert_true(identical(dd(x)$hash, dd(value)$hash)) + x = unclass(x) x[i] = value structure(x, class = c("lazy_tensor", "list")) @@ -60,11 +57,12 @@ new_lazy_tensor = function(data_descriptor, ids) { #' @export `[[<-.lazy_tensor` = function(x, i, value) { - assert_true(is_lazy_tensor(value)) + # We ensure that there are no degenerate entries in a lazy tensor + assert_lazy_tensor(value) assert_true(length(value) == 1L) - assert_true(length(i) == 1L) - assert_true(length(x) >= 1L) - assert_true(identical(dd(x)$hash), dd(value)$hash) + assert_int(i) + assert_true(i <= length(x) + 1L) + assert(check_true(length(x) == 0), check_true(identical(dd(x), dd(value))), combine = "or") x = unclass(x) x[[i]] = value structure(x, class = c("lazy_tensor", "list")) @@ -163,6 +161,18 @@ as_lazy_tensor.torch_tensor = function(x, ...) { # nolint as_lazy_tensor(ds, dataset_shapes = list(x = c(NA, dim(x)[-1]))) } +#' Assert Lazy Tensor +#' +#' Asserts whether something is a lazy tensor. +#' +#' @param x (any)\cr +#' Object to check. +#' @export +assert_lazy_tensor = function(x) { + assert_class(x, "lazy_tensor") +} + + #' @title Check for lazy tensor #' @description #' Checks whether an object is a lazy tensor. @@ -262,3 +272,26 @@ hash_input.lazy_tensor = function(x) { list() } } + + +#' Compare lazy tensors +#' @description +#' Compares lazy tensors using their indices and the data descriptor's hash. +#' This means that if two [`lazy_tensor`]s: +#' * are equal: they will mateterialize to the same tensors. +#' * are unequal: they might materialize to the same tensors. +#' @param x, y ([`lazy_tensor`])\cr +#' Values to compare. +#' @export +`==.lazy_tensor` = function(x, y) { + if (length(x) == 0L && length(y) == 0L) { + return(logical(0)) + } + assert_true(length(x) >= 0 && length(y) >= 0) + n = max(length(x), length(y)) + + if (dd(x)$hash != dd(y)$hash) { + return(rep(FALSE, n)) + } + map_int(x, 1L) == map_int(y, 1L) +} diff --git a/R/utils.R b/R/utils.R index fae42321..2b5cab4d 100644 --- a/R/utils.R +++ b/R/utils.R @@ -157,10 +157,6 @@ argument_matcher = function(args) { fn } -assert_lazy_tensor = function(x) { - assert_class(x, "lazy_tensor") -} - uniqueify = function(new, existing) { make.unique(c(existing, new), sep = "_")[length(existing) + seq_along(new)] } diff --git a/man/assert_lazy_tensor.Rd b/man/assert_lazy_tensor.Rd new file mode 100644 index 00000000..77945f09 --- /dev/null +++ b/man/assert_lazy_tensor.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lazy_tensor.R +\name{assert_lazy_tensor} +\alias{assert_lazy_tensor} +\title{Assert Lazy Tensor} +\usage{ +assert_lazy_tensor(x) +} +\arguments{ +\item{x}{(any)\cr +Object to check.} +} +\description{ +Asserts whether something is a lazy tensor. +} diff --git a/man/equals-.lazy_tensor.Rd b/man/equals-.lazy_tensor.Rd new file mode 100644 index 00000000..df14314e --- /dev/null +++ b/man/equals-.lazy_tensor.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lazy_tensor.R +\name{==.lazy_tensor} +\alias{==.lazy_tensor} +\title{Compare lazy tensors} +\usage{ +\method{==}{lazy_tensor}(x, y) +} +\arguments{ +\item{x, }{y (\code{\link{lazy_tensor}})\cr +Values to compare.} +} +\description{ +Compares lazy tensors using their indices and the data descriptor's hash. +This means that if two \code{\link{lazy_tensor}}s: +\itemize{ +\item are equal: they will mateterialize to the same tensors. +\item are unequal: they might materialize to the same tensors. +} +} diff --git a/man/mlr_learners.alexnet.Rd b/man/mlr_learners.alexnet.Rd index 2b800a3c..c477ef17 100644 --- a/man/mlr_learners.alexnet.Rd +++ b/man/mlr_learners.alexnet.Rd @@ -78,13 +78,11 @@ Other Learner:
Inherited methods diff --git a/man/mlr_learners.mlp.Rd b/man/mlr_learners.mlp.Rd index f6e9b0d7..a13ba4c5 100644 --- a/man/mlr_learners.mlp.Rd +++ b/man/mlr_learners.mlp.Rd @@ -106,13 +106,11 @@ Other Learner:
Inherited methods diff --git a/man/mlr_learners.torch_featureless.Rd b/man/mlr_learners.torch_featureless.Rd index 8b86364f..e77f5a44 100644 --- a/man/mlr_learners.torch_featureless.Rd +++ b/man/mlr_learners.torch_featureless.Rd @@ -95,13 +95,11 @@ Other Learner:
Inherited methods diff --git a/man/mlr_learners_torch.Rd b/man/mlr_learners_torch.Rd index 971ddf78..3b18b5f0 100644 --- a/man/mlr_learners_torch.Rd +++ b/man/mlr_learners_torch.Rd @@ -135,13 +135,11 @@ Shortcut for \code{learner$model$callbacks$history}.}
Inherited methods
}} diff --git a/man/mlr_learners_torch_image.Rd b/man/mlr_learners_torch_image.Rd index bb090266..033e94a5 100644 --- a/man/mlr_learners_torch_image.Rd +++ b/man/mlr_learners_torch_image.Rd @@ -55,13 +55,11 @@ Other Learner:
Inherited methods diff --git a/man/mlr_learners_torch_model.Rd b/man/mlr_learners_torch_model.Rd index f203aae8..90c8922d 100644 --- a/man/mlr_learners_torch_model.Rd +++ b/man/mlr_learners_torch_model.Rd @@ -78,13 +78,11 @@ Other Graph Network:
Inherited methods diff --git a/man/mlr_pipeops_preproc_torch.Rd b/man/mlr_pipeops_preproc_torch.Rd index 71be0125..ccb219ea 100644 --- a/man/mlr_pipeops_preproc_torch.Rd +++ b/man/mlr_pipeops_preproc_torch.Rd @@ -11,7 +11,7 @@ function can be defined through the \code{PipeOp}'s parameter set. The preprocessing is done per column, i.e. the number of lazy tensor output columns is equal to the number of lazy tensor input columns. -To create custom preprocessing \code{PipeOp}s you can use \code{\link{pipeop_preproc_torch}} / \code{\link{pipeop_preproc_torch_class}}. +To create custom preprocessing \code{PipeOp}s you can use \code{\link{pipeop_preproc_torch}}. } \section{Inheriting}{ diff --git a/man/pipeop_preproc_torch.Rd b/man/pipeop_preproc_torch.Rd index beceb500..913d28eb 100644 --- a/man/pipeop_preproc_torch.Rd +++ b/man/pipeop_preproc_torch.Rd @@ -9,7 +9,6 @@ pipeop_preproc_torch( fn, shapes_out = NULL, param_set = NULL, - param_vals = list(), packages = character(0), rowwise = FALSE, parent_env = parent.frame(), @@ -33,8 +32,7 @@ If "infer", the output shape function is inferred and calculates the output shap For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. If the first dimension is not \code{NA}, the output shape of applying the preprocessing function is returned. - -This should be correct in most cases, but might fail in some edge cases.} +Method \code{"infer"} should be correct in most cases, but might fail in some edge cases.} \item{param_set}{(\code{\link{ParamSet}} or \code{NULL})\cr The parameter set. @@ -43,9 +41,6 @@ All parameters but the first and \code{...} of \code{fn} are set as untyped para have no default value are tagged as 'required' as well. Default values are not annotated.} -\item{param_vals}{(\code{list()})\cr -The parameter values.} - \item{packages}{(\code{character()})\cr The R packages this object depends on.} @@ -63,6 +58,15 @@ if it starts with \code{"augment"}. Otherwise it must specified.} \item{tags}{(\code{character()})\cr Tags for the pipeop} } +\value{ +An \code{\link[R6:R6Class]{R6Class}} instance inheriting from \code{\link{PipeOpTaskPreprocTorch}} +} \description{ -Calls \code{\link{pipeop_preproc_torch_class}} and instantiates the instance with the given parameter values. +Function to create objects of class \code{\link{PipeOpTaskPreprocTorch}} in a more convenient way. +Start by reading the documentation of \code{\link{PipeOpTaskPreprocTorch}}. +} +\examples{ +PipeOpPreprocExample = pipeop_preproc_torch("preproc_example", function(x, a) x + a, ) +po_example = PipeOpPreprocExample$new() +po_example$param_set } diff --git a/man/pipeop_preproc_torch_class.Rd b/man/pipeop_preproc_torch_class.Rd deleted file mode 100644 index 2a757d42..00000000 --- a/man/pipeop_preproc_torch_class.Rd +++ /dev/null @@ -1,73 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTaskPreprocTorch.R -\name{pipeop_preproc_torch_class} -\alias{pipeop_preproc_torch_class} -\title{Create Torch Preprocessing PipeOps} -\usage{ -pipeop_preproc_torch_class( - id, - fn, - shapes_out, - param_set = NULL, - packages = character(0), - rowwise = FALSE, - parent_env = parent.frame(), - stages_init = NULL, - tags = NULL -) -} -\arguments{ -\item{id}{(\code{character(1)})\cr -The id for of the new object.} - -\item{fn}{(\code{function})\cr -The preprocessing function.} - -\item{shapes_out}{(\code{function} or \code{NULL} or \code{"infer"} or \code{"unchanged"})\cr -The private \code{.shapes_out(shapes_in, param_vals, task)} method of \code{\link{PipeOpTaskPreprocTorch}} -(see section Inheriting). -Special values are \code{NULL} and \code{infer}: -If \code{NULL}, the output shapes are unknown. -If "infer", the output shape function is inferred and calculates the output shapes as follows: -For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is -applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. -If the first dimension is not \code{NA}, the output shape of applying the preprocessing function is returned. - -This should be correct in most cases, but might fail in some edge cases.} - -\item{param_set}{(\code{\link{ParamSet}} or \code{NULL})\cr -The parameter set. -If this is left as \code{NULL} (default) the parameter set is inferred in the following way: -All parameters but the first and \code{...} of \code{fn} are set as untyped parameters with tags 'train' and those that -have no default value are tagged as 'required' as well. -Default values are not annotated.} - -\item{packages}{(\code{character()})\cr -The R packages this object depends on.} - -\item{rowwise}{(\code{logical(1)})\cr -Whether the preprocessing is applied row-wise.} - -\item{parent_env}{(\code{environment})\cr -The parent environment for the R6 class.} - -\item{stages_init}{(\code{character(1)})\cr -Initial value for the \code{stages} parameter. -If \code{NULL} (default), will be set to \code{"both"} in case the \code{id} starts with \code{"trafo"} and to \code{"train"} -if it starts with \code{"augment"}. Otherwise it must specified.} - -\item{tags}{(\code{character()})\cr -Tags for the pipeop} -} -\value{ -An \code{\link[R6:R6Class]{R6Class}} instance inheriting from \code{\link{PipeOpTaskPreprocTorch}} -} -\description{ -Function to create objects of class \code{\link{PipeOpTaskPreprocTorch}} in a slightly more convenient way. -Start by reading the documentation of \code{\link{PipeOpTaskPreprocTorch}}. -} -\examples{ -po_example = pipeop_preproc_torch("preproc_example", function(x, a) x + a, ) -po_example -po_example$param_set -} diff --git a/tests/testthat/helper_pipeop.R b/tests/testthat/helper_pipeop.R index 156decec..a9bbec83 100644 --- a/tests/testthat/helper_pipeop.R +++ b/tests/testthat/helper_pipeop.R @@ -45,7 +45,7 @@ PipeOpTorchDebug = R6Class("PipeOpTorchDebug", ) ) -PipeOpPreprocTorchAddSome = pipeop_preproc_torch_class("trafo_some", +PipeOpPreprocTorchAddSome = pipeop_preproc_torch("trafo_some", param_set = ps(some = p_dbl(default = 1L, tags = "train")), fn = crate(function(x, some = 1L) x + some), shapes_out = "unchanged" diff --git a/tests/testthat/test_PipeOpTaskPreprocTorch.R b/tests/testthat/test_PipeOpTaskPreprocTorch.R index c7bb4e27..5b16bd83 100644 --- a/tests/testthat/test_PipeOpTaskPreprocTorch.R +++ b/tests/testthat/test_PipeOpTaskPreprocTorch.R @@ -108,10 +108,10 @@ test_that("basic", { po_test3 = pipeop_preproc_torch("test3", rowwise = FALSE, fn = function(x) x$reshape(-1), shapes_out = NULL, stages_init = "both" - ) + )$new() po_test4 = pipeop_preproc_torch("test4", rowwise = TRUE, fn = function(x) x$reshape(-1), shapes_out = NULL, stages_init = "both" - ) + )$new() expect_equal( materialize(po_test3$train(list(task))[[1L]]$data(cols = "x1")$x1, rbind = TRUE)$shape, @@ -129,7 +129,7 @@ test_that("rowwise works", { expect_true(nrow(x) == 150L) x } - po_rowwise = pipeop_preproc_torch("test3", fn = fn_rowwise, rowwise = FALSE, shapes_out = NULL, stages_init = "both") + po_rowwise = pipeop_preproc_torch("test3", fn = fn_rowwise, rowwise = FALSE, shapes_out = NULL, stages_init = "both")$new() # nolint taskout = po_rowwise$train(list(task))[[1L]] expect_error(materialize(taskout$data()$x), regexp = NA) @@ -138,7 +138,7 @@ test_that("rowwise works", { expect_true(all.equal(x$shape, 4)) x } - po_batchwise = pipeop_preproc_torch("test3", fn = fn_batchwise, rowwise = TRUE, shapes_out = NULL, stages_init = "both") + po_batchwise = pipeop_preproc_torch("test3", fn = fn_batchwise, rowwise = TRUE, shapes_out = NULL, stages_init = "both")$new() # nolint taskout2 = po_batchwise$train(list(task))[[1L]] expect_error(materialize(taskout2$data()$x), regexp = NA) }) @@ -212,7 +212,7 @@ test_that("pipeop_preproc_torch", { list(s) }, stages_init = "both" - ) + )$new() expect_true("required" %in% po_test$param_set$tags$a) expect_class(po_test, "PipeOpPreprocTorchTrafoAbc") @@ -235,41 +235,41 @@ test_that("pipeop_preproc_torch", { expect_torch_equal(x[1, 2]$item(), 1) po_test1 = pipeop_preproc_torch("test1", torchvision::transform_resize, shapes_out = "infer", - param_vals = list(size = c(10, 10)), stages_init = "both" - ) + stages_init = "both" + )$new(param_vals = list(size = c(10, 10))) size = po_test1$shapes_out(list(c(NA, 20, 20)), "train") expect_equal(size, list(c(NA, 10, 10))) - expect_true(pipeop_preproc_torch("test3", identity, rowwise = TRUE, shapes_out = NULL, stages_init = "both")$rowwise) - expect_false(pipeop_preproc_torch("test3", identity, rowwise = FALSE, shapes_out = NULL, stages_init = "both")$rowwise) + expect_true(pipeop_preproc_torch("test3", identity, rowwise = TRUE, shapes_out = NULL, stages_init = "both")$new()$rowwise) + expect_false(pipeop_preproc_torch("test3", identity, rowwise = FALSE, shapes_out = NULL, stages_init = "both")$new()$rowwise) # stages_init works expect_equal(pipeop_preproc_torch( - "test3", identity, rowwise = TRUE, shapes_out = NULL, stages_init = "both")$param_set$values$stages, + "test3", identity, rowwise = TRUE, shapes_out = NULL, stages_init = "both")$new()$param_set$values$stages, "both" ) expect_equal(pipeop_preproc_torch( - "test3", identity, rowwise = TRUE, shapes_out = NULL, stages_init = "train")$param_set$values$stages, + "test3", identity, rowwise = TRUE, shapes_out = NULL, stages_init = "train")$new()$param_set$values$stages, "train" ) # tags work expect_set_equal(pipeop_preproc_torch( - "test3", identity, rowwise = TRUE, shapes_out = NULL, stages_init = "train", tags = c("learner", "encode"))$tags, + "test3", identity, rowwise = TRUE, shapes_out = NULL, stages_init = "train", tags = c("learner", "encode"))$new()$tags, c("learner", "encode", "data transform", "torch") ) }) test_that("can pass variable to fn", { fn = function(x, a) x + a - po_test = pipeop_preproc_torch("test", fn = fn, shapes_out = "infer", stages_init = "train", param_vals = list(a = 1000)) + po_test = pipeop_preproc_torch("test", fn = fn, shapes_out = "infer", stages_init = "train", )$new(param_vals = list(a = 1000)) x = po_test$train(list(tsk("lazy_iris")$filter(1)))[[1L]]$data()$x expect_true(all(as_array(materialize(x, rbind = TRUE)) >= 50)) }) test_that("predict shapes are added during training", { - po_test = pipeop_preproc_torch("test", fn = function(x) torch_cat(list(x, x * 2), dim = 2), shapes_out = "infer") + po_test = pipeop_preproc_torch("test", fn = function(x) torch_cat(list(x, x * 2), dim = 2), shapes_out = "infer")$new() po_test$param_set$set_values( stages = "train" diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index e98ee0c5..c3cc32f8 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -1,4 +1,20 @@ -test_that("Unknown shapes", { +test_that("prototype", { + proto = lazy_tensor() + expect_class(proto, "lazy_tensor") + expect_true(length(proto) == 0L) + expect_error(dd(proto)) + + expect_error(materialize(lazy_tensor()), "Cannot materialize") +}) + +test_that("input checks", { + desc = dd(as_lazy_tensor(1:10)) + expect_error(lazy_tensor(desc, 1:11), "ids") + expect_error(lazy_tensor(desc, NA), "missing values") +}) + + +test_that("unknown shapes", { ds = dataset( initialize = function() { self$x = list( @@ -39,6 +55,18 @@ test_that("assignment", { materialize(x[1], rbind = TRUE), materialize(x[2], rbind = TRUE) ) + # cannot assign beyond vector length + expect_error({x[3] = as_lazy_tensor(1)}, "max") # nolint + expect_error({x[2] = 1}, "class") # nolint + # indices must be ints + expect_error({x["hallo"] = as_lazy_tensor(1)}, "integerish") # nolint + expect_error({x[1] = as_lazy_tensor(10)}, "data descriptor") + + + y = lazy_tensor() + y[[1]] = as_lazy_tensor(1) + expect_class(y, "lazy_tensor") + expect_true(length(y) == 1) expect_error({x[1] = as_lazy_tensor(1)}) # nolint }) @@ -52,6 +80,11 @@ test_that("concatenation", { x = c(x1, x1) expect_class(x, "lazy_tensor") expect_equal(length(x), 2) + + # can still concatenate lazy tensor with other objects + l = list(1, x) + expect_class(l, "list") + expect_false(inherits(l, "lazy_tensor")) }) test_that("subsetting and indexing", { @@ -64,15 +97,6 @@ test_that("subsetting and indexing", { }) -test_that("prototype", { - proto = lazy_tensor() - expect_class(proto, "lazy_tensor") - expect_true(length(proto) == 0L) - expect_error(dd(proto)) - - expect_error(materialize(lazy_tensor()), "Cannot materialize") -}) - test_that("transform_lazy_tensor", { lt = as_lazy_tensor(torch_randn(16, 2, 5)) lt_mat = materialize(lt, rbind = TRUE) @@ -179,3 +203,13 @@ test_that("printer", { c("", "[1] ") ) }) + +test_that("comparison", { + x = as_lazy_tensor(1:2) + # diffe + y = as_lazy_tensor(1:2) + expect_equal(x == x, c(TRUE, TRUE)) + expect_equal(x[2:1] == x, c(FALSE, FALSE)) + expect_equal(x[c(1, 1)] == x, c(TRUE, FALSE)) + expect_equal(x == y, c(FALSE, FALSE)) +}) diff --git a/tests/testthat/test_materialize.R b/tests/testthat/test_materialize.R index 46807452..d939abc2 100644 --- a/tests/testthat/test_materialize.R +++ b/tests/testthat/test_materialize.R @@ -158,7 +158,7 @@ test_that("materialize with varying shapes", { a <<- a - 1 x * a }, .parent = e) - po_test = pipeop_preproc_torch("trafo_test", fn = fn) + po_test = pipeop_preproc_torch("trafo_test", fn = fn)$new() # is processed batch-wise -> task2 = po_test$train(list(nano_mnist()$filter(1:2)))[[1L]] diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index 82e98517..d7f886a2 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -268,7 +268,7 @@ test_that("cachine of graph", { env$counter = env$counter + 1L x + 1 }, env) - po_test = pipeop_preproc_torch("test", fn = fn, shapes_out = "unchanged", stages_init = "both") + po_test = pipeop_preproc_torch("test", fn = fn, shapes_out = "unchanged", stages_init = "both")$new() expect_true(is.function(po_test$fn)) @@ -302,7 +302,7 @@ test_that("merging of graphs behaves as expected", { a <<- a + 1 x }, .parent = e) - graph = pipeop_preproc_torch("trafo_counter", fn = fn) %>>% + graph = pipeop_preproc_torch("trafo_counter", fn = fn)$new() %>>% list( po("renamecolumns", renaming = c(x = "x1"), id = "a1") %>>% po("trafo_nop", id = "nop1"), po("renamecolumns", renaming = c(x = "x2"), id = "a2") %>>% po("trafo_nop", id = "nop2") From 09957f87e08097d85b68e8de9cc19f0af20d2bc2 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 30 Jan 2024 09:57:04 +0100 Subject: [PATCH 75/90] fix docs --- R/lazy_tensor.R | 2 +- man/equals-.lazy_tensor.Rd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index bf198c3d..0912eb32 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -280,7 +280,7 @@ hash_input.lazy_tensor = function(x) { #' This means that if two [`lazy_tensor`]s: #' * are equal: they will mateterialize to the same tensors. #' * are unequal: they might materialize to the same tensors. -#' @param x, y ([`lazy_tensor`])\cr +#' @param x,y ([`lazy_tensor`])\cr #' Values to compare. #' @export `==.lazy_tensor` = function(x, y) { diff --git a/man/equals-.lazy_tensor.Rd b/man/equals-.lazy_tensor.Rd index df14314e..9be38b0c 100644 --- a/man/equals-.lazy_tensor.Rd +++ b/man/equals-.lazy_tensor.Rd @@ -7,7 +7,7 @@ \method{==}{lazy_tensor}(x, y) } \arguments{ -\item{x, }{y (\code{\link{lazy_tensor}})\cr +\item{x, y}{(\code{\link{lazy_tensor}})\cr Values to compare.} } \description{ From 671e5c7d1d01d3df90e669c9655c56e84be70e50 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 30 Jan 2024 17:04:59 +0100 Subject: [PATCH 76/90] ... --- R/DataDescriptor.R | 6 +- R/LearnerTorchMLP.R | 99 ++++++----- R/PipeOpTaskPreprocTorch.R | 16 +- R/PipeOpTorchIngress.R | 2 +- R/preprocess.R | 131 +++++++++----- R/shape.R | 28 ++- R/utils.R | 33 +++- README.Rmd | 3 +- README.md | 5 +- man/PipeOpPreprocTorchTrafoScale.Rd | 12 ++ man/mlr_learners.mlp.Rd | 15 +- man/pipeop_preproc_torch.Rd | 2 +- tests/testthat/helper_autotest.R | 29 ++- tests/testthat/helper_pipeop.R | 2 +- tests/testthat/test_CallbackSet.R | 2 +- tests/testthat/test_CallbackSetCheckpoint.R | 4 +- tests/testthat/test_CallbackSetHistory.R | 4 +- tests/testthat/test_CallbackSetProgress.R | 2 +- tests/testthat/test_DataDescriptor.R | 6 + tests/testthat/test_LearnerTorchMLP.R | 16 +- tests/testthat/test_PipeOpTorchIngress.R | 6 + tests/testthat/test_lazy_tensor.R | 3 - tests/testthat/test_learner_torch_methods.R | 2 +- tests/testthat/test_preprocess.R | 2 +- tests/testthat/test_shape.R | 1 + tests/testthat/test_task_dataset.R | 4 +- vignettes/get_started.Rmd | 6 +- vignettes/lazy_tensor.Rmd | 186 ++++++++++++++++++++ 28 files changed, 474 insertions(+), 153 deletions(-) create mode 100644 man/PipeOpPreprocTorchTrafoScale.Rd create mode 100644 vignettes/lazy_tensor.Rmd diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index a98743b2..922b9a18 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -57,11 +57,9 @@ DataDescriptor = R6Class("DataDescriptor", pointer_shape = NULL, pointer_shape_predict = NULL, clone_graph = TRUE) { assert_class(dataset, "dataset") assert_flag(clone_graph) - # If the dataset implements a .getbatch() method the shape must be specified, as it should be the same for - # all batches # For simplicity we here require the first dimension of the shape to be NA so we don't have to deal with it, # e.g. during subsetting - assert_shapes(dataset_shapes, null_ok = is.null(dataset$.getbatch), unknown_batch = TRUE, named = TRUE) + assert_shapes(dataset_shapes, null_ok = TRUE, unknown_batch = TRUE, named = TRUE) # prevent user from e.g. forgetting to wrap the return in a list example = if (is.null(dataset$.getbatch)) { @@ -92,7 +90,7 @@ DataDescriptor = R6Class("DataDescriptor", } # get unique ID for input PipeOp graph = as_graph(po("nop", id = - paste0("nop.", calculate_hash(address(dataset)), ".", input_map) + paste0("nop.", substr(calculate_hash(address(dataset)), 1, 4)) ), clone = FALSE) } else { graph = as_graph(graph, clone = clone_graph) diff --git a/R/LearnerTorchMLP.R b/R/LearnerTorchMLP.R index dddee35f..22f61cba 100644 --- a/R/LearnerTorchMLP.R +++ b/R/LearnerTorchMLP.R @@ -2,13 +2,14 @@ #' #' @templateVar name mlp #' @templateVar task_types classif, regr -#' @templateVar param_vals layers = 1, d_hidden = 10 +#' @templateVar param_vals neurons = 10 #' @template params_learner #' @template learner #' @template learner_example #' #' @description #' Fully connected feed forward network with dropout after each activation function. +#' The features can either be a single [`lazy_tensor`] or one or more numeric columns. #' #' @section Parameters: #' Parameters from [`LearnerTorch`], as well as: @@ -18,13 +19,15 @@ #' * `activation_args` :: named `list()`\cr #' A named list with initialization arguments for the activation function. #' This is intialized to an empty list. -#' * `layers` :: `integer(1)`\cr -#' The number of layers. -#' * `d_hidden` :: `numeric(1)`\cr -#' The dimension of the hidden layers. +#' * `neurons` :: `integer()`\cr +#' The number of neurons per hidden layer. +#' By default there is no hidden layer. #' * `p` :: `numeric(1)`\cr #' The dropout probability. #' Is initialized to `0.5`. +#' * `shape` :: `integer()` or `NULL`\cr +#' The input shape. +#' Only needs to be present specified when there is a lazy tensor input with unknown shape. #' #' @export LearnerTorchMLP = R6Class("LearnerTorchMLP", @@ -36,11 +39,15 @@ LearnerTorchMLP = R6Class("LearnerTorchMLP", check_activation = crate(function(x) check_class(x, "nn_module"), .parent = topenv()) check_activation_args = crate(function(x) check_list(x, names = "unique"), .parent = topenv()) param_set = ps( - layers = p_int(lower = 0L, tags = c("required", "train")), - d_hidden = p_int(lower = 1L, tags = c("required", "train")), + neurons = p_uty(default = integer(0), tags = "train", custom_check = crate(function(x) { + check_integerish(x, any.missing = FALSE, lower = 1) + })), p = p_dbl(lower = 0, upper = 1, tags = c("required", "train")), activation = p_uty(tags = c("required", "train"), custom_check = check_activation), - activation_args = p_uty(tags = c("required", "train"), custom_check = check_activation_args) + activation_args = p_uty(tags = c("required", "train"), custom_check = check_activation_args), + shape = p_uty(default = NULL, tags = "train", custom_check = crate(function(x) { + check_shape(x, null_ok = TRUE) + })) ) param_set$set_values( activation = nn_relu, @@ -62,61 +69,65 @@ LearnerTorchMLP = R6Class("LearnerTorchMLP", callbacks = callbacks, loss = loss, man = "mlr3torch::mlr_learners.mlp", - feature_types = c("numeric", "integer") + feature_types = c("numeric", "integer", "lazy_tensor") ) } ), private = list( .network = function(task, param_vals) { - make_mlp( - task = task, - activation = param_vals$activation, - layers = param_vals$layers, - d_hidden = param_vals$d_hidden, - p = param_vals$p, - activation_args = param_vals$activation_args - ) + # verify_train_task was already called beforehand, so we can make some assumptions + d_out = get_nout(task) + d_in = if (single_lazy_tensor(task)) { + get_unique_shape(task, param_vals$shape)[2L] + } else { + length(task$feature_names) + } + network = invoke(make_mlp, .args = param_vals, d_in = d_in, d_out = d_out) + network }, .dataset = function(task, param_vals) { - dataset_num(task, param_vals) + if (single_lazy_tensor(task)) { + param_vals$shape = get_unique_shape(task, param_vals$shape) + dataset_ltnsr(task, param_vals) + } else { + dataset_num(task, param_vals) + } + }, + .verify_train_task = function(task, param_vals) { + features = task$feature_types[, "type"][[1L]] + lazy_tensor_input = identical(features, "lazy_tensor") + assert(check_true(lazy_tensor_input), check_false(some(features, function(x) x == "lazy_tensor"))) + + if (lazy_tensor_input) { + shape = get_unique_shape(task, param_vals$shape) + assert_shape(shape, len = 2L) + } } ) ) -make_mlp = function(task, activation, layers, d_hidden, p, activation_args) { - task_type = task$task_type - layers = layers - d_hidden = d_hidden - if (layers > 0) assert_true(!is.null(d_hidden)) - - out_dim = get_nout(task) - if (layers == 0L) { - network = nn_sequential( - nn_linear(length(task$feature_names), out_dim) - ) - return(network) - } +single_lazy_tensor = function(task) { + identical(task$feature_types[, "type"][[1L]], "lazy_tensor") +} +# shape is (NA, x) if preesnt +make_mlp = function(task, d_in, d_out, activation, neurons = integer(0), p, activation_args, ...) { # This way, dropout_args will have length 0 if p is `NULL` dropout_args = list() dropout_args$p = p - - modules = list( - nn_linear(length(task$feature_names), d_hidden), - invoke(activation, .args = activation_args), - invoke(nn_dropout, .args = dropout_args) - ) - - for (i in seq_len(layers - 1L)) { - modules = c(modules, list( - nn_linear(d_hidden, d_hidden), + prev_dim = d_in + modules = list() + for (n in neurons) { + modules = append(modules, list( + nn_linear( + in_features = prev_dim, + out_features = n), invoke(activation, .args = activation_args), invoke(nn_dropout, .args = dropout_args) )) + prev_dim = n } - - modules = c(modules, list(nn_linear(d_hidden, out_dim))) - + modules = c(modules, list(nn_linear(prev_dim, d_out))) invoke(nn_sequential, .args = modules) } diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index f723164f..14a61bab 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -399,7 +399,7 @@ create_ps = function(fn) { #' @template param_id #' @param fn (`function`)\cr #' The preprocessing function. -#' @param shapes_out (`function` or `NULL` or `"infer"` or `"unchanged"`)\cr +#' @param shapes_out (`function` or `NULL` or `"infer"`)\cr #' The private `.shapes_out(shapes_in, param_vals, task)` method of [`PipeOpTaskPreprocTorch`] #' (see section Inheriting). #' Special values are `NULL` and `infer`: @@ -436,7 +436,7 @@ pipeop_preproc_torch = function(id, fn, shapes_out = NULL, param_set = NULL, pac rowwise = FALSE, parent_env = parent.frame(), stages_init = NULL, tags = NULL) { assert( check_function(shapes_out, args = c("shapes_in", "param_vals", "task"), null.ok = TRUE), - check_choice(shapes_out, c("infer", "unchanged")) + check_choice(shapes_out, "infer") ) if (is.null(stages_init)) { @@ -462,7 +462,7 @@ pipeop_preproc_torch = function(id, fn, shapes_out = NULL, param_set = NULL, pac tensor_in = invoke(torch_empty, .args = sin, device = torch_device("meta")) tensor_out = tryCatch(invoke(self$fn, tensor_in, .args = param_vals), error = function(e) { - stopf("Failed to infer output shape, presumably invalid input shape; error message is: %s", e) + stopf("Input shape '%s' is invalid for PipeOp with id '%s'.", shape_to_str(list(sin)), self$id) } ) sout = dim(tensor_out) @@ -475,14 +475,18 @@ pipeop_preproc_torch = function(id, fn, shapes_out = NULL, param_set = NULL, pac list(sout) }) - } else if (identical(shapes_out, "unchanged")) { - shapes_out = crate(function(shapes_in, param_vals, task_in) shapes_in) } else if (is.function(shapes_out) || is.null(shapes_out)) { # nothing to do } else { stopf("unreachable") } - + if (test_class(param_set, "ParamSet") && is.function(fn) && "..." %nin% formalArgs(fn)) { + pars = setdiff(param_set$ids(), c("stages", "affect_columns")) + fn_args = formalArgs(fn) + # there needs to be a parameter for the tensor + assert_true(length(fn_args) > length(pars)) + assert_subset(pars, fn_args) + } param_set = param_set %??% create_ps(fn) # the .__construction info construct is used to not having to rely on NSE diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index 1483bc6d..cda79335 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -51,7 +51,7 @@ PipeOpTorchIngress = R6Class("PipeOpTorchIngress", .train = function(inputs) { pv = self$param_set$get_values() task = inputs[[1]] - if (any(task$missings())) { + if (any(task$missings(task$feature_names))) { # NAs are converted to their underlying machine representation when calling `torch_tensor()` # https://github.com/mlverse/torch/issues/933 stopf("No missing values allowed in task '%s'.", task$id) diff --git a/R/preprocess.R b/R/preprocess.R index 59af348d..e19d21cf 100644 --- a/R/preprocess.R +++ b/R/preprocess.R @@ -27,6 +27,16 @@ register_preproc("trafo_resize", torchvision::transform_resize, rowwise = FALSE ) +unchanged_shapes_rgb = function(shapes_in, param_vals, task) { + assert_rgb_shape(shapes_in[[1L]]) + shapes_in +} + +unchanged_shapes_image = function(shapes_in, param_vals, task) { + assert_image_shape(shapes_in[[1L]]) + shapes_in +} + #' @title PipeOpPreprocTorchTrafoNop #' @usage NULL #' @name mlr_pipeops_preproc_torch.trafo_nop @@ -36,28 +46,48 @@ register_preproc("trafo_resize", torchvision::transform_resize, #' #' @description #' Does nothing. -register_preproc("trafo_nop", identity, shapes_out = "unchanged", rowwise = FALSE) +register_preproc("trafo_nop", identity, rowwise = FALSE, shapes_out = unchanged_shapes) + + +#' @title PipeOpPreprocTorchTrafoNop +#' @usage NULL +#' @name mlr_pipeops_preproc_torch.trafo_scale +#' @aliases PipeOpPreprocTorchTrafoScale +#' @rdname PipeOpPreprocTorchTrafoScale +#' @format [`R6Class`] inheriting from [`PipeOpTaskPreprocTorch`]. +#' +#' @description +#' Applies `(x - mean) / sd` to a tensor `x`. +register_preproc("trafo_scale", crate(function(x, mean, sd) (x - mean) / sd), + shapes_out = unchanged_shapes, rowwise = FALSE, + param_set = ps( + mean = p_uty(tags = c("train", "required")), + sd = p_uty(tags = c("train", "required")) + ) +) #' @template preprocess_torchvision #' @templateVar id trafo_adjust_gamma -register_preproc("trafo_adjust_gamma", torchvision::transform_adjust_gamma, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, +register_preproc("trafo_adjust_gamma", torchvision::transform_adjust_gamma, packages = "torchvision", shapes_out = "infer", rowwise = TRUE, param_set = ps( gamma = p_dbl(lower = 0, tags = c("train", "required")), gain = p_dbl(default = 1, tags = "train") ) -) # nolint +) #' @template preprocess_torchvision #' @templateVar id trafo_adjust_brightness -register_preproc("trafo_adjust_brightness", torchvision::transform_adjust_brightness, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, +register_preproc("trafo_adjust_brightness", torchvision::transform_adjust_brightness, packages = "torchvision", + shapes_out = "infer", rowwise = TRUE, param_set = ps( brightness_factor = p_dbl(lower = 0, tags = c("train", "required")) ) -) # nolint +) #' @template preprocess_torchvision #' @templateVar id trafo_adjust_hue -register_preproc("trafo_adjust_hue", torchvision::transform_adjust_hue, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, +register_preproc("trafo_adjust_hue", torchvision::transform_adjust_hue, packages = "torchvision", + rowwise = TRUE, shapes_out = unchanged_shapes_rgb, param_set = ps( hue_factor = p_dbl(lower = -0.5, upper = 0.5, tags = c("train", "required")) ) @@ -65,36 +95,42 @@ register_preproc("trafo_adjust_hue", torchvision::transform_adjust_hue, packages #' @template preprocess_torchvision #' @templateVar id trafo_adjust_saturation -register_preproc("trafo_adjust_saturation", torchvision::transform_adjust_saturation, packages = "torchvision", shapes_out = "infer", rowwise = TRUE, +register_preproc("trafo_adjust_saturation", torchvision::transform_adjust_saturation, packages = "torchvision", + shapes_out = "infer", rowwise = TRUE, param_set = ps( saturation_factor = p_dbl(tags = c("train", "required")) ) -) # nolint +) #' @template preprocess_torchvision #' @templateVar id trafo_grayscale -register_preproc("trafo_grayscale", torchvision::transform_grayscale, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, +register_preproc("trafo_grayscale", torchvision::transform_grayscale, packages = "torchvision", shapes_out = "infer", rowwise = TRUE, param_set = ps( num_output_channels = p_int(lower = 1L, upper = 3L, tags = c("train", "required")) ) -) # nolint +) #' @template preprocess_torchvision #' @templateVar id trafo_rgb_to_grayscale register_preproc("trafo_rgb_to_grayscale", torchvision::transform_rgb_to_grayscale, packages = "torchvision", shapes_out = "infer", rowwise = TRUE, param_set = ps() -) # nolint +) #' @template preprocess_torchvision #' @templateVar id trafo_normalize -register_preproc("trafo_normalize", torchvision::transform_normalize, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, +register_preproc("trafo_normalize", torchvision::transform_normalize, packages = "torchvision", rowwise = TRUE, param_set = ps( mean = p_uty(tags = c("train", "required")), std = p_uty(tags = c("train", "required")) # no inplace parameter as this might be problematic when a preprocessing pipeop's output is connected to multiple # other pipeops - ) -) # nolint + ), + shapes_out = function(shapes_in, param_vals, task) { + s = shapes_in[[1L]] + assert_true(length(s) >= 2) + shapes_in + } +) #' @template preprocess_torchvision #' @templateVar id trafo_pad @@ -104,7 +140,7 @@ register_preproc("trafo_pad", torchvision::transform_pad, packages = "torchvisio fill = p_uty(default = 0, tags = "train"), padding_mode = p_fct(default = "constant", levels = c("constant", "edge", "reflect", "symmetric"), tags = "train") ) -) # nolint +) # Data Augmentation @@ -119,18 +155,18 @@ register_preproc("augment_resized_crop", torchvision::transform_resized_crop, pa size = p_uty(tags = c("train", "required")), interpolation = p_int(default = 2L, lower = 0L, upper = 3L, tags = "train") ) -) # nolint +) #' @template preprocess_torchvision #' @templateVar id augment_color_jitter -register_preproc("augment_color_jitter", torchvision::transform_color_jitter, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, +register_preproc("augment_color_jitter", torchvision::transform_color_jitter, packages = "torchvision", shapes_out = "infer", rowwise = TRUE, param_set = ps( brightness = p_dbl(default = 0, lower = 0, tags = "train"), contrast = p_dbl(default = 0, lower = 0, tags = "train"), saturation = p_dbl(default = 0, lower = 0, tags = "train"), hue = p_dbl(default = 0, lower = 0, tags = "train") ) -) # nolint +) #' @template preprocess_torchvision #' @templateVar id augment_random_resized_crop @@ -141,7 +177,7 @@ register_preproc("augment_random_resized_crop", torchvision::transform_random_re ratio = p_uty(default = c(3 / 4, 4 / 3), tags = "train"), interpolation = p_int(default = 2L, lower = 0L, upper = 3L, tags = "train") ) -) # nolint +) #' @template preprocess_torchvision #' @templateVar id augment_random_order @@ -149,21 +185,29 @@ register_preproc("augment_random_order", torchvision::transform_random_order, pa param_set = ps( transforms = p_uty(tags = c("train", "required"), custom_check = check_list) ) -) # nolint +) #' @template preprocess_torchvision #' @templateVar id augment_hflip -register_preproc("augment_hflip", torchvision::transform_hflip, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, +register_preproc("augment_hflip", torchvision::transform_hflip, packages = "torchvision", rowwise = TRUE, + shapes_out = function(shapes_in, param_vals, task) { + assert_image_shape(shapes_in[[1L]]) + shapes_in + }, param_set = ps() -) # nolint +) #' @template preprocess_torchvision #' @templateVar id augment_random_horizontal_flip -register_preproc("augment_random_horizontal_flip", torchvision::transform_random_horizontal_flip, packages = "torchvision", shapes_out = NULL, rowwise = TRUE, +register_preproc("augment_random_horizontal_flip", torchvision::transform_random_horizontal_flip, packages = "torchvision", rowwise = TRUE, param_set = ps( p = p_dbl(default = 0.5, lower = 0, upper = 1, tags = "train") - ) -) # nolint + ), + shapes_out = function(shapes_in, param_vals, task) { + assert_rgb_shape(shapes_in[[1L]]) + shapes_in + } +) #' @template preprocess_torchvision @@ -175,15 +219,16 @@ register_preproc("augment_crop", torchvision::transform_crop, packages = "torchv height = p_int(tags = c("train", "required")), width = p_int(tags = c("train", "required")) ) -) # nolint +) #' @template preprocess_torchvision #' @templateVar id augment_random_vertical_flip -register_preproc("augment_random_vertical_flip", torchvision::transform_random_vertical_flip, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, +register_preproc("augment_random_vertical_flip", torchvision::transform_random_vertical_flip, packages = "torchvision", + rowwise = TRUE, shapes_out = unchanged_shapes_rgb, param_set = ps( p = p_dbl(default = 0.5, lower = 0, upper = 1, tags = "train") ) -) # nolint +) #' @template preprocess_torchvision #' @templateVar id augment_random_affine @@ -195,14 +240,18 @@ register_preproc("augment_random_affine", torchvision::transform_random_affine, resample = p_int(default = 0, tags = "train"), fillcolor = p_uty(default = 0, tags = "train") ) -) # nolint +) #' @template preprocess_torchvision #' @templateVar id augment_vflip -register_preproc("augment_vflip", torchvision::transform_vflip, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE, - param_set = ps() -) # nolint +register_preproc("augment_vflip", torchvision::transform_vflip, packages = "torchvision", rowwise = TRUE, + param_set = ps(), + shapes_out = function(shapes_in, param_vals, task) { + assert_image_shape(shapes_in[[1L]]) + shapes_in + } +) #' @template preprocess_torchvision #' @templateVar id augment_random_apply @@ -211,7 +260,7 @@ register_preproc("augment_random_apply", torchvision::transform_random_apply, pa transforms = p_uty(tags = c("train", "required"), custom_check = check_list), p = p_dbl(default = 0.5, lower = 0, upper = 1, tags = "train") ) -) # nolint +) #' @template preprocess_torchvision #' @templateVar id augment_rotate @@ -223,7 +272,7 @@ register_preproc("augment_rotate", torchvision::transform_rotate, packages = "to center = p_uty(default = NULL, tags = "train"), fill = p_uty(default = NULL, tags = "train") ) -) # nolint +) #' @template preprocess_torchvision #' @templateVar id augment_center_crop @@ -231,7 +280,7 @@ register_preproc("augment_center_crop", torchvision::transform_center_crop, pack param_set = ps( size = p_uty(tags = c("train", "required")) ) -) # nolint +) #' @template preprocess_torchvision #' @templateVar id augment_random_choice @@ -239,7 +288,7 @@ register_preproc("augment_random_choice", torchvision::transform_random_choice, param_set = ps( transforms = p_uty(custom_check = check_list, tags = c("train", "required")) ) -) # nolint +) #' @template preprocess_torchvision #' @templateVar id augment_random_crop @@ -256,7 +305,7 @@ register_preproc("augment_random_crop", torchvision::transform_random_crop, pack ##' @name PipeOpPreprocTorchAugmentRandomRotation ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_random_rotation", torchvision::transform_random_rotation, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint +#register_preproc("augment_random_rotation", torchvision::transform_random_rotation, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) ##' @name PipeOpPreprocTorchAugmentRandomErasing ##' @rdname mlr_pipeops_preproc_torch_overview @@ -265,18 +314,18 @@ register_preproc("augment_random_crop", torchvision::transform_random_crop, pack # not implemented ##' @name PipeOpPreprocTorchAugmentPerspective ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_perspective", torchvision::transform_perspective, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint +#register_preproc("augment_perspective", torchvision::transform_perspective, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # not implemented for tensor ##' @name PipeOpPreprocTorchAugmentRandomGrayscale ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_random_grayscale", torchvision::transform_random_grayscale, packages = "torchvision", shapes_out = "unchanged", rowwise = TRUE) # nolint +#register_preproc("augment_random_grayscale", torchvision::transform_random_grayscale, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # infering shape does not work, we could do it manually ##' @name PipeOpPreprocTorchAugmentLinearTransformation ##' @rdname mlr_pipeops_preproc_torch_overview -#register_preproc("augment_linear_transformation", torchvision::transform_linear_transformation, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) # nolint +#register_preproc("augment_linear_transformation", torchvision::transform_linear_transformation, packages = "torchvision", shapes_out = "infer", rowwise = TRUE) ##' @template preprocess_torchvision ##' @templateVar id augment_random_perspective -#register_preproc("augment_random_perspective", torchvision::transform_random_perspective, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) # nolint +#register_preproc("augment_random_perspective", torchvision::transform_random_perspective, packages = "torchvision", shapes_out = NULL, rowwise = TRUE) diff --git a/R/shape.R b/R/shape.R index 4d983638..adbc00e7 100644 --- a/R/shape.R +++ b/R/shape.R @@ -11,9 +11,11 @@ #' @param unknown_batch (`logical(1)`)\cr #' Whether the batch **must** be unknonw, i.e. `NA`. #' If left `NULL` (default), the first dimension can be `NA` or not. +#' @param len (`integer(1)`)\cr +#' The length of the shape. #' @noRd -assert_shape = function(shape, null_ok = FALSE, coerce = TRUE, unknown_batch = NULL) { - result = check_shape(shape, null_ok = null_ok, unknown_batch = unknown_batch) +assert_shape = function(shape, null_ok = FALSE, coerce = TRUE, unknown_batch = NULL, len = NULL) { + result = check_shape(shape, null_ok = null_ok, unknown_batch = unknown_batch, len = len) if (!isTRUE(result)) stopf(result) @@ -24,11 +26,11 @@ assert_shape = function(shape, null_ok = FALSE, coerce = TRUE, unknown_batch = N } -test_shape = function(shape, null_ok = FALSE, unknown_batch = NULL) { +test_shape = function(shape, null_ok = FALSE, unknown_batch = NULL, len = NULL) { if (is.null(shape) && null_ok) { return(TRUE) } - ok = test_integerish(shape, min.len = 2L, all.missing = FALSE, any.missing = TRUE) + ok = test_integerish(shape, min.len = 2L, all.missing = FALSE, any.missing = TRUE, len = len) if (!ok) { return(FALSE) @@ -44,12 +46,13 @@ test_shape = function(shape, null_ok = FALSE, unknown_batch = NULL) { return(is.na(shape[1L]) == unknown_batch) } -check_shape = function(shape, null_ok = FALSE, unknown_batch = NULL) { - if (test_shape(shape, null_ok = null_ok, unknown_batch = unknown_batch)) { +check_shape = function(x, null_ok = FALSE, unknown_batch = NULL, len = NULL) { + if (test_shape(x, null_ok = null_ok, unknown_batch = unknown_batch, len = len)) { return(TRUE) } - sprintf("Invalid shape: %s.", paste0(format(shape), collapse = ", ")) + sprintf("Invalid shape: %s.", paste0(format(x), collapse = ", ")) } + assert_shapes = function(shapes, coerce = TRUE, named = FALSE, null_ok = FALSE, unknown_batch = NULL) { # nolint ok = test_list(shapes, min.len = 1L) if (named) { @@ -60,3 +63,14 @@ assert_shapes = function(shapes, coerce = TRUE, named = FALSE, null_ok = FALSE, } map(shapes, assert_shape, coerce = coerce, null_ok = null_ok, unknown_batch = unknown_batch) } + +assert_rgb_shape = function(shape) { + assert_shape(shape, len = 4L, null_ok = FALSE) + assert_true(shape[2L] == 3L) +} + +# grayscale or rgb image +assert_image_shape = function(shape) { + assert_shape(shape, len = 4L, null_ok = FALSE) + assert_true(shape[2L] == 3L || shape[2L] == 1L) +} diff --git a/R/utils.R b/R/utils.R index 2b5cab4d..d985b141 100644 --- a/R/utils.R +++ b/R/utils.R @@ -7,13 +7,7 @@ #' @export auto_device = function(device = NULL) { if (device == "auto") { - device = if (cuda_is_available()) { - "cuda" - } else if (backends_mps_is_available()) { - "mps" - } else { - "cpu" - } + device = if (cuda_is_available()) "cuda" else "cpu" lg$debug("Auto-detected device '%s'.", device) } return(device) @@ -162,7 +156,12 @@ uniqueify = function(new, existing) { } shape_to_str = function(x) { - shapedescs = map_chr(x, function(y) paste0("(", paste(y, collapse = ",", recycle0 = TRUE), ")")) + shapedescs = map_chr(x, function(y) { + if (is.null(y)) { + return("") + } + paste0("(", paste(y, collapse = ",", recycle0 = TRUE), ")") + }) if (test_named(x)) { repr = paste0("[", names(x), ": ", paste(shapedescs, collapse = ";", recycle0 = TRUE), "]") return(repr) @@ -194,3 +193,21 @@ list_to_batch = function(tensors) { auto_cache_lazy_tensors = function(lts) { any(duplicated(map_chr(lts, function(x) dd(x)$dataset_hash))) } + +unchanged_shapes = function(shapes_in, param_vals, task) { + shapes_in +} + +get_unique_shape = function(s1, s2) { + if (test_class(s1, "Task")) { + assert_true(identical(s1$feature_types[, "type"][[1L]], "lazy_tensor")) + s1 = dd(s1$data(s1$row_roles$use[1L], s1$feature_names)[[1L]])$pointer_shape + } + assert_shape(s1, null_ok = TRUE) + assert_shape(s2, null_ok = TRUE) + s = unique(discard(list(s1, s2), is.null)) + assert_true(length(s) == 1L) + s[[1L]] +} + +assert_compatible_shapes = get_unique_shape diff --git a/README.Rmd b/README.Rmd index e598d37f..b3fbe27f 100644 --- a/README.Rmd +++ b/README.Rmd @@ -59,8 +59,7 @@ library(mlr3torch) learner_mlp = lrn("classif.mlp", # defining network parameters activation = nn_relu, - layers = 1, - d_hidden = 20, + neurons = c(20, 20), # training parameters batch_size = 16, epochs = 50, diff --git a/README.md b/README.md index ba39d181..76a1f6b9 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,7 @@ library(mlr3torch) learner_mlp = lrn("classif.mlp", # defining network parameters activation = nn_relu, - layers = 1, - d_hidden = 20, + neurons = 20, # training parameters batch_size = 16, epochs = 50, @@ -103,7 +102,7 @@ graph_mlp #> Graph with 8 PipeOps: #> ID State sccssors prdcssors #> -#> torch_ingress_num <> nn_linear +#> torch_ingress_num <> nn_linear #> nn_linear <> nn_relu torch_ingress_num #> nn_relu <> nn_head nn_linear #> nn_head <> torch_loss nn_relu diff --git a/man/PipeOpPreprocTorchTrafoScale.Rd b/man/PipeOpPreprocTorchTrafoScale.Rd new file mode 100644 index 00000000..0a3cac68 --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoScale.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_scale} +\alias{mlr_pipeops_preproc_torch.trafo_scale} +\alias{PipeOpPreprocTorchTrafoScale} +\title{PipeOpPreprocTorchTrafoNop} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Applies \code{(x - mean) / sd} to a tensor \code{x}. +} diff --git a/man/mlr_learners.mlp.Rd b/man/mlr_learners.mlp.Rd index a13ba4c5..a18ef202 100644 --- a/man/mlr_learners.mlp.Rd +++ b/man/mlr_learners.mlp.Rd @@ -6,6 +6,7 @@ \title{My Little Pony} \description{ Fully connected feed forward network with dropout after each activation function. +The features can either be a single \code{\link{lazy_tensor}} or one or more numeric columns. } \section{Dictionary}{ @@ -25,7 +26,7 @@ lrn("regr.mlp", ...) \item classif: 'response', 'prob' \item regr: 'response' } -\item Feature Types: \dQuote{integer}, \dQuote{numeric} +\item Feature Types: \dQuote{integer}, \dQuote{numeric}, \dQuote{lazy_tensor} \item Required Packages: \CRANpkg{mlr3}, \CRANpkg{mlr3torch}, \CRANpkg{torch} } } @@ -51,13 +52,15 @@ The activation function. Is initialized to \code{\link{nn_relu}}. \item \code{activation_args} :: named \code{list()}\cr A named list with initialization arguments for the activation function. This is intialized to an empty list. -\item \code{layers} :: \code{integer(1)}\cr -The number of layers. -\item \code{d_hidden} :: \code{numeric(1)}\cr -The dimension of the hidden layers. +\item \code{neurons} :: \code{integer()}\cr +The number of neurons per hidden layer. +By default there is no hidden layer. \item \code{p} :: \code{numeric(1)}\cr The dropout probability. Is initialized to \code{0.5}. +\item \code{shape} :: \code{integer()} or \code{NULL}\cr +The input shape. +Only needs to be present specified when there is a lazy tensor input with unknown shape. } } @@ -65,7 +68,7 @@ Is initialized to \code{0.5}. # Define the Learner and set parameter values learner = lrn("classif.mlp") learner$param_set$set_values( - layers = 1, d_hidden = 10, batch_size = 1, epochs = 1, device = "cpu" + neurons = 10, batch_size = 1, epochs = 1, device = "cpu" ) # Define a Task diff --git a/man/pipeop_preproc_torch.Rd b/man/pipeop_preproc_torch.Rd index 913d28eb..3eb70276 100644 --- a/man/pipeop_preproc_torch.Rd +++ b/man/pipeop_preproc_torch.Rd @@ -23,7 +23,7 @@ The id for of the new object.} \item{fn}{(\code{function})\cr The preprocessing function.} -\item{shapes_out}{(\code{function} or \code{NULL} or \code{"infer"} or \code{"unchanged"})\cr +\item{shapes_out}{(\code{function} or \code{NULL} or \code{"infer"})\cr The private \code{.shapes_out(shapes_in, param_vals, task)} method of \code{\link{PipeOpTaskPreprocTorch}} (see section Inheriting). Special values are \code{NULL} and \code{infer}: diff --git a/tests/testthat/helper_autotest.R b/tests/testthat/helper_autotest.R index f3219bbf..7f7f4ddf 100644 --- a/tests/testthat/helper_autotest.R +++ b/tests/testthat/helper_autotest.R @@ -326,7 +326,8 @@ autotest_torch_callback = function(torch_callback, check_man = TRUE) { #' @param obj ([`PipeOpTaskPreprocTorch`])\cr #' The object to test. #' @parm tnsr_in (`integer()`)\cr -autotest_pipeop_torch_preprocess = function(obj, shapes_in, exclude = character(0), exclude_defaults = character(0)) { +autotest_pipeop_torch_preprocess = function(obj, shapes_in, exclude = character(0), exclude_defaults = character(0), + in_package = TRUE) { expect_pipeop(obj) expect_class(obj, "PipeOpTaskPreprocTorch") # a) Check that all parameters but stages have tags train and predict (this should hold in basically all cases) @@ -340,14 +341,16 @@ autotest_pipeop_torch_preprocess = function(obj, shapes_in, exclude = character( # b) Check that the shape prediction is compatible (already done in autotest for pipeop torch) # c) check that start with stages / trafo, depending on the initial value - class = get(class(obj)[[1L]], envir = getNamespace("mlr3torch")) - instance = class$new() + if (in_package) { + class = get(class(obj)[[1L]], envir = getNamespace("mlr3torch")) + instance = class$new() - testthat::expect_true(grepl(instance$id, pattern = "^(trafo|augment)_")) - if (startsWith(instance$id, "augment")) { - expect_set_equal(instance$param_set$values$stages, "train") - } else { - expect_set_equal(instance$param_set$values$stages, "both") + testthat::expect_true(grepl(instance$id, pattern = "^(trafo|augment)_")) + if (startsWith(instance$id, "augment")) { + expect_set_equal(instance$param_set$values$stages, "train") + } else { + expect_set_equal(instance$param_set$values$stages, "both") + } } shapes_in = if (!test_list(shapes_in)) list(shapes_in) else shapes_in @@ -376,3 +379,13 @@ autotest_pipeop_torch_preprocess = function(obj, shapes_in, exclude = character( } }) } + + +#' @title Autotest Learner Torch +#' @descrition +#' The autotest for torch learners differs from the standard mlr3 autotest for learners. +#' The reason is, that we do not have to test the +autotest_learner_torch = function(learner) { + +} + diff --git a/tests/testthat/helper_pipeop.R b/tests/testthat/helper_pipeop.R index a9bbec83..31d5d9c7 100644 --- a/tests/testthat/helper_pipeop.R +++ b/tests/testthat/helper_pipeop.R @@ -48,5 +48,5 @@ PipeOpTorchDebug = R6Class("PipeOpTorchDebug", PipeOpPreprocTorchAddSome = pipeop_preproc_torch("trafo_some", param_set = ps(some = p_dbl(default = 1L, tags = "train")), fn = crate(function(x, some = 1L) x + some), - shapes_out = "unchanged" + shapes_out = "infer" ) diff --git a/tests/testthat/test_CallbackSet.R b/tests/testthat/test_CallbackSet.R index 69c7ce9a..d789fc84 100644 --- a/tests/testthat/test_CallbackSet.R +++ b/tests/testthat/test_CallbackSet.R @@ -41,7 +41,7 @@ test_that("All stages are called correctly", { ) path = tempfile() learner = lrn("classif.mlp", batch_size = 1, epochs = 1, callbacks = cb, cb.test.path = path, - layers = 0, d_hidden = 1, measures_valid = msr("classif.acc")) + measures_valid = msr("classif.acc")) task$row_roles$use = 2 task$row_roles$test = 3 diff --git a/tests/testthat/test_CallbackSetCheckpoint.R b/tests/testthat/test_CallbackSetCheckpoint.R index 9fb3ce34..fd5b1175 100644 --- a/tests/testthat/test_CallbackSetCheckpoint.R +++ b/tests/testthat/test_CallbackSetCheckpoint.R @@ -9,14 +9,14 @@ test_that("CallbackSetCheckpoint manual", { task$row_roles$use = 1 pth0 = tempfile() - learner = lrn("classif.mlp", epochs = 3, batch_size = 1, layers = 0, d_hidden = 1, callbacks = cb) + learner = lrn("classif.mlp", epochs = 3, batch_size = 1, callbacks = cb) learner$param_set$set_values(cb.checkpoint.path = pth0) learner$train(task) expect_set_equal(paste0("network", 1:3, ".pt"), list.files(pth0)) - learner = lrn("classif.mlp", epochs = 3, batch_size = 1, layers = 0, d_hidden = 1, callbacks = cb) + learner = lrn("classif.mlp", epochs = 3, batch_size = 1, callbacks = cb) pth2 = tempfile() learner$param_set$set_values(cb.checkpoint.path = pth2, cb.checkpoint.freq = 2) learner$train(task) diff --git a/tests/testthat/test_CallbackSetHistory.R b/tests/testthat/test_CallbackSetHistory.R index 408e56ad..8b461440 100644 --- a/tests/testthat/test_CallbackSetHistory.R +++ b/tests/testthat/test_CallbackSetHistory.R @@ -10,7 +10,7 @@ test_that("CallbackSetHistory works", { task$row_roles$use = 1 task$row_roles$test = 2 - learner = lrn("classif.mlp", epochs = 3, batch_size = 1, layers = 0, d_hidden = 1, callbacks = t_clbk("history")) + learner = lrn("classif.mlp", epochs = 3, batch_size = 1, callbacks = t_clbk("history")) learner$train(task) @@ -32,7 +32,7 @@ test_that("CallbackSetHistory works", { test_that("plotting works", { task = tsk("iris") split = partition(task) - learner = lrn("classif.mlp", epochs = 2, batch_size = 50, layers = 0, d_hidden = 1, callbacks = t_clbk("history"), + learner = lrn("classif.mlp", epochs = 2, batch_size = 50, callbacks = t_clbk("history"), measures_train = msrs(c("classif.acc", "classif.ce", "classif.logloss")), measures_valid = msr("classif.ce"), predict_type = "prob" ) diff --git a/tests/testthat/test_CallbackSetProgress.R b/tests/testthat/test_CallbackSetProgress.R index 08c34840..1ede9924 100644 --- a/tests/testthat/test_CallbackSetProgress.R +++ b/tests/testthat/test_CallbackSetProgress.R @@ -4,7 +4,7 @@ test_that("autotest", { }) test_that("manual test", { - learner = lrn("classif.mlp", epochs = 1, batch_size = 1, d_hidden = 1, layers = 0, + learner = lrn("classif.mlp", epochs = 1, batch_size = 1, measures_train = msr("classif.acc"), measures_valid = msr("classif.ce"), callbacks = t_clbk("progress"), drop_last = FALSE, shuffle = TRUE ) diff --git a/tests/testthat/test_DataDescriptor.R b/tests/testthat/test_DataDescriptor.R index de174012..4facfe60 100644 --- a/tests/testthat/test_DataDescriptor.R +++ b/tests/testthat/test_DataDescriptor.R @@ -43,3 +43,9 @@ test_that("can infer the simple case", { expect_equal(dd$pointer, c(dd$graph$output$op.id, dd$graph$output$channel.name)) }) + +test_that("printer", { + dd = DataDescriptor$new(random_dataset(1), list(x = NULL)) + # unknown shapes + expect_true(grepl(paste0(capture.output(dd), collapse = ""), pattern = "", fixed = TRUE)) +}) diff --git a/tests/testthat/test_LearnerTorchMLP.R b/tests/testthat/test_LearnerTorchMLP.R index 44ee45d4..04143cd6 100644 --- a/tests/testthat/test_LearnerTorchMLP.R +++ b/tests/testthat/test_LearnerTorchMLP.R @@ -4,7 +4,7 @@ test_that("LearnerTorchMLP works", { tab = table(map_chr(learner$network$children, function(x) class(x)[[1L]])) act = class(learner$param_set$values$activation)[[1L]] - l = learner$param_set$values$layers + l = length(learner$param_set$values$neurons) expect_true(tab["nn_linear"] == l + 1) if (l > 0) { @@ -17,11 +17,10 @@ test_that("LearnerTorchMLP works", { } learner = lrn("classif.mlp", - layers = 2L, + neurons = rep(13, 2), p = 0.111, batch_size = 16L, epochs = 0, - d_hidden = 13, optimizer = "adagrad", activation = nn_softshrink, activation_args = list(lambd = 0.25) @@ -38,10 +37,17 @@ test_that("LearnerTorchMLP works", { verify_network(learner) - learner$param_set$set_values(layers = 0L) + learner$param_set$set_values(neurons = integer(0)) learner$train(task) verify_network(learner) }) -# FIXME: Autotest for learner +test_that("works for lazy tensor", { + learner = lrn("classif.mlp", epochs = 100, batch_size = 150) + task_lazy = tsk("lazy_iris") + lt = learner$train(task_lazy) +}) + + +# TODO: More tests diff --git a/tests/testthat/test_PipeOpTorchIngress.R b/tests/testthat/test_PipeOpTorchIngress.R index c4855888..27da1d11 100644 --- a/tests/testthat/test_PipeOpTorchIngress.R +++ b/tests/testthat/test_PipeOpTorchIngress.R @@ -48,3 +48,9 @@ test_that("PipeOpTorchIngressLazyTensor", { expect_error(po_ingress$param_set$set_values(shape = c(22, 4))) expect_error(po_ingress$param_set$set_values(shape = c(NA, 22, 4)), regexp = NA) }) + +test_that("target can contain missings for ingress", { + task = as_task_regr(data.table(y = c(1, NA), x = 1:1), target = "y") + md = po("torch_ingress_num")$train(list(task))[[1L]] + expect_class(md, "ModelDescriptor") +}) diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index c3cc32f8..266c0421 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -42,9 +42,6 @@ test_that("unknown shapes", { expect_class(lt[[1]], "list") expect_class(c(lt, lazy_tensor()), "lazy_tensor") - - ds = random_dataset(10, 3) - expect_error(DataDescriptor$new(ds, list(x = NULL))) }) test_that("assignment", { diff --git a/tests/testthat/test_learner_torch_methods.R b/tests/testthat/test_learner_torch_methods.R index 271d1e87..48765a55 100644 --- a/tests/testthat/test_learner_torch_methods.R +++ b/tests/testthat/test_learner_torch_methods.R @@ -102,7 +102,7 @@ test_that("Test roles are respected", { test_that("learner_torch_predict works", { task = tsk("iris") - learner = lrn("classif.mlp", batch_size = 16, epochs = 1, layers = 0, device = "cpu") + learner = lrn("classif.mlp", batch_size = 16, epochs = 1, device = "cpu") dl = get_private(learner)$.dataloader(task, learner$param_set$values) network = get_private(learner)$.network(task, learner$param_set$values) diff --git a/tests/testthat/test_preprocess.R b/tests/testthat/test_preprocess.R index e312aac0..7280c371 100644 --- a/tests/testthat/test_preprocess.R +++ b/tests/testthat/test_preprocess.R @@ -147,7 +147,7 @@ test_that("augment_crop", { test_that("augment_random_vertical_flip", { autotest_pipeop_torch_preprocess( obj = po("augment_random_vertical_flip"), - shapes_in = list(c(3, 3, 8, 7)) + shapes_in = list(c(3, 3, 8, 8)) ) }) diff --git a/tests/testthat/test_shape.R b/tests/testthat/test_shape.R index 73e30521..e5a68d8f 100644 --- a/tests/testthat/test_shape.R +++ b/tests/testthat/test_shape.R @@ -18,4 +18,5 @@ test_that("assert_shape and friends", { expect_error(assert_shapes(list(c(1, 2), c(2, 3)), named = TRUE)) expect_error(assert_shapes(list(c(1, 2), c(2, 3))), regexp = NA) expect_error(assert_shapes(list(c(4, 5), c(2, 3)), unknown_batch = TRUE)) + expect_error(assert_shape(c(NA, 1, 2), len = 2)) }) diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index d7f886a2..a6c210c0 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -263,12 +263,11 @@ test_that("default target batchgetter works: classification", { test_that("cachine of graph", { env = new.env() - env$counter = 0L fn = crate(function(x) { env$counter = env$counter + 1L x + 1 }, env) - po_test = pipeop_preproc_torch("test", fn = fn, shapes_out = "unchanged", stages_init = "both")$new() + po_test = pipeop_preproc_torch("test", fn = fn, shapes_out = "infer", stages_init = "both")$new() expect_true(is.function(po_test$fn)) @@ -288,6 +287,7 @@ test_that("cachine of graph", { ) ds = task_dataset(task, ingress_tokens, device = "cpu") + env$counter = 0L ds$.getbatch(1) expect_equal(env$counter, 1) diff --git a/vignettes/get_started.Rmd b/vignettes/get_started.Rmd index 64bb9990..50c608b4 100644 --- a/vignettes/get_started.Rmd +++ b/vignettes/get_started.Rmd @@ -32,14 +32,14 @@ task$head() Learners in `mlr3torch` work very similary to other `mlr3` learners. Below, we construct a simple multi layer perceptron for regression. We do this as usual using the `lrn()` function and specify its parameters: -The hidden dimension is set to 50 and the number of layers to 2. +We use two hidden layers with 50 neurons, For training, we set the batch size to 32, the number of training epochs to 30 and the device to `"cpu"`. For a complete description of the available parameters see `?mlr3torch::LearnerTorchMLP`. ```{r} mlp = lrn("regr.mlp", # architecture parameters - d_hidden = 50, layers = 2, + neurons = c(50, 50), # training arguments batch_size = 32, epochs = 30, device = "cpu" ) @@ -213,7 +213,7 @@ mlp_custom = lrn("regr.mlp", measures_train = msr("regr.mae"), # other parameters are left as-is: # architecture - d_hidden = 50, layers = 2, + neurons = c(50, 50), # training arguments batch_size = 32, epochs = 30, device = "cpu" ) diff --git a/vignettes/lazy_tensor.Rmd b/vignettes/lazy_tensor.Rmd new file mode 100644 index 00000000..28efe22f --- /dev/null +++ b/vignettes/lazy_tensor.Rmd @@ -0,0 +1,186 @@ +--- +title: "Lazy Tensor" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Lazy Tensor} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +library(ggplot2) +theme_set(theme_bw()) +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +This vignette introduces the `lazy_tensor` class, which is a vector type that can be used to lazily represent torch tensors of arbitary dimensions. +The `lazy_tensor` type can be illustrated using the predefined `"lazy_iris"` task, which is similar to the `"iris"` task, but stores the 4 features in a single `lazy_tensor` column instead of four numeric columns. + +```{r} +library(mlr3torch) + +tsk_iris = tsk("lazy_iris") +tsk_iris +lt = tsk_iris$data(cols = "x")$x +head(lt) +``` + +We can convert the `lazy_tensor` column to a `torch_tensor` by calling `materialize()`. +By default, this will return a list of `torch_tensor`s. + +```{r} +materialize(lt[1:2]) +``` + +We can also convert the `lazy_tensor` to a single tensor by setting `rbind = TRUE`. + +```{r} +materialize(lt[1:2], rbind = TRUE) +``` + +An important feature of the `lazy_tensor` type is that it can be preprocessed like other (non-lazy) datatypes. +Below, we standardize the data using its mean and standard deviation, which we calculate from the materialized tensor. + +```{r} +lt_mat = materialize(lt, rbind = TRUE) +mus = torch_mean(lt_mat, dim = 1L) +sigmas = torch_std(lt_mat, dim = 1L) +po_scale = po("trafo_scale", mean = mus, sd = sigmas) + +tsk_iris_preproc = po_scale$train(list(tsk_iris))[[1L]] +tsk_iris_preproc +``` + +Materializing the (lazily) preprocessed lazy tensor is equivalent to (eagerly) preprocessing the materialized tensor. + +```{r} +lt_preproc = tsk_iris_preproc$data(cols = "x")$x +torch_equal(materialize(lt_preproc, rbind = TRUE), (lt_mat - mus) / sigmas) +``` + +We can combine the preprocessing with a simple multi layer perceptron to create a `GraphLearner`. + +```{r} +glrn = as_learner( + po_scale %>>% lrn("classif.mlp", batch_size = 150, epochs = 10) +) + +glrn$train(tsk("iris")) +``` + + +## Creating a Lazy Tensor + +Every `lazy_tensor` is built on top of a `torch::dataset`, so we start by creating an dataset containing random data. +The only restriction that we impose on the dataset is that it must have a `.getitem` method that returns a list of named tensors. +In this case, the dataset returns a single tensor named `x`. +While the data is stored in-memory in this example, this is not necessary and the `$.getitem()` method can e.g. load images from disk. +For more information on how to create `torch::dataset`s, we recommend reading the [torch package documentation](https://torch.mlverse.org/). + +```{r} +mydata = dataset( + initialize = function() { + self$x = runif(1000, -1, 1) + }, + .getbatch = function(i) list(x = torch_tensor(self$x[i])$unsqueeze(2)), + .length = function() 1000 +)() +``` + +In order to create a `lazy_tensor` from `mydata`, we have to annotate the returned shapes of the dataset by passing a named list to `dataset_shapes`. +The first dimension must be `NA` as it is the batch dimension. +We can also set a shape to `NULL` to indicate that it is unknown (e.g. because it is variable). + +```{r} +lt = as_lazy_tensor(mydata, dataset_shapes = list(x = c(NA, 1))) +lt +``` + +We can convert this vector to a `torch_tensor` just like before + +```{r} +materialize(lt[1], rbind = TRUE) +``` + +Because we added no preprocessing, this is the same as calling the `$.getbatch()` method on `mydata` and selecting the element `x`. + +```{r} +torch_equal( + materialize(lt[1], rbind = TRUE), + mydata$.getbatch(1)$x +) +``` + +We continue with creating an example task from `lt`. + +```{r} +library(data.table) +x = mydata$x +y = 0.2 + 0.1 * x - 0.1 * x^2 - 0.3 * x^3 + 0.5 * x^4 + 0.5 * x^7 + 0.6 * x^11 + rnorm(length(mydata)) * 0.1 +dt = data.table(y = y, x = lt) +task_poly = as_task_regr(dt, target = "y", id = "poly") +``` + +```{r} +library(ggplot2) +ggplot(data = data.frame(x = x, y = y)) + + geom_point(aes(x = x, y = y)) +``` + +In the next section, we will create a custom `PipeOp` to fit a polynomial regression model. + +## Custom Preprocessing + +In order to create a custom preprocessing operator for a lazy tensor, we have to create a new `PipeOp` class. +To make this as convenient as possible, `mlr3torch` offters a `pipeop_preproc_torch()` function that we recommend using for this purpose. +Its most important arguments are: +* `id` - Used as the default identifier of the `PipeOp` +* `fn` - The preprocessing function +* `shapes_out` - A function that returns the shapes of the output tensors given the input shapes + + +```{r} +PipeOpPreprocTorchPoly = pipeop_preproc_torch("poly", + fn = function(x, degrees) { + torch_cat(lapply(degrees, function(d) torch_pow(x, d)), dim = 2L) + }, + shapes_out = function(shapes_in, param_vals, task) { + shape = shapes_in[[1L]] + stopifnot(length(shape) == 2L) + list(c(NA, length(param_vals$degrees))) + } +) + +po_poly = PipeOpPreprocTorchPoly$new() +po_poly$param_set$set_values( + degrees = c(0, 1, 2, 3, 4, 7, 11), + stages = "both" +) + +lrn_poly = as_learner( + po_poly %>>% lrn("regr.mlp", batch_size = 256, epochs = 100) +) + +pred = lrn_poly$predict(task_poly) + +dt = melt(data.table( + truth = pred$truth, + response = pred$response, + x = x), + id.vars = "x", measure.vars = c("truth", "response") +) +dt$variable = factor(dt$variable, levels = c("truth", "response")) + + +ggplot(data = dt) + + geom_point(aes(x = x, y = value, color = variable)) +``` + +## Digging Into Internals + +TODO + + From a52cd1db54d19d40d89dc67fdee7af5ae31c4fbe Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 30 Jan 2024 17:53:40 +0100 Subject: [PATCH 77/90] ... --- R/DataDescriptor.R | 5 +-- R/LearnerTorchMLP.R | 4 +- vignettes/lazy_tensor.Rmd | 86 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 86 insertions(+), 9 deletions(-) diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index 922b9a18..de970ffa 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -155,10 +155,9 @@ DataDescriptor = R6Class("DataDescriptor", catn(sprintf("* dataset_shapes: %s", shape_to_str(self$dataset_shapes))) catn(sprintf("* input_map: (%s) -> Graph", paste0(self$input_map, collapse = ", "))) catn(sprintf("* pointer: %s", paste0(self$pointer, collapse = "."))) - catn(str_indent("* shape(train):", + catn(str_indent("* shape:", if (is.null(self$pointer_shape)) "" else shape_to_str(list(self$pointer_shape)))) - catn(str_indent("* shape(predict):", - if (is.null(self$pointer_shape_predict)) "" else shape_to_str(list(self$pointer_shape_predict)))) + # dont print the predict shape, it is too confusing }, #' @field dataset ([`torch::dataset`])\cr #' The dataset. diff --git a/R/LearnerTorchMLP.R b/R/LearnerTorchMLP.R index 22f61cba..767484c5 100644 --- a/R/LearnerTorchMLP.R +++ b/R/LearnerTorchMLP.R @@ -46,8 +46,8 @@ LearnerTorchMLP = R6Class("LearnerTorchMLP", activation = p_uty(tags = c("required", "train"), custom_check = check_activation), activation_args = p_uty(tags = c("required", "train"), custom_check = check_activation_args), shape = p_uty(default = NULL, tags = "train", custom_check = crate(function(x) { - check_shape(x, null_ok = TRUE) - })) + check_shape(x, null_ok = TRUE) + }, .parent = topenv())) ) param_set$set_values( activation = nn_relu, diff --git a/vignettes/lazy_tensor.Rmd b/vignettes/lazy_tensor.Rmd index 28efe22f..7230fff7 100644 --- a/vignettes/lazy_tensor.Rmd +++ b/vignettes/lazy_tensor.Rmd @@ -75,7 +75,7 @@ glrn$train(tsk("iris")) ## Creating a Lazy Tensor Every `lazy_tensor` is built on top of a `torch::dataset`, so we start by creating an dataset containing random data. -The only restriction that we impose on the dataset is that it must have a `.getitem` method that returns a list of named tensors. +The only restriction that we impose on the dataset is that it must have a `.getitem` or `.getbatch` method that returns a list of named tensors. In this case, the dataset returns a single tensor named `x`. While the data is stored in-memory in this example, this is not necessary and the `$.getitem()` method can e.g. load images from disk. For more information on how to create `torch::dataset`s, we recommend reading the [torch package documentation](https://torch.mlverse.org/). @@ -96,7 +96,7 @@ We can also set a shape to `NULL` to indicate that it is unknown (e.g. because i ```{r} lt = as_lazy_tensor(mydata, dataset_shapes = list(x = c(NA, 1))) -lt +lt[1:5] ``` We can convert this vector to a `torch_tensor` just like before @@ -155,15 +155,18 @@ PipeOpPreprocTorchPoly = pipeop_preproc_torch("poly", ) po_poly = PipeOpPreprocTorchPoly$new() + +# We want to apply the preprocessing during both `"train"` and `"predict"` and set te stages parameter accordingly. po_poly$param_set$set_values( degrees = c(0, 1, 2, 3, 4, 7, 11), stages = "both" ) lrn_poly = as_learner( - po_poly %>>% lrn("regr.mlp", batch_size = 256, epochs = 100) + po_poly %>>% lrn("regr.mlp", batch_size = 256, epochs = 20) ) +lrn_poly$train(task_poly) pred = lrn_poly$predict(task_poly) dt = melt(data.table( @@ -181,6 +184,81 @@ ggplot(data = dt) + ## Digging Into Internals -TODO +Internally, the `lazy_tensor` vector uses the `DataDescriptor` class to represent the (possibly) preprocessed data. +It is very similar to the `ModelDescriptor` class that is used to build up neural nerworks using `PipeOpTorch` objects. +The `DataDescriptor` stores a `torch::dataset`, an `mlr3pipelines::Graph` and some metadata. + + +```{r} +desc = DataDescriptor$new( + dataset = mydata, + dataset_shapes = list(x = c(NA, 1)) +) +``` + +Per default, the preprocessing graph contains only a single `PipOpNop` that doees nothing. + +```{r} +desc +``` + +The printed output of the data descriptor informs us about: + +* The number of `PipeOp`s contained in the preprocessing graph +* The output shapes of the dataset +* The input map, i.e. how the data is passed to the preprocessing graph, which is important when there are multiple inputs +* The `pointer`, which points to a specific channel of an output `PipeOp`. + The output of this channel is the tensor represented by the `DataDescriptor`. + + +A lazy tensor can be constructed from an integer vector and a `DataDescriptor`. +The integer vector specifies which element of the `DataDescriptor` an element of the `lazy_tensor` vector represents. +Below, the first two elements of the `lazy_tensor` vector represent the same element of the `DataDescriptor`, while the third element represents a different element. +Note that all indices refer to the same `DataDescriptor`. + +```{r} +lt = lazy_tensor(desc, ids = c(1, 1, 2)) +materialize(lt, rbind = TRUE) +``` + +Internally, the lazy tensor is represented as a list of lists, containing an id and a `DataDescriptor` +Currently, there can only be a single `DataDescriptor` in a `lazy_tensor` vector. + +```{r} +unclass(lt[[1]]) +``` + + +What happens during `materialize(lt[1])` is the following: + +```{r} +# get index and data descriptor +desc = lt[[1]][[2]] +id = lt[[1]][[1]] +dataset_output = desc$dataset$.getbatch(id) + +# batch is reorganized according to the input map +graph_input = dataset_output[desc$input_map] +names(graph_input) = names(desc$graph$input$name) +# the reorganized batch is fed into the preprocessing graph +graph_output = desc$graph$train(graph_input, single_input = FALSE) +# the output pointed to by the pointer is returned +tensor = graph_output[[paste0(desc$pointer, collapse = ".")]] +tensor +``` +Preprocessing a `lazy_tensor` vector adds new `PipeOp`s to the preprocessing graph and updates the metainformation like the pointer and output shape. +To show this, we create a simple example task, using the `lt` vector as a feature. + +```{r} +taskin = as_task_regr(data.table(x = lt, y = 1:3), target = "y") + +taskout = po_poly$train(list(taskin))[[1L]] + +lt_out = taskout$data(cols = "x")$x + +descout = lt_out[[1]][[2]] + +descout$graph +``` From 9c88bd36f74bd1de41a14b4e218091dfed9670f6 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Tue, 30 Jan 2024 17:59:34 +0100 Subject: [PATCH 78/90] pkgdown --- pkgdown/_pkgdown.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index 99c0a9b4..9de89df1 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -44,3 +44,7 @@ articles: navbar: ~ contents: - get_started +- title: Lazy Tensor + navbar: ~ + contents: + - lazy_tensor From a818ea83a12b3164c1a3f4622b0e4fa05364ebd2 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 31 Jan 2024 08:36:58 +0100 Subject: [PATCH 79/90] ... --- R/LearnerTorchMLP.R | 46 +++++++++++++++++++++++-------------- R/preprocess.R | 4 ++++ R/task_dataset.R | 2 +- R/utils.R | 17 -------------- R/zzz.R | 2 +- benchmarks/dataset.R | 11 +++++++++ man/mlr_learners.mlp.Rd | 14 +++++------ tests/testthat/test_shape.R | 2 ++ 8 files changed, 55 insertions(+), 43 deletions(-) create mode 100644 benchmarks/dataset.R diff --git a/R/LearnerTorchMLP.R b/R/LearnerTorchMLP.R index 767484c5..e3a0c108 100644 --- a/R/LearnerTorchMLP.R +++ b/R/LearnerTorchMLP.R @@ -9,7 +9,7 @@ #' #' @description #' Fully connected feed forward network with dropout after each activation function. -#' The features can either be a single [`lazy_tensor`] or one or more numeric columns. +#' The features can either be a single [`lazy_tensor`] or one or more numeric columns (but not both). #' #' @section Parameters: #' Parameters from [`LearnerTorch`], as well as: @@ -20,14 +20,14 @@ #' A named list with initialization arguments for the activation function. #' This is intialized to an empty list. #' * `neurons` :: `integer()`\cr -#' The number of neurons per hidden layer. -#' By default there is no hidden layer. +#' The number of neurons per hidden layer. By default there is no hidden layer. +#' Setting this to `c(10, 20)` would have a the first hidden layer with 10 neurons and the second with 20. #' * `p` :: `numeric(1)`\cr -#' The dropout probability. -#' Is initialized to `0.5`. +#' The dropout probability. Is initialized to `0.5`. #' * `shape` :: `integer()` or `NULL`\cr -#' The input shape. -#' Only needs to be present specified when there is a lazy tensor input with unknown shape. +#' The input shape of length 2, e.g. `c(NA, 5)`. +#' Only needs to be present when there is a lazy tensor input with unknown shape (`NULL`). +#' Otherwise the input shape is inferred from the number of numeric features. #' #' @export LearnerTorchMLP = R6Class("LearnerTorchMLP", @@ -38,21 +38,22 @@ LearnerTorchMLP = R6Class("LearnerTorchMLP", initialize = function(task_type, optimizer = NULL, loss = NULL, callbacks = list()) { check_activation = crate(function(x) check_class(x, "nn_module"), .parent = topenv()) check_activation_args = crate(function(x) check_list(x, names = "unique"), .parent = topenv()) + check_neurons = crate(function(x) check_integerish(x, any.missing = FALSE, lower = 1), .parent = topenv()) + cehck_shape = crate(function(x) check_shape(x, null_ok = TRUE, len = 2L), .parent = topenv()) + param_set = ps( - neurons = p_uty(default = integer(0), tags = "train", custom_check = crate(function(x) { - check_integerish(x, any.missing = FALSE, lower = 1) - })), + neurons = p_uty(tags = c("train", "predict"), custom_check = check_neurons), p = p_dbl(lower = 0, upper = 1, tags = c("required", "train")), activation = p_uty(tags = c("required", "train"), custom_check = check_activation), activation_args = p_uty(tags = c("required", "train"), custom_check = check_activation_args), - shape = p_uty(default = NULL, tags = "train", custom_check = crate(function(x) { - check_shape(x, null_ok = TRUE) - }, .parent = topenv())) + shape = p_uty(tags = "train", custom_check = check_shape) ) + param_set$set_values( activation = nn_relu, p = 0.5, - activation_args = list() + activation_args = list(), + neurons = integer(0) ) properties = switch(task_type, regr = character(0), @@ -78,7 +79,7 @@ LearnerTorchMLP = R6Class("LearnerTorchMLP", # verify_train_task was already called beforehand, so we can make some assumptions d_out = get_nout(task) d_in = if (single_lazy_tensor(task)) { - get_unique_shape(task, param_vals$shape)[2L] + private$.get_input_shape(task, param_vals$shape)[2L] } else { length(task$feature_names) } @@ -87,7 +88,7 @@ LearnerTorchMLP = R6Class("LearnerTorchMLP", }, .dataset = function(task, param_vals) { if (single_lazy_tensor(task)) { - param_vals$shape = get_unique_shape(task, param_vals$shape) + param_vals$shape = private$.get_input_shape(task, param_vals$shape) dataset_ltnsr(task, param_vals) } else { dataset_num(task, param_vals) @@ -99,9 +100,20 @@ LearnerTorchMLP = R6Class("LearnerTorchMLP", assert(check_true(lazy_tensor_input), check_false(some(features, function(x) x == "lazy_tensor"))) if (lazy_tensor_input) { - shape = get_unique_shape(task, param_vals$shape) + shape = private$.get_input_shape(task, param_vals$shape) assert_shape(shape, len = 2L) } + }, + .get_input_shape = function(s1, s2) { + if (test_class(s1, "Task")) { + assert_true(identical(s1$feature_types[, "type"][[1L]], "lazy_tensor")) + s1 = dd(s1$data(s1$row_roles$use[1L], s1$feature_names)[[1L]])$pointer_shape + } + assert_shape(s1, null_ok = TRUE) + assert_shape(s2, null_ok = TRUE) + s = unique(discard(list(s1, s2), is.null)) + assert_true(length(s) == 1L) + s[[1L]] } ) ) diff --git a/R/preprocess.R b/R/preprocess.R index e19d21cf..0d52fdea 100644 --- a/R/preprocess.R +++ b/R/preprocess.R @@ -37,6 +37,10 @@ unchanged_shapes_image = function(shapes_in, param_vals, task) { shapes_in } +unchanged_shapes = function(shapes_in, param_vals, task) { + shapes_in +} + #' @title PipeOpPreprocTorchTrafoNop #' @usage NULL #' @name mlr_pipeops_preproc_torch.trafo_nop diff --git a/R/task_dataset.R b/R/task_dataset.R index c47bbeda..f0bf678e 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -165,7 +165,7 @@ dataset_num = function(task, param_vals) { names(ingress) = "input" task_dataset( task = task, - feature_ingress_tokens = ingress, + feature_ingress_tokens = md$ingress, target_batchgetter = get_target_batchgetter(task$task_type), device = param_vals$device ) diff --git a/R/utils.R b/R/utils.R index d985b141..15ac4f03 100644 --- a/R/utils.R +++ b/R/utils.R @@ -194,20 +194,3 @@ auto_cache_lazy_tensors = function(lts) { any(duplicated(map_chr(lts, function(x) dd(x)$dataset_hash))) } -unchanged_shapes = function(shapes_in, param_vals, task) { - shapes_in -} - -get_unique_shape = function(s1, s2) { - if (test_class(s1, "Task")) { - assert_true(identical(s1$feature_types[, "type"][[1L]], "lazy_tensor")) - s1 = dd(s1$data(s1$row_roles$use[1L], s1$feature_names)[[1L]])$pointer_shape - } - assert_shape(s1, null_ok = TRUE) - assert_shape(s2, null_ok = TRUE) - s = unique(discard(list(s1, s2), is.null)) - assert_true(length(s) == 1L) - s[[1L]] -} - -assert_compatible_shapes = get_unique_shape diff --git a/R/zzz.R b/R/zzz.R index 8f7f09e4..2cdfaf59 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -95,9 +95,9 @@ register_mlr3 = function() { register_mlr3pipelines = function() { mlr_pipeops = utils::getFromNamespace("mlr_pipeops", ns = "mlr3pipelines") + add = mlr_pipeops$add # nolint iwalk(as.list(mlr3torch_pipeops), function(value, name) { # metainf is quoted by pipelines - add = mlr_pipeops$add eval(call("add", quote(name), quote(value$constructor), value$metainf)) }) mlr_reflections$pipeops$valid_tags = unique(c(mlr_reflections$pipeops$valid_tags, mlr3torch_pipeop_tags)) diff --git a/benchmarks/dataset.R b/benchmarks/dataset.R new file mode 100644 index 00000000..bc227ea4 --- /dev/null +++ b/benchmarks/dataset.R @@ -0,0 +1,11 @@ +devtools::load_all("~/mlr/mlr3") +devtools::load_all("~/mlr/mlr3torch") + +lazy_iris = tsk("lazy_iris") +dt = lazy_iris$data(cols = "x")$x +dataset = dt[[1L]][[2L]]$dataset + +dt = do.call(c, args = lapply(1:1000, function(i) dt)) + + +profvis::profvis({materialize_internal(dt, rbind = TRUE)}) diff --git a/man/mlr_learners.mlp.Rd b/man/mlr_learners.mlp.Rd index a18ef202..fcdb2ef2 100644 --- a/man/mlr_learners.mlp.Rd +++ b/man/mlr_learners.mlp.Rd @@ -6,7 +6,7 @@ \title{My Little Pony} \description{ Fully connected feed forward network with dropout after each activation function. -The features can either be a single \code{\link{lazy_tensor}} or one or more numeric columns. +The features can either be a single \code{\link{lazy_tensor}} or one or more numeric columns (but not both). } \section{Dictionary}{ @@ -53,14 +53,14 @@ The activation function. Is initialized to \code{\link{nn_relu}}. A named list with initialization arguments for the activation function. This is intialized to an empty list. \item \code{neurons} :: \code{integer()}\cr -The number of neurons per hidden layer. -By default there is no hidden layer. +The number of neurons per hidden layer. By default there is no hidden layer. +Setting this to \code{c(10, 20)} would have a the first hidden layer with 10 neurons and the second with 20. \item \code{p} :: \code{numeric(1)}\cr -The dropout probability. -Is initialized to \code{0.5}. +The dropout probability. Is initialized to \code{0.5}. \item \code{shape} :: \code{integer()} or \code{NULL}\cr -The input shape. -Only needs to be present specified when there is a lazy tensor input with unknown shape. +The input shape of length 2, e.g. \code{c(NA, 5)}. +Only needs to be present when there is a lazy tensor input with unknown shape (\code{NULL}). +Otherwise the input shape is inferred from the number of numeric features. } } diff --git a/tests/testthat/test_shape.R b/tests/testthat/test_shape.R index e5a68d8f..dbafcb4d 100644 --- a/tests/testthat/test_shape.R +++ b/tests/testthat/test_shape.R @@ -19,4 +19,6 @@ test_that("assert_shape and friends", { expect_error(assert_shapes(list(c(1, 2), c(2, 3))), regexp = NA) expect_error(assert_shapes(list(c(4, 5), c(2, 3)), unknown_batch = TRUE)) expect_error(assert_shape(c(NA, 1, 2), len = 2)) + # NULL is ok even when len is specified + expect_true(check_shape(NULL, null_ok = TRUE, len = 2)) }) From 15b74cdcde1033b1f1946a72c977e8fea159d2e9 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 31 Jan 2024 12:46:45 +0100 Subject: [PATCH 80/90] ... --- R/learner_torch_methods.R | 20 -------------------- tests/testthat/helper_autotest.R | 2 +- tests/testthat/test_CallbackSetHistory.R | 1 - 3 files changed, 1 insertion(+), 22 deletions(-) diff --git a/R/learner_torch_methods.R b/R/learner_torch_methods.R index 45bcc8b5..07f322d1 100644 --- a/R/learner_torch_methods.R +++ b/R/learner_torch_methods.R @@ -9,25 +9,6 @@ normalize_to_list = function(x) { x } -learner_torch_initialize = function( - self, - private, - super, - task_type, - id, - optimizer, - loss, - param_set, - properties, - packages, - predict_types, - feature_types, - man, - label, - callbacks - ) { -} - learner_torch_predict = function(self, private, super, task, param_vals) { # parameter like device "auto" already resolved self$network$to(device = param_vals$device) @@ -41,7 +22,6 @@ learner_torch_train = function(self, private, super, task, param_vals) { # Here, all param_vals (like seed = "random" or device = "auto") have already been resolved loader_train = private$.dataloader(task, param_vals) - network = private$.network(task, param_vals)$to(device = param_vals$device) optimizer = private$.optimizer$generate(network$parameters) loss_fn = private$.loss$generate() diff --git a/tests/testthat/helper_autotest.R b/tests/testthat/helper_autotest.R index 7f7f4ddf..360cef84 100644 --- a/tests/testthat/helper_autotest.R +++ b/tests/testthat/helper_autotest.R @@ -385,7 +385,7 @@ autotest_pipeop_torch_preprocess = function(obj, shapes_in, exclude = character( #' @descrition #' The autotest for torch learners differs from the standard mlr3 autotest for learners. #' The reason is, that we do not have to test the -autotest_learner_torch = function(learner) { +expect_learner_torch = function(learner) { } diff --git a/tests/testthat/test_CallbackSetHistory.R b/tests/testthat/test_CallbackSetHistory.R index 8b461440..5ae537f9 100644 --- a/tests/testthat/test_CallbackSetHistory.R +++ b/tests/testthat/test_CallbackSetHistory.R @@ -1,6 +1,5 @@ test_that("Autotest", { cb = t_clbk("history") - autotest_torch_callback(cb) }) From 099bf5c3865a8c8e5b6cefba7c4944ba2a3c83e0 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 31 Jan 2024 12:57:57 +0100 Subject: [PATCH 81/90] init vs default --- R/LearnerTorchMLP.R | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/R/LearnerTorchMLP.R b/R/LearnerTorchMLP.R index e3a0c108..4696c3a9 100644 --- a/R/LearnerTorchMLP.R +++ b/R/LearnerTorchMLP.R @@ -43,7 +43,7 @@ LearnerTorchMLP = R6Class("LearnerTorchMLP", param_set = ps( neurons = p_uty(tags = c("train", "predict"), custom_check = check_neurons), - p = p_dbl(lower = 0, upper = 1, tags = c("required", "train")), + p = p_dbl(default = 0.5, lower = 0, upper = 1), activation = p_uty(tags = c("required", "train"), custom_check = check_activation), activation_args = p_uty(tags = c("required", "train"), custom_check = check_activation_args), shape = p_uty(tags = "train", custom_check = check_shape) @@ -51,7 +51,6 @@ LearnerTorchMLP = R6Class("LearnerTorchMLP", param_set$set_values( activation = nn_relu, - p = 0.5, activation_args = list(), neurons = integer(0) ) From d9a8c98552f5efb253dc4466f4bbbb5181ef22cb Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 7 Feb 2024 17:17:46 +0100 Subject: [PATCH 82/90] many fixes --- .github/workflows/pkgdown.yml | 5 +- .github/workflows/r-cmd-check.yml | 5 +- DESCRIPTION | 7 +- R/DataDescriptor.R | 4 +- R/LearnerTorchAlexNet.R | 1 - R/LearnerTorchMLP.R | 13 +-- R/PipeOpTorchReshape.R | 10 --- R/materialize.R | 3 +- R/paramset_torchlearner.R | 2 +- R/task_dataset.R | 32 +++++-- R/utils.R | 2 +- R/zzz.R | 3 +- TODO.md | 4 +- {vignettes => attic}/lazy_tensor.Rmd | 0 man/ModelDescriptor.Rd | 4 +- man/TorchCallback.Rd | 4 +- man/TorchIngressToken.Rd | 4 +- man/as_torch_callback.Rd | 2 +- man/as_torch_callbacks.Rd | 2 +- man/callback_set.Rd | 4 +- man/materialize_internal.Rd | 3 +- man/mlr3torch_callbacks.Rd | 4 +- man/mlr_callback_set.Rd | 2 +- man/mlr_callback_set.checkpoint.Rd | 4 +- man/mlr_callback_set.progress.Rd | 4 +- man/mlr_context_torch.Rd | 4 +- man/mlr_learners.alexnet.Rd | 4 +- man/mlr_learners.mlp.Rd | 4 +- man/mlr_learners.torch_featureless.Rd | 4 +- man/mlr_learners_torch_image.Rd | 4 +- man/mlr_learners_torch_model.Rd | 8 +- man/mlr_pipeops_module.Rd | 4 +- man/mlr_pipeops_nn_avg_pool1d.Rd | 12 +-- man/mlr_pipeops_nn_avg_pool2d.Rd | 12 +-- man/mlr_pipeops_nn_avg_pool3d.Rd | 12 +-- man/mlr_pipeops_nn_batch_norm1d.Rd | 12 +-- man/mlr_pipeops_nn_batch_norm2d.Rd | 12 +-- man/mlr_pipeops_nn_batch_norm3d.Rd | 12 +-- man/mlr_pipeops_nn_celu.Rd | 12 +-- man/mlr_pipeops_nn_conv1d.Rd | 12 +-- man/mlr_pipeops_nn_conv2d.Rd | 12 +-- man/mlr_pipeops_nn_conv3d.Rd | 12 +-- man/mlr_pipeops_nn_conv_transpose1d.Rd | 12 +-- man/mlr_pipeops_nn_conv_transpose2d.Rd | 12 +-- man/mlr_pipeops_nn_conv_transpose3d.Rd | 12 +-- man/mlr_pipeops_nn_dropout.Rd | 12 +-- man/mlr_pipeops_nn_elu.Rd | 12 +-- man/mlr_pipeops_nn_flatten.Rd | 12 +-- man/mlr_pipeops_nn_gelu.Rd | 12 +-- man/mlr_pipeops_nn_glu.Rd | 12 +-- man/mlr_pipeops_nn_hardshrink.Rd | 12 +-- man/mlr_pipeops_nn_hardsigmoid.Rd | 12 +-- man/mlr_pipeops_nn_hardtanh.Rd | 12 +-- man/mlr_pipeops_nn_head.Rd | 12 +-- man/mlr_pipeops_nn_layer_norm.Rd | 12 +-- man/mlr_pipeops_nn_leaky_relu.Rd | 12 +-- man/mlr_pipeops_nn_linear.Rd | 12 +-- man/mlr_pipeops_nn_log_sigmoid.Rd | 12 +-- man/mlr_pipeops_nn_max_pool1d.Rd | 12 +-- man/mlr_pipeops_nn_max_pool2d.Rd | 12 +-- man/mlr_pipeops_nn_max_pool3d.Rd | 12 +-- man/mlr_pipeops_nn_merge.Rd | 10 +-- man/mlr_pipeops_nn_merge_cat.Rd | 12 +-- man/mlr_pipeops_nn_merge_prod.Rd | 12 +-- man/mlr_pipeops_nn_merge_sum.Rd | 24 ++--- man/mlr_pipeops_nn_prelu.Rd | 12 +-- man/mlr_pipeops_nn_relu.Rd | 10 +-- man/mlr_pipeops_nn_relu6.Rd | 10 +-- man/mlr_pipeops_nn_reshape.Rd | 12 +-- man/mlr_pipeops_nn_rrelu.Rd | 12 +-- man/mlr_pipeops_nn_selu.Rd | 12 +-- man/mlr_pipeops_nn_sigmoid.Rd | 12 +-- man/mlr_pipeops_nn_softmax.Rd | 12 +-- man/mlr_pipeops_nn_softplus.Rd | 12 +-- man/mlr_pipeops_nn_softshrink.Rd | 12 +-- man/mlr_pipeops_nn_softsign.Rd | 12 +-- man/mlr_pipeops_nn_squeeze.Rd | 24 ++--- man/mlr_pipeops_nn_tanh.Rd | 10 +-- man/mlr_pipeops_nn_tanhshrink.Rd | 10 +-- man/mlr_pipeops_nn_threshold.Rd | 12 +-- man/mlr_pipeops_torch.Rd | 2 +- man/mlr_pipeops_torch_ingress.Rd | 12 +-- man/mlr_pipeops_torch_ingress_categ.Rd | 16 ++-- man/mlr_pipeops_torch_ingress_ltnsr.Rd | 16 ++-- man/mlr_pipeops_torch_ingress_num.Rd | 16 ++-- man/mlr_pipeops_torch_loss.Rd | 12 +-- man/mlr_pipeops_torch_model.Rd | 8 +- man/mlr_pipeops_torch_model_classif.Rd | 12 +-- man/mlr_pipeops_torch_model_regr.Rd | 12 +-- man/model_descriptor_to_learner.Rd | 4 +- man/model_descriptor_to_module.Rd | 4 +- man/model_descriptor_union.Rd | 4 +- man/nn_graph.Rd | 4 +- man/t_clbk.Rd | 4 +- man/torch_callback.Rd | 4 +- tests/testthat/helper_autotest.R | 12 +-- tests/testthat/helper_learner.R | 2 +- tests/testthat/test_CallbackSetCheckpoint.R | 2 +- tests/testthat/test_CallbackSetHistory.R | 2 +- tests/testthat/test_CallbackSetProgress.R | 2 +- tests/testthat/test_PipeOpTorchActivation.R | 88 +++++++++---------- tests/testthat/test_PipeOpTorchAvgPool.R | 12 +-- tests/testthat/test_PipeOpTorchBatchNorm.R | 14 +-- tests/testthat/test_PipeOpTorchConv.R | 12 +-- .../testthat/test_PipeOpTorchConvTranspose.R | 12 +-- tests/testthat/test_PipeOpTorchDropout.R | 4 +- tests/testthat/test_PipeOpTorchHead.R | 4 +- tests/testthat/test_PipeOpTorchLayerNorm.R | 4 +- tests/testthat/test_PipeOpTorchLinear.R | 4 +- tests/testthat/test_PipeOpTorchMaxPool.R | 12 +-- tests/testthat/test_PipeOpTorchMerge.R | 12 +-- tests/testthat/test_PipeOpTorchReshape.R | 16 ++-- tests/testthat/test_TorchLoss.R | 6 +- tests/testthat/test_TorchOptimizer.R | 14 +-- tests/testthat/test_autotests.R | 50 +++++------ tests/testthat/test_lazy_tensor.R | 2 +- tests/testthat/test_learner_torch_methods.R | 4 +- tests/testthat/test_preprocess.R | 64 +++++++------- tests/testthat/test_task_dataset.R | 52 ++++++++++- 119 files changed, 667 insertions(+), 619 deletions(-) rename {vignettes => attic}/lazy_tensor.Rmd (100%) diff --git a/.github/workflows/pkgdown.yml b/.github/workflows/pkgdown.yml index eeac52da..44640701 100644 --- a/.github/workflows/pkgdown.yml +++ b/.github/workflows/pkgdown.yml @@ -22,6 +22,7 @@ jobs: group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + TORCH_INSTALL: 1 steps: - uses: actions/checkout@v3 @@ -34,10 +35,6 @@ jobs: extra-packages: any::pkgdown, local::. needs: website - - name: Install torch - run: torch::install_torch() - shell: Rscript {0} - - name: Install template run: pak::pkg_install("mlr-org/mlr3pkgdowntemplate") shell: Rscript {0} diff --git a/.github/workflows/r-cmd-check.yml b/.github/workflows/r-cmd-check.yml index 71f6708a..a3849980 100644 --- a/.github/workflows/r-cmd-check.yml +++ b/.github/workflows/r-cmd-check.yml @@ -28,6 +28,7 @@ jobs: env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + TORCH_INSTALL: 1 strategy: fail-fast: false @@ -52,10 +53,6 @@ jobs: extra-packages: any::rcmdcheck needs: check - - name: Install torch - run: torch::install_torch() - shell: Rscript {0} - - uses: r-lib/actions/check-r-package@v2 - uses: mxschmitt/action-tmate@v3 diff --git a/DESCRIPTION b/DESCRIPTION index d0aa69fd..aae8dbf3 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -60,12 +60,9 @@ Suggests: rmarkdown, viridis, testthat (>= 3.0.0), - torchvision, - zip + torchvision Remotes: - r-lib/zip, mlr-org/mlr3, - mlr-org/mlr3misc@feat/custom-hash-info, mlr-org/mlr3pipelines@feat/keep_results, mlverse/torchvision Config/testthat/edition: 3 @@ -74,7 +71,7 @@ ByteCompile: no VignetteBuilder: knitr Encoding: UTF-8 Roxygen: list(markdown = TRUE, r6 = TRUE) -RoxygenNote: 7.2.3.9000 +RoxygenNote: 7.3.1 Collate: 'CallbackSet.R' 'zzz.R' diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index de970ffa..622ace6c 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -90,7 +90,7 @@ DataDescriptor = R6Class("DataDescriptor", } # get unique ID for input PipeOp graph = as_graph(po("nop", id = - paste0("nop.", substr(calculate_hash(address(dataset)), 1, 4)) + paste0("nop.", substr(calculate_hash(address(dataset)), 1, 4), ".", input_map) ), clone = FALSE) } else { graph = as_graph(graph, clone = clone_graph) @@ -105,7 +105,7 @@ DataDescriptor = R6Class("DataDescriptor", } else { assert_subset(input_map, names(dataset_shapes)) } - if (is.null(pointer) && simple_case) { + if (is.null(pointer) && nrow(graph$output) == 1L) { pointer = c(graph$output$op.id, graph$output$channel.name) } else { assert_character(pointer, len = 2L) diff --git a/R/LearnerTorchAlexNet.R b/R/LearnerTorchAlexNet.R index 2d91e70d..7035c718 100644 --- a/R/LearnerTorchAlexNet.R +++ b/R/LearnerTorchAlexNet.R @@ -1,4 +1,3 @@ -# TODO #' @title AlexNet Image Classifier #' #' @templateVar name alexnet diff --git a/R/LearnerTorchMLP.R b/R/LearnerTorchMLP.R index 4696c3a9..58553206 100644 --- a/R/LearnerTorchMLP.R +++ b/R/LearnerTorchMLP.R @@ -36,14 +36,14 @@ LearnerTorchMLP = R6Class("LearnerTorchMLP", #' @description #' Creates a new instance of this [R6][R6::R6Class] class. initialize = function(task_type, optimizer = NULL, loss = NULL, callbacks = list()) { - check_activation = crate(function(x) check_class(x, "nn_module"), .parent = topenv()) - check_activation_args = crate(function(x) check_list(x, names = "unique"), .parent = topenv()) - check_neurons = crate(function(x) check_integerish(x, any.missing = FALSE, lower = 1), .parent = topenv()) - cehck_shape = crate(function(x) check_shape(x, null_ok = TRUE, len = 2L), .parent = topenv()) + check_activation = crate(function(x) check_class(x, "nn_module")) + check_activation_args = crate(function(x) check_list(x, names = "unique")) + check_neurons = crate(function(x) check_integerish(x, any.missing = FALSE, lower = 1)) + cechk_shape = crate(function(x) check_shape(x, null_ok = TRUE, len = 2L)) param_set = ps( neurons = p_uty(tags = c("train", "predict"), custom_check = check_neurons), - p = p_dbl(default = 0.5, lower = 0, upper = 1), + p = p_dbl(lower = 0, upper = 1, tags = "train"), activation = p_uty(tags = c("required", "train"), custom_check = check_activation), activation_args = p_uty(tags = c("required", "train"), custom_check = check_activation_args), shape = p_uty(tags = "train", custom_check = check_shape) @@ -52,7 +52,8 @@ LearnerTorchMLP = R6Class("LearnerTorchMLP", param_set$set_values( activation = nn_relu, activation_args = list(), - neurons = integer(0) + neurons = integer(0), + p = 0.5 ) properties = switch(task_type, regr = character(0), diff --git a/R/PipeOpTorchReshape.R b/R/PipeOpTorchReshape.R index fd531107..40c9a8c0 100644 --- a/R/PipeOpTorchReshape.R +++ b/R/PipeOpTorchReshape.R @@ -21,16 +21,6 @@ PipeOpTorchReshape = R6Class("PipeOpTorchReshape", #' @description Creates a new instance of this [R6][R6::R6Class] class. #' @template params_pipelines initialize = function(id = "nn_reshape", param_vals = list()) { - check_shape = function(x) { - x[x == -1] = NA - assert_integerish(shape, lower = 1) - if (sum(is.na(shape)) > 1) { - return("Parameter 'shape' must only contain one -1 or NA.") - } else if (!is.na(x[1])) { - return("First dimension should be -1 or NA.") - } - return(TRUE) - } param_set = ps( shape = p_uty(tags = c("train", "required"), custom_check = check_integerish) ) diff --git a/R/materialize.R b/R/materialize.R index 486d8e42..1d94704b 100644 --- a/R/materialize.R +++ b/R/materialize.R @@ -125,7 +125,7 @@ get_output = function(input, graph, varying_shapes, rbind, device) { #' @title Materialize a Lazy Tensor #' @description -#' Convert a [`lazy_tensor()`] to a [`torch_tensor()`]. +#' Convert a [`lazy_tensor`] to a [`torch_tensor`]. #' #' @details #' Materializing a lazy tensor consists of: @@ -135,6 +135,7 @@ get_output = function(input, graph, varying_shapes, rbind, device) { #' #' When materializing multiple [`lazy_tensor`] columns, caching can be useful because: #' a) Output(s) from the dataset might be input to multiple graphs. +#' (in task_dataset this is shoudl rarely be the case because because we try to merge them). #' b) Different lazy tensors might be outputs from the same graph. #' #' For this reason it is possible to provide a cache environment. diff --git a/R/paramset_torchlearner.R b/R/paramset_torchlearner.R index 7fcb686a..897d48c1 100644 --- a/R/paramset_torchlearner.R +++ b/R/paramset_torchlearner.R @@ -26,7 +26,7 @@ make_check_measures = function(task_type) { return("Measures must not require a learner or model.") } return(TRUE) - }, task_type, .parent = topenv()) + }, task_type) } diff --git a/R/task_dataset.R b/R/task_dataset.R index f0bf678e..6326d600 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -48,6 +48,7 @@ task_dataset = dataset( stopf("Received ingress token '%s' with no features.", nm) } }) + assert_list(feature_ingress_tokens, types = "TorchIngressToken", names = "unique", min.len = 1L) self$feature_ingress_tokens = assert_list(feature_ingress_tokens, types = "TorchIngressToken", names = "unique") self$all_features = unique(c(unlist(map(feature_ingress_tokens, "features")), task$target_names)) assert_subset(self$all_features, c(task$target_names, task$feature_names)) @@ -59,10 +60,13 @@ task_dataset = dataset( data = self$task$data(cols = lazy_tensor_features) # Here, we could have multiple `lazy_tensor` columns that share parts of the graph - # We try to merge those graphs if possible + # we only try to merge those with the same DataDescriptor, this is a restriction which we might want to + # relax later, but it eases data-loading if (length(lazy_tensor_features) > 1L) { - merge_result = merge_lazy_tensor_graphs(data) - self$task$cbind(merge_result) + merged_cols = merge_lazy_tensor_graphs(data) + if (!is.null(merged_cols)) { + self$task$cbind(merged_cols) + } } self$cache_lazy_tensors = auto_cache_lazy_tensors(data) @@ -86,16 +90,26 @@ task_dataset = dataset( } ) +# This returns a merge_lazy_tensor_graphs = function(lts) { - names_lts = names(lts) - # we only attempt to merge preprocessing graphs that have the same dataset_hash hashes = map_chr(lts, function(lt) dd(lt)$dataset_hash) - lts = unlist(map(unique(hashes), function(hash) { - merge_compatible_lazy_tensor_graphs(lts[, names_lts[hashes == hash], with = FALSE]) - }), recursive = FALSE) + # we remove columns that don't share dataset_hash with other columns + hashes_to_merge = unique(hashes[duplicated(hashes)]) + lts = lts[, hashes %in% hashes_to_merge, with = FALSE] + hashes_subset = map_chr(lts, function(lt) dd(lt)$dataset_hash) + + names_lts = names(lts) + lts = map(hashes_to_merge, function(hash) { + x = try(merge_compatible_lazy_tensor_graphs(lts[, names_lts[hashes_subset == hash], with = FALSE]), silent = TRUE) + if (inherits(x, "try-error")) { + lg$warn("Cannot merge lazy tensors with data descriptor with hash '%s'", hash) + return(NULL) + } + x + }) - as_data_backend(as.data.table(set_names(lts, names_lts))) + Reduce(cbind, lts) } merge_compatible_lazy_tensor_graphs = function(lts) { diff --git a/R/utils.R b/R/utils.R index 15ac4f03..527dd3a4 100644 --- a/R/utils.R +++ b/R/utils.R @@ -43,7 +43,7 @@ make_check_vector = function(d) { } tmp = if (d == 1) "." else sprintf(" or %s.", d) sprintf("Must be an integerish vector of length 1%s", tmp) - }, d, .parent = topenv()) + }, d) } check_function_or_null = function(x) check_function(x, null.ok = TRUE) diff --git a/R/zzz.R b/R/zzz.R index 2cdfaf59..db74ea2d 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -49,7 +49,7 @@ register_learner = function(name, constructor) { # For this reason, we need this hacky solution here, might change in the future in mlr3misc fn = crate(function() { invoke(constructor$new, task_type = task_type, .args = as.list(match.call()[-1])) - }, constructor, task_type, .parent = topenv()) + }, constructor, task_type) fmls = formals(constructor$public_methods$initialize) fmls$task_type = NULL formals(fn) = fmls @@ -94,6 +94,7 @@ register_mlr3 = function() { } register_mlr3pipelines = function() { + mlr_reflections = utils::getFromNamespace("mlr_reflections", ns = "mlr3") mlr_pipeops = utils::getFromNamespace("mlr_pipeops", ns = "mlr3pipelines") add = mlr_pipeops$add # nolint iwalk(as.list(mlr3torch_pipeops), function(value, name) { diff --git a/TODO.md b/TODO.md index 567a0a1a..1dfff0c3 100644 --- a/TODO.md +++ b/TODO.md @@ -55,7 +55,7 @@ **Other** * [x] argument_matcher -* [ ] autotest_pipeop_torch +* [ ] expect_pipeop_torch * [ ] avg_output_shape * [ ] po_register_env * [ ] Tiny Imagenet @@ -140,7 +140,7 @@ Some notes: from paramset_torchlearner is actually doing something **Test Coverage** -* run paramtest vs autotest_paramset --> decide for one and delete the other +* run paramtest vs expect_paramset --> decide for one and delete the other * [ ] Proper testing for torch learners: * don't need the autotest as we don't really test the learners. * Instead we need to that: diff --git a/vignettes/lazy_tensor.Rmd b/attic/lazy_tensor.Rmd similarity index 100% rename from vignettes/lazy_tensor.Rmd rename to attic/lazy_tensor.Rmd diff --git a/man/ModelDescriptor.Rd b/man/ModelDescriptor.Rd index a6e9ee4a..38a350f9 100644 --- a/man/ModelDescriptor.Rd +++ b/man/ModelDescriptor.Rd @@ -77,11 +77,11 @@ Other Graph Network: \code{\link{TorchIngressToken}()}, \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch}}, \code{\link{model_descriptor_to_learner}()}, \code{\link{model_descriptor_to_module}()}, \code{\link{model_descriptor_union}()}, diff --git a/man/TorchCallback.Rd b/man/TorchCallback.Rd index dceda0ed..7c060eee 100644 --- a/man/TorchCallback.Rd +++ b/man/TorchCallback.Rd @@ -53,13 +53,13 @@ learner$param_set } \seealso{ Other Callback: -\code{\link{as_torch_callbacks}()}, \code{\link{as_torch_callback}()}, +\code{\link{as_torch_callbacks}()}, \code{\link{callback_set}()}, \code{\link{mlr3torch_callbacks}}, +\code{\link{mlr_callback_set}}, \code{\link{mlr_callback_set.checkpoint}}, \code{\link{mlr_callback_set.progress}}, -\code{\link{mlr_callback_set}}, \code{\link{mlr_context_torch}}, \code{\link{t_clbk}()}, \code{\link{torch_callback}()} diff --git a/man/TorchIngressToken.Rd b/man/TorchIngressToken.Rd index 5a341e65..0e56dff4 100644 --- a/man/TorchIngressToken.Rd +++ b/man/TorchIngressToken.Rd @@ -55,11 +55,11 @@ Other Graph Network: \code{\link{ModelDescriptor}()}, \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch}}, \code{\link{model_descriptor_to_learner}()}, \code{\link{model_descriptor_to_module}()}, \code{\link{model_descriptor_union}()}, diff --git a/man/as_torch_callback.Rd b/man/as_torch_callback.Rd index 0ca24ba4..db5feeb8 100644 --- a/man/as_torch_callback.Rd +++ b/man/as_torch_callback.Rd @@ -28,9 +28,9 @@ Other Callback: \code{\link{as_torch_callbacks}()}, \code{\link{callback_set}()}, \code{\link{mlr3torch_callbacks}}, +\code{\link{mlr_callback_set}}, \code{\link{mlr_callback_set.checkpoint}}, \code{\link{mlr_callback_set.progress}}, -\code{\link{mlr_callback_set}}, \code{\link{mlr_context_torch}}, \code{\link{t_clbk}()}, \code{\link{torch_callback}()} diff --git a/man/as_torch_callbacks.Rd b/man/as_torch_callbacks.Rd index ad4bacc5..563a4251 100644 --- a/man/as_torch_callbacks.Rd +++ b/man/as_torch_callbacks.Rd @@ -28,9 +28,9 @@ Other Callback: \code{\link{as_torch_callback}()}, \code{\link{callback_set}()}, \code{\link{mlr3torch_callbacks}}, +\code{\link{mlr_callback_set}}, \code{\link{mlr_callback_set.checkpoint}}, \code{\link{mlr_callback_set.progress}}, -\code{\link{mlr_callback_set}}, \code{\link{mlr_context_torch}}, \code{\link{t_clbk}()}, \code{\link{torch_callback}()} diff --git a/man/callback_set.Rd b/man/callback_set.Rd index e3e662a2..60bd5db7 100644 --- a/man/callback_set.Rd +++ b/man/callback_set.Rd @@ -64,12 +64,12 @@ provided. \seealso{ Other Callback: \code{\link{TorchCallback}}, -\code{\link{as_torch_callbacks}()}, \code{\link{as_torch_callback}()}, +\code{\link{as_torch_callbacks}()}, \code{\link{mlr3torch_callbacks}}, +\code{\link{mlr_callback_set}}, \code{\link{mlr_callback_set.checkpoint}}, \code{\link{mlr_callback_set.progress}}, -\code{\link{mlr_callback_set}}, \code{\link{mlr_context_torch}}, \code{\link{t_clbk}()}, \code{\link{torch_callback}()} diff --git a/man/materialize_internal.Rd b/man/materialize_internal.Rd index 2c5b36b8..65390e21 100644 --- a/man/materialize_internal.Rd +++ b/man/materialize_internal.Rd @@ -24,7 +24,7 @@ Whtether to rbind the resulting tensors (\code{TRUE}) or return them as a list o \code{\link[=lazy_tensor]{lazy_tensor()}} } \description{ -Convert a \code{\link[=lazy_tensor]{lazy_tensor()}} to a \code{\link[=torch_tensor]{torch_tensor()}}. +Convert a \code{\link{lazy_tensor}} to a \code{\link{torch_tensor}}. } \details{ Materializing a lazy tensor consists of: @@ -36,6 +36,7 @@ Materializing a lazy tensor consists of: When materializing multiple \code{\link{lazy_tensor}} columns, caching can be useful because: a) Output(s) from the dataset might be input to multiple graphs. +(in task_dataset this is shoudl rarely be the case because because we try to merge them). b) Different lazy tensors might be outputs from the same graph. For this reason it is possible to provide a cache environment. diff --git a/man/mlr3torch_callbacks.Rd b/man/mlr3torch_callbacks.Rd index 066c27f8..e12cd877 100644 --- a/man/mlr3torch_callbacks.Rd +++ b/man/mlr3torch_callbacks.Rd @@ -25,12 +25,12 @@ as.data.table(mlr3torch_callbacks) \seealso{ Other Callback: \code{\link{TorchCallback}}, -\code{\link{as_torch_callbacks}()}, \code{\link{as_torch_callback}()}, +\code{\link{as_torch_callbacks}()}, \code{\link{callback_set}()}, +\code{\link{mlr_callback_set}}, \code{\link{mlr_callback_set.checkpoint}}, \code{\link{mlr_callback_set.progress}}, -\code{\link{mlr_callback_set}}, \code{\link{mlr_context_torch}}, \code{\link{t_clbk}()}, \code{\link{torch_callback}()} diff --git a/man/mlr_callback_set.Rd b/man/mlr_callback_set.Rd index 3191efde..8333758f 100644 --- a/man/mlr_callback_set.Rd +++ b/man/mlr_callback_set.Rd @@ -46,8 +46,8 @@ These functions perform checks such as that the stages are not accidentally miss \seealso{ Other Callback: \code{\link{TorchCallback}}, -\code{\link{as_torch_callbacks}()}, \code{\link{as_torch_callback}()}, +\code{\link{as_torch_callbacks}()}, \code{\link{callback_set}()}, \code{\link{mlr3torch_callbacks}}, \code{\link{mlr_callback_set.checkpoint}}, diff --git a/man/mlr_callback_set.checkpoint.Rd b/man/mlr_callback_set.checkpoint.Rd index a3cd1944..a080d021 100644 --- a/man/mlr_callback_set.checkpoint.Rd +++ b/man/mlr_callback_set.checkpoint.Rd @@ -10,12 +10,12 @@ Saves the model during training. \seealso{ Other Callback: \code{\link{TorchCallback}}, -\code{\link{as_torch_callbacks}()}, \code{\link{as_torch_callback}()}, +\code{\link{as_torch_callbacks}()}, \code{\link{callback_set}()}, \code{\link{mlr3torch_callbacks}}, -\code{\link{mlr_callback_set.progress}}, \code{\link{mlr_callback_set}}, +\code{\link{mlr_callback_set.progress}}, \code{\link{mlr_context_torch}}, \code{\link{t_clbk}()}, \code{\link{torch_callback}()} diff --git a/man/mlr_callback_set.progress.Rd b/man/mlr_callback_set.progress.Rd index e86fc697..66763c0b 100644 --- a/man/mlr_callback_set.progress.Rd +++ b/man/mlr_callback_set.progress.Rd @@ -10,12 +10,12 @@ Prints a progress bar and the metrics for training and validation. \seealso{ Other Callback: \code{\link{TorchCallback}}, -\code{\link{as_torch_callbacks}()}, \code{\link{as_torch_callback}()}, +\code{\link{as_torch_callbacks}()}, \code{\link{callback_set}()}, \code{\link{mlr3torch_callbacks}}, -\code{\link{mlr_callback_set.checkpoint}}, \code{\link{mlr_callback_set}}, +\code{\link{mlr_callback_set.checkpoint}}, \code{\link{mlr_context_torch}}, \code{\link{t_clbk}()}, \code{\link{torch_callback}()} diff --git a/man/mlr_context_torch.Rd b/man/mlr_context_torch.Rd index 4e967921..01f43ee7 100644 --- a/man/mlr_context_torch.Rd +++ b/man/mlr_context_torch.Rd @@ -12,13 +12,13 @@ For more information on callbacks, see \code{\link{CallbackSet}}. \seealso{ Other Callback: \code{\link{TorchCallback}}, -\code{\link{as_torch_callbacks}()}, \code{\link{as_torch_callback}()}, +\code{\link{as_torch_callbacks}()}, \code{\link{callback_set}()}, \code{\link{mlr3torch_callbacks}}, +\code{\link{mlr_callback_set}}, \code{\link{mlr_callback_set.checkpoint}}, \code{\link{mlr_callback_set.progress}}, -\code{\link{mlr_callback_set}}, \code{\link{t_clbk}()}, \code{\link{torch_callback}()} } diff --git a/man/mlr_learners.alexnet.Rd b/man/mlr_learners.alexnet.Rd index c477ef17..55a85bc9 100644 --- a/man/mlr_learners.alexnet.Rd +++ b/man/mlr_learners.alexnet.Rd @@ -59,9 +59,9 @@ Krizhevsky, Alex, Sutskever, Ilya, Hinton, E. G (2017). Other Learner: \code{\link{mlr_learners.mlp}}, \code{\link{mlr_learners.torch_featureless}}, +\code{\link{mlr_learners_torch}}, \code{\link{mlr_learners_torch_image}}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_learners_torch}} +\code{\link{mlr_learners_torch_model}} } \concept{Learner} \section{Super classes}{ diff --git a/man/mlr_learners.mlp.Rd b/man/mlr_learners.mlp.Rd index fcdb2ef2..18fb5cd8 100644 --- a/man/mlr_learners.mlp.Rd +++ b/man/mlr_learners.mlp.Rd @@ -90,9 +90,9 @@ predictions$score() Other Learner: \code{\link{mlr_learners.alexnet}}, \code{\link{mlr_learners.torch_featureless}}, +\code{\link{mlr_learners_torch}}, \code{\link{mlr_learners_torch_image}}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_learners_torch}} +\code{\link{mlr_learners_torch_model}} } \concept{Learner} \section{Super classes}{ diff --git a/man/mlr_learners.torch_featureless.Rd b/man/mlr_learners.torch_featureless.Rd index e77f5a44..e893f780 100644 --- a/man/mlr_learners.torch_featureless.Rd +++ b/man/mlr_learners.torch_featureless.Rd @@ -76,9 +76,9 @@ predictions$score() Other Learner: \code{\link{mlr_learners.alexnet}}, \code{\link{mlr_learners.mlp}}, +\code{\link{mlr_learners_torch}}, \code{\link{mlr_learners_torch_image}}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_learners_torch}} +\code{\link{mlr_learners_torch_model}} } \concept{Learner} \section{Super classes}{ diff --git a/man/mlr_learners_torch_image.Rd b/man/mlr_learners_torch_image.Rd index 033e94a5..b956d708 100644 --- a/man/mlr_learners_torch_image.Rd +++ b/man/mlr_learners_torch_image.Rd @@ -37,8 +37,8 @@ Other Learner: \code{\link{mlr_learners.alexnet}}, \code{\link{mlr_learners.mlp}}, \code{\link{mlr_learners.torch_featureless}}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_learners_torch}} +\code{\link{mlr_learners_torch}}, +\code{\link{mlr_learners_torch_model}} } \concept{Learner} \section{Super classes}{ diff --git a/man/mlr_learners_torch_model.Rd b/man/mlr_learners_torch_model.Rd index 90c8922d..5482da90 100644 --- a/man/mlr_learners_torch_model.Rd +++ b/man/mlr_learners_torch_model.Rd @@ -45,18 +45,18 @@ Other Learner: \code{\link{mlr_learners.alexnet}}, \code{\link{mlr_learners.mlp}}, \code{\link{mlr_learners.torch_featureless}}, -\code{\link{mlr_learners_torch_image}}, -\code{\link{mlr_learners_torch}} +\code{\link{mlr_learners_torch}}, +\code{\link{mlr_learners_torch_image}} Other Graph Network: \code{\link{ModelDescriptor}()}, \code{\link{TorchIngressToken}()}, \code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch}}, \code{\link{model_descriptor_to_learner}()}, \code{\link{model_descriptor_to_module}()}, \code{\link{model_descriptor_union}()}, diff --git a/man/mlr_pipeops_module.Rd b/man/mlr_pipeops_module.Rd index 66a110ca..113d5dcd 100644 --- a/man/mlr_pipeops_module.Rd +++ b/man/mlr_pipeops_module.Rd @@ -98,11 +98,11 @@ Other Graph Network: \code{\link{ModelDescriptor}()}, \code{\link{TorchIngressToken}()}, \code{\link{mlr_learners_torch_model}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch}}, \code{\link{model_descriptor_to_learner}()}, \code{\link{model_descriptor_to_module}()}, \code{\link{model_descriptor_union}()}, diff --git a/man/mlr_pipeops_nn_avg_pool1d.Rd b/man/mlr_pipeops_nn_avg_pool1d.Rd index aa30f4fb..1c244e23 100644 --- a/man/mlr_pipeops_nn_avg_pool1d.Rd +++ b/man/mlr_pipeops_nn_avg_pool1d.Rd @@ -85,13 +85,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -101,17 +101,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_avg_pool2d.Rd b/man/mlr_pipeops_nn_avg_pool2d.Rd index 63dcedcf..3819c435 100644 --- a/man/mlr_pipeops_nn_avg_pool2d.Rd +++ b/man/mlr_pipeops_nn_avg_pool2d.Rd @@ -85,13 +85,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -101,17 +101,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_avg_pool3d.Rd b/man/mlr_pipeops_nn_avg_pool3d.Rd index d7c79589..e917a326 100644 --- a/man/mlr_pipeops_nn_avg_pool3d.Rd +++ b/man/mlr_pipeops_nn_avg_pool3d.Rd @@ -85,13 +85,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -101,17 +101,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_batch_norm1d.Rd b/man/mlr_pipeops_nn_batch_norm1d.Rd index 7c508d49..f4893c5b 100644 --- a/man/mlr_pipeops_nn_batch_norm1d.Rd +++ b/man/mlr_pipeops_nn_batch_norm1d.Rd @@ -83,13 +83,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -99,17 +99,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_batch_norm2d.Rd b/man/mlr_pipeops_nn_batch_norm2d.Rd index b311e42d..942aedc6 100644 --- a/man/mlr_pipeops_nn_batch_norm2d.Rd +++ b/man/mlr_pipeops_nn_batch_norm2d.Rd @@ -83,13 +83,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -99,17 +99,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_batch_norm3d.Rd b/man/mlr_pipeops_nn_batch_norm3d.Rd index 3cb0ca60..5f858053 100644 --- a/man/mlr_pipeops_nn_batch_norm3d.Rd +++ b/man/mlr_pipeops_nn_batch_norm3d.Rd @@ -83,13 +83,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -99,17 +99,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_celu.Rd b/man/mlr_pipeops_nn_celu.Rd index ebe7046b..5abb33b3 100644 --- a/man/mlr_pipeops_nn_celu.Rd +++ b/man/mlr_pipeops_nn_celu.Rd @@ -74,13 +74,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -90,17 +90,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_conv1d.Rd b/man/mlr_pipeops_nn_conv1d.Rd index 59dbf860..a45c85da 100644 --- a/man/mlr_pipeops_nn_conv1d.Rd +++ b/man/mlr_pipeops_nn_conv1d.Rd @@ -89,13 +89,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -105,17 +105,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_conv2d.Rd b/man/mlr_pipeops_nn_conv2d.Rd index a3fa342c..bdf59cc1 100644 --- a/man/mlr_pipeops_nn_conv2d.Rd +++ b/man/mlr_pipeops_nn_conv2d.Rd @@ -89,13 +89,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -105,17 +105,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_conv3d.Rd b/man/mlr_pipeops_nn_conv3d.Rd index 082dd671..3a48ff60 100644 --- a/man/mlr_pipeops_nn_conv3d.Rd +++ b/man/mlr_pipeops_nn_conv3d.Rd @@ -89,13 +89,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -105,17 +105,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_conv_transpose1d.Rd b/man/mlr_pipeops_nn_conv_transpose1d.Rd index edb55f4b..111450c6 100644 --- a/man/mlr_pipeops_nn_conv_transpose1d.Rd +++ b/man/mlr_pipeops_nn_conv_transpose1d.Rd @@ -92,13 +92,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -108,17 +108,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_conv_transpose2d.Rd b/man/mlr_pipeops_nn_conv_transpose2d.Rd index d8dacb30..78890b78 100644 --- a/man/mlr_pipeops_nn_conv_transpose2d.Rd +++ b/man/mlr_pipeops_nn_conv_transpose2d.Rd @@ -91,13 +91,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -107,17 +107,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_conv_transpose3d.Rd b/man/mlr_pipeops_nn_conv_transpose3d.Rd index 76fa706e..de6ee003 100644 --- a/man/mlr_pipeops_nn_conv_transpose3d.Rd +++ b/man/mlr_pipeops_nn_conv_transpose3d.Rd @@ -91,13 +91,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -107,17 +107,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_dropout.Rd b/man/mlr_pipeops_nn_dropout.Rd index 7c5f3d2f..0708f1ec 100644 --- a/man/mlr_pipeops_nn_dropout.Rd +++ b/man/mlr_pipeops_nn_dropout.Rd @@ -77,13 +77,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -93,17 +93,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_elu.Rd b/man/mlr_pipeops_nn_elu.Rd index ee8745e5..8ce7375a 100644 --- a/man/mlr_pipeops_nn_elu.Rd +++ b/man/mlr_pipeops_nn_elu.Rd @@ -75,13 +75,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -91,17 +91,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_flatten.Rd b/man/mlr_pipeops_nn_flatten.Rd index ea0cabc9..f848734a 100644 --- a/man/mlr_pipeops_nn_flatten.Rd +++ b/man/mlr_pipeops_nn_flatten.Rd @@ -73,13 +73,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -89,17 +89,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_gelu.Rd b/man/mlr_pipeops_nn_gelu.Rd index c3659258..8b9715d7 100644 --- a/man/mlr_pipeops_nn_gelu.Rd +++ b/man/mlr_pipeops_nn_gelu.Rd @@ -72,13 +72,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -88,17 +88,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_glu.Rd b/man/mlr_pipeops_nn_glu.Rd index 2a82f15b..8a2ff5c8 100644 --- a/man/mlr_pipeops_nn_glu.Rd +++ b/man/mlr_pipeops_nn_glu.Rd @@ -72,13 +72,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -88,17 +88,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_hardshrink.Rd b/man/mlr_pipeops_nn_hardshrink.Rd index bc36d117..c61f2e22 100644 --- a/man/mlr_pipeops_nn_hardshrink.Rd +++ b/man/mlr_pipeops_nn_hardshrink.Rd @@ -72,13 +72,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -88,17 +88,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_hardsigmoid.Rd b/man/mlr_pipeops_nn_hardsigmoid.Rd index bc491251..d0b4fedb 100644 --- a/man/mlr_pipeops_nn_hardsigmoid.Rd +++ b/man/mlr_pipeops_nn_hardsigmoid.Rd @@ -69,13 +69,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -85,17 +85,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_hardtanh.Rd b/man/mlr_pipeops_nn_hardtanh.Rd index 54dcebb5..2d16549a 100644 --- a/man/mlr_pipeops_nn_hardtanh.Rd +++ b/man/mlr_pipeops_nn_hardtanh.Rd @@ -70,13 +70,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -86,17 +86,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_head.Rd b/man/mlr_pipeops_nn_head.Rd index 7e2db85e..bfd9bd03 100644 --- a/man/mlr_pipeops_nn_head.Rd +++ b/man/mlr_pipeops_nn_head.Rd @@ -77,13 +77,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -93,17 +93,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_layer_norm.Rd b/man/mlr_pipeops_nn_layer_norm.Rd index 2bc95fab..ecc366b5 100644 --- a/man/mlr_pipeops_nn_layer_norm.Rd +++ b/man/mlr_pipeops_nn_layer_norm.Rd @@ -79,13 +79,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -95,17 +95,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_leaky_relu.Rd b/man/mlr_pipeops_nn_leaky_relu.Rd index 29de56e5..9b16959e 100644 --- a/man/mlr_pipeops_nn_leaky_relu.Rd +++ b/man/mlr_pipeops_nn_leaky_relu.Rd @@ -75,13 +75,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -91,17 +91,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_linear.Rd b/man/mlr_pipeops_nn_linear.Rd index 88b5ab1b..513c5c0e 100644 --- a/man/mlr_pipeops_nn_linear.Rd +++ b/man/mlr_pipeops_nn_linear.Rd @@ -77,13 +77,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -93,17 +93,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_log_sigmoid.Rd b/man/mlr_pipeops_nn_log_sigmoid.Rd index bd8d59db..d6c84891 100644 --- a/man/mlr_pipeops_nn_log_sigmoid.Rd +++ b/man/mlr_pipeops_nn_log_sigmoid.Rd @@ -69,13 +69,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -85,17 +85,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_max_pool1d.Rd b/man/mlr_pipeops_nn_max_pool1d.Rd index cb5bf6b7..e09c4737 100644 --- a/man/mlr_pipeops_nn_max_pool1d.Rd +++ b/man/mlr_pipeops_nn_max_pool1d.Rd @@ -83,13 +83,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_log_sigmoid}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -99,17 +99,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_max_pool2d.Rd b/man/mlr_pipeops_nn_max_pool2d.Rd index b3939784..4a4bbb79 100644 --- a/man/mlr_pipeops_nn_max_pool2d.Rd +++ b/man/mlr_pipeops_nn_max_pool2d.Rd @@ -83,13 +83,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_log_sigmoid}}, \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -99,17 +99,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_max_pool3d.Rd b/man/mlr_pipeops_nn_max_pool3d.Rd index d7aa6fce..277ad6d9 100644 --- a/man/mlr_pipeops_nn_max_pool3d.Rd +++ b/man/mlr_pipeops_nn_max_pool3d.Rd @@ -83,13 +83,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_log_sigmoid}}, \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -99,17 +99,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_merge.Rd b/man/mlr_pipeops_nn_merge.Rd index 06629f1a..ff6a184c 100644 --- a/man/mlr_pipeops_nn_merge.Rd +++ b/man/mlr_pipeops_nn_merge.Rd @@ -70,8 +70,8 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -81,17 +81,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_merge_cat.Rd b/man/mlr_pipeops_nn_merge_cat.Rd index 8f8edc87..6cfc99e8 100644 --- a/man/mlr_pipeops_nn_merge_cat.Rd +++ b/man/mlr_pipeops_nn_merge_cat.Rd @@ -80,12 +80,12 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -95,17 +95,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_merge_prod.Rd b/man/mlr_pipeops_nn_merge_prod.Rd index 9a8aa49b..b7fe76f4 100644 --- a/man/mlr_pipeops_nn_merge_prod.Rd +++ b/man/mlr_pipeops_nn_merge_prod.Rd @@ -76,12 +76,12 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -91,17 +91,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_merge_sum.Rd b/man/mlr_pipeops_nn_merge_sum.Rd index 41a4244f..73858dc7 100644 --- a/man/mlr_pipeops_nn_merge_sum.Rd +++ b/man/mlr_pipeops_nn_merge_sum.Rd @@ -76,12 +76,12 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -91,17 +91,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} Other PipeOps: \code{\link{mlr_pipeops_nn_avg_pool1d}}, @@ -133,12 +133,12 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -148,17 +148,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_prelu.Rd b/man/mlr_pipeops_nn_prelu.Rd index 0bc935cc..b065394b 100644 --- a/man/mlr_pipeops_nn_prelu.Rd +++ b/man/mlr_pipeops_nn_prelu.Rd @@ -78,12 +78,12 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -93,17 +93,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_relu.Rd b/man/mlr_pipeops_nn_relu.Rd index 96fd8627..a3dd171a 100644 --- a/man/mlr_pipeops_nn_relu.Rd +++ b/man/mlr_pipeops_nn_relu.Rd @@ -73,10 +73,10 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, \code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, @@ -88,17 +88,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_relu6.Rd b/man/mlr_pipeops_nn_relu6.Rd index ba4c765e..48230853 100644 --- a/man/mlr_pipeops_nn_relu6.Rd +++ b/man/mlr_pipeops_nn_relu6.Rd @@ -73,10 +73,10 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, \code{\link{mlr_pipeops_nn_relu}}, \code{\link{mlr_pipeops_nn_reshape}}, @@ -88,17 +88,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_reshape.Rd b/man/mlr_pipeops_nn_reshape.Rd index 7b69db1b..4a80e200 100644 --- a/man/mlr_pipeops_nn_reshape.Rd +++ b/man/mlr_pipeops_nn_reshape.Rd @@ -75,13 +75,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, \code{\link{mlr_pipeops_nn_sigmoid}}, @@ -90,17 +90,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_rrelu.Rd b/man/mlr_pipeops_nn_rrelu.Rd index e746fed9..70023721 100644 --- a/man/mlr_pipeops_nn_rrelu.Rd +++ b/man/mlr_pipeops_nn_rrelu.Rd @@ -77,13 +77,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_selu}}, \code{\link{mlr_pipeops_nn_sigmoid}}, @@ -92,17 +92,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_selu.Rd b/man/mlr_pipeops_nn_selu.Rd index 1f7365da..87afed1f 100644 --- a/man/mlr_pipeops_nn_selu.Rd +++ b/man/mlr_pipeops_nn_selu.Rd @@ -76,13 +76,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_sigmoid}}, @@ -91,17 +91,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_sigmoid.Rd b/man/mlr_pipeops_nn_sigmoid.Rd index 735eef01..628e393f 100644 --- a/man/mlr_pipeops_nn_sigmoid.Rd +++ b/man/mlr_pipeops_nn_sigmoid.Rd @@ -70,13 +70,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -85,17 +85,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_softmax.Rd b/man/mlr_pipeops_nn_softmax.Rd index 9e3ba8fd..d08d04ec 100644 --- a/man/mlr_pipeops_nn_softmax.Rd +++ b/man/mlr_pipeops_nn_softmax.Rd @@ -74,13 +74,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -89,17 +89,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_softplus.Rd b/man/mlr_pipeops_nn_softplus.Rd index a486be90..ba1a897b 100644 --- a/man/mlr_pipeops_nn_softplus.Rd +++ b/man/mlr_pipeops_nn_softplus.Rd @@ -75,13 +75,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -90,17 +90,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_softshrink.Rd b/man/mlr_pipeops_nn_softshrink.Rd index 8385d8be..bbf197a9 100644 --- a/man/mlr_pipeops_nn_softshrink.Rd +++ b/man/mlr_pipeops_nn_softshrink.Rd @@ -73,13 +73,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -88,17 +88,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softplus}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_softsign.Rd b/man/mlr_pipeops_nn_softsign.Rd index ee2a75e2..6b079e6b 100644 --- a/man/mlr_pipeops_nn_softsign.Rd +++ b/man/mlr_pipeops_nn_softsign.Rd @@ -70,13 +70,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -85,17 +85,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softplus}}, \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_squeeze.Rd b/man/mlr_pipeops_nn_squeeze.Rd index 27e9cf9d..32fc5d40 100644 --- a/man/mlr_pipeops_nn_squeeze.Rd +++ b/man/mlr_pipeops_nn_squeeze.Rd @@ -101,13 +101,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -116,17 +116,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softplus}}, \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} Other PipeOps: \code{\link{mlr_pipeops_nn_avg_pool1d}}, @@ -158,13 +158,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -173,17 +173,17 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softplus}}, \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_tanh.Rd b/man/mlr_pipeops_nn_tanh.Rd index 297cc8ac..d626dbee 100644 --- a/man/mlr_pipeops_nn_tanh.Rd +++ b/man/mlr_pipeops_nn_tanh.Rd @@ -70,13 +70,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -88,14 +88,14 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_squeeze}}, \code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_tanhshrink.Rd b/man/mlr_pipeops_nn_tanhshrink.Rd index 74e5766e..8dc2513a 100644 --- a/man/mlr_pipeops_nn_tanhshrink.Rd +++ b/man/mlr_pipeops_nn_tanhshrink.Rd @@ -70,13 +70,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -88,14 +88,14 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_squeeze}}, \code{\link{mlr_pipeops_nn_tanh}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_nn_threshold.Rd b/man/mlr_pipeops_nn_threshold.Rd index c2eb8741..161acae7 100644 --- a/man/mlr_pipeops_nn_threshold.Rd +++ b/man/mlr_pipeops_nn_threshold.Rd @@ -77,13 +77,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -93,16 +93,16 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_torch.Rd b/man/mlr_pipeops_torch.Rd index 9f104bdf..efb5d3a3 100644 --- a/man/mlr_pipeops_torch.Rd +++ b/man/mlr_pipeops_torch.Rd @@ -236,10 +236,10 @@ Other Graph Network: \code{\link{TorchIngressToken}()}, \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{model_descriptor_to_learner}()}, \code{\link{model_descriptor_to_module}()}, \code{\link{model_descriptor_union}()}, diff --git a/man/mlr_pipeops_torch_ingress.Rd b/man/mlr_pipeops_torch_ingress.Rd index b49151e4..583ec51f 100644 --- a/man/mlr_pipeops_torch_ingress.Rd +++ b/man/mlr_pipeops_torch_ingress.Rd @@ -63,13 +63,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -79,26 +79,26 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} Other Graph Network: \code{\link{ModelDescriptor}()}, \code{\link{TorchIngressToken}()}, \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch}}, \code{\link{model_descriptor_to_learner}()}, \code{\link{model_descriptor_to_module}()}, \code{\link{model_descriptor_union}()}, diff --git a/man/mlr_pipeops_torch_ingress_categ.Rd b/man/mlr_pipeops_torch_ingress_categ.Rd index 14d72a77..be3d2f98 100644 --- a/man/mlr_pipeops_torch_ingress_categ.Rd +++ b/man/mlr_pipeops_torch_ingress_categ.Rd @@ -72,13 +72,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -88,26 +88,26 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} Other Graph Network: \code{\link{ModelDescriptor}()}, \code{\link{TorchIngressToken}()}, \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch}}, \code{\link{model_descriptor_to_learner}()}, \code{\link{model_descriptor_to_module}()}, \code{\link{model_descriptor_union}()}, diff --git a/man/mlr_pipeops_torch_ingress_ltnsr.Rd b/man/mlr_pipeops_torch_ingress_ltnsr.Rd index a893cd20..514f1c20 100644 --- a/man/mlr_pipeops_torch_ingress_ltnsr.Rd +++ b/man/mlr_pipeops_torch_ingress_ltnsr.Rd @@ -107,13 +107,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -123,26 +123,26 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} Other Graph Network: \code{\link{ModelDescriptor}()}, \code{\link{TorchIngressToken}()}, \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch}}, \code{\link{model_descriptor_to_learner}()}, \code{\link{model_descriptor_to_module}()}, \code{\link{model_descriptor_union}()}, diff --git a/man/mlr_pipeops_torch_ingress_num.Rd b/man/mlr_pipeops_torch_ingress_num.Rd index 8a65e2d7..080d724e 100644 --- a/man/mlr_pipeops_torch_ingress_num.Rd +++ b/man/mlr_pipeops_torch_ingress_num.Rd @@ -38,10 +38,10 @@ Other Graph Network: \code{\link{TorchIngressToken}()}, \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch}}, \code{\link{model_descriptor_to_learner}()}, \code{\link{model_descriptor_to_module}()}, \code{\link{model_descriptor_union}()}, @@ -77,13 +77,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -93,16 +93,16 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{Graph Network} \concept{PipeOps} diff --git a/man/mlr_pipeops_torch_loss.Rd b/man/mlr_pipeops_torch_loss.Rd index 174f68e9..fd953769 100644 --- a/man/mlr_pipeops_torch_loss.Rd +++ b/man/mlr_pipeops_torch_loss.Rd @@ -67,13 +67,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -83,16 +83,16 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_model}}, \code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model_regr}} Other Model Configuration: \code{\link{ModelDescriptor}()}, diff --git a/man/mlr_pipeops_torch_model.Rd b/man/mlr_pipeops_torch_model.Rd index 62c0b767..818b558d 100644 --- a/man/mlr_pipeops_torch_model.Rd +++ b/man/mlr_pipeops_torch_model.Rd @@ -92,13 +92,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -108,13 +108,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, \code{\link{mlr_pipeops_torch_model_classif}}, \code{\link{mlr_pipeops_torch_model_regr}} diff --git a/man/mlr_pipeops_torch_model_classif.Rd b/man/mlr_pipeops_torch_model_classif.Rd index 79da502b..4d06225c 100644 --- a/man/mlr_pipeops_torch_model_classif.Rd +++ b/man/mlr_pipeops_torch_model_classif.Rd @@ -78,13 +78,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -94,16 +94,16 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model_regr}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_regr}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/mlr_pipeops_torch_model_regr.Rd b/man/mlr_pipeops_torch_model_regr.Rd index e19cd20c..bd440fd5 100644 --- a/man/mlr_pipeops_torch_model_regr.Rd +++ b/man/mlr_pipeops_torch_model_regr.Rd @@ -78,13 +78,13 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_max_pool1d}}, \code{\link{mlr_pipeops_nn_max_pool2d}}, \code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_merge_cat}}, \code{\link{mlr_pipeops_nn_merge_prod}}, \code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_merge}}, \code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, \code{\link{mlr_pipeops_nn_reshape}}, \code{\link{mlr_pipeops_nn_rrelu}}, \code{\link{mlr_pipeops_nn_selu}}, @@ -94,16 +94,16 @@ Other PipeOps: \code{\link{mlr_pipeops_nn_softshrink}}, \code{\link{mlr_pipeops_nn_softsign}}, \code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, \code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model}} +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}} } \concept{PipeOps} \section{Super classes}{ diff --git a/man/model_descriptor_to_learner.Rd b/man/model_descriptor_to_learner.Rd index 7a739641..ca28a14f 100644 --- a/man/model_descriptor_to_learner.Rd +++ b/man/model_descriptor_to_learner.Rd @@ -24,11 +24,11 @@ Other Graph Network: \code{\link{TorchIngressToken}()}, \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch}}, \code{\link{model_descriptor_to_module}()}, \code{\link{model_descriptor_union}()}, \code{\link{nn_graph}()} diff --git a/man/model_descriptor_to_module.Rd b/man/model_descriptor_to_module.Rd index 33ffefc9..7eb09a67 100644 --- a/man/model_descriptor_to_module.Rd +++ b/man/model_descriptor_to_module.Rd @@ -35,11 +35,11 @@ Other Graph Network: \code{\link{TorchIngressToken}()}, \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch}}, \code{\link{model_descriptor_to_learner}()}, \code{\link{model_descriptor_union}()}, \code{\link{nn_graph}()} diff --git a/man/model_descriptor_union.Rd b/man/model_descriptor_union.Rd index 63ffa75c..1eee931e 100644 --- a/man/model_descriptor_union.Rd +++ b/man/model_descriptor_union.Rd @@ -41,11 +41,11 @@ Other Graph Network: \code{\link{TorchIngressToken}()}, \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch}}, \code{\link{model_descriptor_to_learner}()}, \code{\link{model_descriptor_to_module}()}, \code{\link{nn_graph}()} diff --git a/man/nn_graph.Rd b/man/nn_graph.Rd index 3c077185..3bca9e6f 100644 --- a/man/nn_graph.Rd +++ b/man/nn_graph.Rd @@ -45,11 +45,11 @@ Other Graph Network: \code{\link{TorchIngressToken}()}, \code{\link{mlr_learners_torch_model}}, \code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, \code{\link{mlr_pipeops_torch_ingress_categ}}, \code{\link{mlr_pipeops_torch_ingress_ltnsr}}, \code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch}}, \code{\link{model_descriptor_to_learner}()}, \code{\link{model_descriptor_to_module}()}, \code{\link{model_descriptor_union}()} diff --git a/man/t_clbk.Rd b/man/t_clbk.Rd index 504853b9..8c2779ed 100644 --- a/man/t_clbk.Rd +++ b/man/t_clbk.Rd @@ -34,13 +34,13 @@ t_clbk("progress") \seealso{ Other Callback: \code{\link{TorchCallback}}, -\code{\link{as_torch_callbacks}()}, \code{\link{as_torch_callback}()}, +\code{\link{as_torch_callbacks}()}, \code{\link{callback_set}()}, \code{\link{mlr3torch_callbacks}}, +\code{\link{mlr_callback_set}}, \code{\link{mlr_callback_set.checkpoint}}, \code{\link{mlr_callback_set.progress}}, -\code{\link{mlr_callback_set}}, \code{\link{mlr_context_torch}}, \code{\link{torch_callback}()} diff --git a/man/torch_callback.Rd b/man/torch_callback.Rd index 2699389d..6e1ef091 100644 --- a/man/torch_callback.Rd +++ b/man/torch_callback.Rd @@ -128,13 +128,13 @@ learner$train(task) \seealso{ Other Callback: \code{\link{TorchCallback}}, -\code{\link{as_torch_callbacks}()}, \code{\link{as_torch_callback}()}, +\code{\link{as_torch_callbacks}()}, \code{\link{callback_set}()}, \code{\link{mlr3torch_callbacks}}, +\code{\link{mlr_callback_set}}, \code{\link{mlr_callback_set.checkpoint}}, \code{\link{mlr_callback_set.progress}}, -\code{\link{mlr_callback_set}}, \code{\link{mlr_context_torch}}, \code{\link{t_clbk}()} } diff --git a/tests/testthat/helper_autotest.R b/tests/testthat/helper_autotest.R index 360cef84..c4406f1c 100644 --- a/tests/testthat/helper_autotest.R +++ b/tests/testthat/helper_autotest.R @@ -22,7 +22,7 @@ #' #' @return `TRUE` if the autotest passes, errs otherwise. #' @export -autotest_pipeop_torch = function(graph, id, task, module_class = id, exclude_args = character(0)) { +expect_pipeop_torch = function(graph, id, task, module_class = id, exclude_args = character(0)) { require_namespaces(c("testthat")) po_test = graph$pipeops[[id]] result = graph$train(task) @@ -189,7 +189,7 @@ collapse_char_list = function(x) { #' For which parameters the defaults should not be checked. #' #' @export -autotest_paramset = function(x, fns, exclude = character(0), exclude_defaults = character(0)) { +expect_paramset = function(x, fns, exclude = character(0), exclude_defaults = character(0)) { if (test_r6(x, "ParamSet")) { param_set = x } else if (test_r6(x$param_set, "ParamSet")) { @@ -282,7 +282,7 @@ expect_paramtest = function(paramtest) { #' The object to test. #' @param check_man (`logical(1)`)\cr #' Whether to check that the manual page exists. Default is `TRUE`. -autotest_torch_callback = function(torch_callback, check_man = TRUE) { +expect_torch_callback = function(torch_callback, check_man = TRUE) { # Checks on descriptor expect_class(torch_callback, "TorchCallback") expect_string(torch_callback$id) @@ -301,7 +301,7 @@ autotest_torch_callback = function(torch_callback, check_man = TRUE) { expect_true(cbgen$cloneable) init_fn = get_init(torch_callback$generator) if (is.null(init_fn)) init_fn = function() NULL - paramtest = autotest_paramset(torch_callback$param_set, init_fn) + paramtest = expect_paramset(torch_callback$param_set, init_fn) expect_paramtest(paramtest) implemented_stages = names(cbgen$public_methods)[grepl("^on_", names(cbgen$public_methods))] expect_subset(implemented_stages, mlr_reflections$torch$callback_stages) @@ -326,7 +326,7 @@ autotest_torch_callback = function(torch_callback, check_man = TRUE) { #' @param obj ([`PipeOpTaskPreprocTorch`])\cr #' The object to test. #' @parm tnsr_in (`integer()`)\cr -autotest_pipeop_torch_preprocess = function(obj, shapes_in, exclude = character(0), exclude_defaults = character(0), +expect_pipeop_torch_preprocess = function(obj, shapes_in, exclude = character(0), exclude_defaults = character(0), in_package = TRUE) { expect_pipeop(obj) expect_class(obj, "PipeOpTaskPreprocTorch") @@ -337,7 +337,7 @@ autotest_pipeop_torch_preprocess = function(obj, shapes_in, exclude = character( stopf("Parameters of PipeOps inheriting from PipeOpTorch must only be active during training.") } }) - autotest_paramset(obj$param_set, obj$fn, exclude = exclude, exclude_defaults = exclude_defaults) + expect_paramset(obj$param_set, obj$fn, exclude = exclude, exclude_defaults = exclude_defaults) # b) Check that the shape prediction is compatible (already done in autotest for pipeop torch) # c) check that start with stages / trafo, depending on the initial value diff --git a/tests/testthat/helper_learner.R b/tests/testthat/helper_learner.R index 9a6790f1..7700c8d0 100644 --- a/tests/testthat/helper_learner.R +++ b/tests/testthat/helper_learner.R @@ -33,7 +33,7 @@ LearnerTorchTest1 = R6Class("LearnerTorchTest1", feature_ingress_tokens = list(num = ingress_token), target_batchgetter = crate(function(data, device) { torch_tensor(data = as.integer(data[[1]]), dtype = torch_long(), device = device) - }, .parent = topenv()), + }), device = param_vals$device ) dl = dataloader( diff --git a/tests/testthat/test_CallbackSetCheckpoint.R b/tests/testthat/test_CallbackSetCheckpoint.R index fd5b1175..86204811 100644 --- a/tests/testthat/test_CallbackSetCheckpoint.R +++ b/tests/testthat/test_CallbackSetCheckpoint.R @@ -1,6 +1,6 @@ test_that("Autotest", { cb = t_clbk("checkpoint", freq = 1, path = tempfile()) - autotest_torch_callback(cb) + expect_torch_callback(cb) }) test_that("CallbackSetCheckpoint manual", { diff --git a/tests/testthat/test_CallbackSetHistory.R b/tests/testthat/test_CallbackSetHistory.R index 5ae537f9..d51c377c 100644 --- a/tests/testthat/test_CallbackSetHistory.R +++ b/tests/testthat/test_CallbackSetHistory.R @@ -1,6 +1,6 @@ test_that("Autotest", { cb = t_clbk("history") - autotest_torch_callback(cb) + expect_torch_callback(cb) }) test_that("CallbackSetHistory works", { diff --git a/tests/testthat/test_CallbackSetProgress.R b/tests/testthat/test_CallbackSetProgress.R index 1ede9924..f6596fb7 100644 --- a/tests/testthat/test_CallbackSetProgress.R +++ b/tests/testthat/test_CallbackSetProgress.R @@ -1,6 +1,6 @@ test_that("autotest", { cb = t_clbk("progress") - autotest_torch_callback(cb) + expect_torch_callback(cb) }) test_that("manual test", { diff --git a/tests/testthat/test_PipeOpTorchActivation.R b/tests/testthat/test_PipeOpTorchActivation.R index 3c755e15..e9c7688e 100644 --- a/tests/testthat/test_PipeOpTorchActivation.R +++ b/tests/testthat/test_PipeOpTorchActivation.R @@ -5,11 +5,11 @@ test_that("PipeOpTorchLogSigmoid autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_log_sigmoid", task) + expect_pipeop_torch(graph, "nn_log_sigmoid", task) }) test_that("PipeOpTorchLogSigmoid paramtest", { - res = autotest_paramset(po("nn_log_sigmoid"), nn_log_sigmoid) + res = expect_paramset(po("nn_log_sigmoid"), nn_log_sigmoid) expect_paramtest(res) }) @@ -20,11 +20,11 @@ test_that("PipeOpTorchSigmoid autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_sigmoid", task) + expect_pipeop_torch(graph, "nn_sigmoid", task) }) test_that("PipeOpTorchSigmoid paramtest", { - res = autotest_paramset(po("nn_sigmoid"), nn_sigmoid) + res = expect_paramset(po("nn_sigmoid"), nn_sigmoid) expect_paramtest(res) }) @@ -35,11 +35,11 @@ test_that("PipeOpTorchGELU autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_gelu", task) + expect_pipeop_torch(graph, "nn_gelu", task) }) test_that("PipeOpTorchGELU paramtest", { - res = autotest_paramset(po("nn_gelu"), nn_gelu) + res = expect_paramset(po("nn_gelu"), nn_gelu) expect_paramtest(res) }) @@ -50,11 +50,11 @@ test_that("PipeOpTorchReLU autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_relu", task) + expect_pipeop_torch(graph, "nn_relu", task) }) test_that("PipeOpTorchReLU paramtest", { - res = autotest_paramset(po("nn_relu"), nn_relu) + res = expect_paramset(po("nn_relu"), nn_relu) expect_paramtest(res) }) @@ -66,11 +66,11 @@ test_that("PipeOpTorchTanhShrink autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_tanhshrink", task) + expect_pipeop_torch(graph, "nn_tanhshrink", task) }) test_that("PipeOpTorchTanhShrink paramtest", { - res = autotest_paramset(po("nn_tanhshrink"), nn_tanhshrink) + res = expect_paramset(po("nn_tanhshrink"), nn_tanhshrink) expect_paramtest(res) }) @@ -80,11 +80,11 @@ test_that("PipeOpTorchGLU autotest", { po_test = po("nn_glu") graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_glu", task) + expect_pipeop_torch(graph, "nn_glu", task) }) test_that("PipeOpTorchGLU paramtest", { - res = autotest_paramset(po("nn_glu"), nn_glu) + res = expect_paramset(po("nn_glu"), nn_glu) expect_paramtest(res) }) @@ -95,11 +95,11 @@ test_that("PipeOpTorchCelu autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_celu", task) + expect_pipeop_torch(graph, "nn_celu", task) }) test_that("PipeOpTorchCelu paramtest", { - res = autotest_paramset(po("nn_celu"), nn_celu) + res = expect_paramset(po("nn_celu"), nn_celu) expect_paramtest(res) }) @@ -110,11 +110,11 @@ test_that("PipeOpTorchThreshold autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_threshold", task) + expect_pipeop_torch(graph, "nn_threshold", task) }) test_that("PipeOpTorchThreshold paramtest", { - res = autotest_paramset(po("nn_threshold"), nn_threshold) + res = expect_paramset(po("nn_threshold"), nn_threshold) expect_paramtest(res) }) @@ -126,11 +126,11 @@ test_that("PipeOpTorchRReLU autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_rrelu", task) + expect_pipeop_torch(graph, "nn_rrelu", task) }) test_that("PipeOpTorchRReLU paramtest", { - res = autotest_paramset(po("nn_rrelu"), nn_rrelu) + res = expect_paramset(po("nn_rrelu"), nn_rrelu) expect_paramtest(res) }) @@ -142,12 +142,12 @@ test_that("PipeOpTorchHardSigmoid autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_hardsigmoid", task) + expect_pipeop_torch(graph, "nn_hardsigmoid", task) }) test_that("PipeOpTorchHardSigmoid paramtest", { - res = autotest_paramset(po("nn_hardsigmoid"), nn_hardsigmoid) + res = expect_paramset(po("nn_hardsigmoid"), nn_hardsigmoid) expect_paramtest(res) }) @@ -159,11 +159,11 @@ test_that("PipeOpTorchPReLU autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_prelu", task) + expect_pipeop_torch(graph, "nn_prelu", task) }) test_that("PipeOpTorchPReLU paramtest", { - res = autotest_paramset(po("nn_prelu"), nn_prelu) + res = expect_paramset(po("nn_prelu"), nn_prelu) expect_paramtest(res) }) @@ -175,11 +175,11 @@ test_that("PipeOpTorchTanh autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_tanh", task) + expect_pipeop_torch(graph, "nn_tanh", task) }) test_that("PipeOpTorchTanh paramtest", { - res = autotest_paramset(po("nn_tanh"), nn_tanh) + res = expect_paramset(po("nn_tanh"), nn_tanh) expect_paramtest(res) }) @@ -190,11 +190,11 @@ test_that("PipeOpTorchLeakyReLU autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_leaky_relu", task) + expect_pipeop_torch(graph, "nn_leaky_relu", task) }) test_that("PipeOpTorchLeakyReLU paramtest", { - res = autotest_paramset(po("nn_leaky_relu"), nn_leaky_relu) + res = expect_paramset(po("nn_leaky_relu"), nn_leaky_relu) expect_paramtest(res) }) @@ -205,11 +205,11 @@ test_that("PipeOpTorchRelu6 autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_relu6", task) + expect_pipeop_torch(graph, "nn_relu6", task) }) test_that("PipeOpTorchRelu6 paramtest", { - res = autotest_paramset(po("nn_relu6"), nn_relu6) + res = expect_paramset(po("nn_relu6"), nn_relu6) expect_paramtest(res) }) @@ -222,12 +222,12 @@ test_that("PipeOpTorchELU autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_elu", task) + expect_pipeop_torch(graph, "nn_elu", task) }) test_that("PipeOpTorchELU paramtest", { - res = autotest_paramset(po("nn_elu"), nn_elu) + res = expect_paramset(po("nn_elu"), nn_elu) expect_paramtest(res) }) @@ -238,12 +238,12 @@ test_that("PipeOpTorchtSoftShrink autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_softshrink", task) + expect_pipeop_torch(graph, "nn_softshrink", task) }) test_that("PipeOpTorchtSoftShrink paramtest", { - res = autotest_paramset(po("nn_softshrink"), nn_softshrink) + res = expect_paramset(po("nn_softshrink"), nn_softshrink) expect_paramtest(res) }) @@ -255,12 +255,12 @@ test_that("PipeOpTorchHardShrink autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_hardshrink", task) + expect_pipeop_torch(graph, "nn_hardshrink", task) }) test_that("PipeOpTorchHardShrink paramtest", { - res = autotest_paramset(po("nn_hardshrink"), nn_hardshrink) + res = expect_paramset(po("nn_hardshrink"), nn_hardshrink) expect_paramtest(res) }) @@ -272,12 +272,12 @@ test_that("PipeOpTorchSoftPlus autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_softplus", task) + expect_pipeop_torch(graph, "nn_softplus", task) }) test_that("PipeOpTorchSoftPlus paramtest", { - res = autotest_paramset(po("nn_softplus"), nn_softplus) + res = expect_paramset(po("nn_softplus"), nn_softplus) expect_paramtest(res) }) @@ -288,12 +288,12 @@ test_that("PipeOpTorchSELU autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_selu", task) + expect_pipeop_torch(graph, "nn_selu", task) }) test_that("PipeOpTorchSELU paramtest", { - res = autotest_paramset(po("nn_selu"), nn_selu) + res = expect_paramset(po("nn_selu"), nn_selu) expect_paramtest(res) }) @@ -305,12 +305,12 @@ test_that("PipeOpTorchSoftmax autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_softmax", task) + expect_pipeop_torch(graph, "nn_softmax", task) }) test_that("PipeOpTorchSoftmax paramtest", { - res = autotest_paramset(po("nn_softmax"), nn_softmax) + res = expect_paramset(po("nn_softmax"), nn_softmax) expect_paramtest(res) }) @@ -322,12 +322,12 @@ test_that("PipeOpTorchSoftSign autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_softsign", task) + expect_pipeop_torch(graph, "nn_softsign", task) }) test_that("PipeOpTorchSoftSign paramtest", { - res = autotest_paramset(po("nn_softsign"), nn_softsign) + res = expect_paramset(po("nn_softsign"), nn_softsign) expect_paramtest(res) }) @@ -338,11 +338,11 @@ test_that("PipeOpTorchHardTanh autotest", { graph = po("torch_ingress_num") %>>% po_test task = tsk("iris") - autotest_pipeop_torch(graph, "nn_hardtanh", task) + expect_pipeop_torch(graph, "nn_hardtanh", task) }) test_that("PipeOpTorchHardTanh paramtest", { - res = autotest_paramset(po("nn_hardtanh"), nn_hardtanh) + res = expect_paramset(po("nn_hardtanh"), nn_hardtanh) expect_paramtest(res) }) diff --git a/tests/testthat/test_PipeOpTorchAvgPool.R b/tests/testthat/test_PipeOpTorchAvgPool.R index aa0c0176..7aad8c94 100644 --- a/tests/testthat/test_PipeOpTorchAvgPool.R +++ b/tests/testthat/test_PipeOpTorchAvgPool.R @@ -4,11 +4,11 @@ test_that("PipeOpTorchAvgPool1D works", { graph = po("torch_ingress_num") %>>% po("nn_unsqueeze", dim = 2) %>>% po_test - autotest_pipeop_torch(graph, "nn_avg_pool1d", task) + expect_pipeop_torch(graph, "nn_avg_pool1d", task) }) test_that("PipeOpTorchAvgPool1D paramtest", { - res = autotest_paramset(po("nn_avg_pool1d"), nn_avg_pool1d, exclude = "num_features") + res = expect_paramset(po("nn_avg_pool1d"), nn_avg_pool1d, exclude = "num_features") expect_paramtest(res) }) @@ -17,11 +17,11 @@ test_that("PipeOpTorchAvgPool2D autotest", { task = nano_imagenet() graph = po("torch_ingress_ltnsr") %>>% po_test - autotest_pipeop_torch(graph, "nn_avg_pool2d", task) + expect_pipeop_torch(graph, "nn_avg_pool2d", task) }) test_that("PipeOpTorchAvgPool2D paramtest", { - res = autotest_paramset(po("nn_avg_pool2d"), nn_avg_pool2d, exclude = "num_features") + res = expect_paramset(po("nn_avg_pool2d"), nn_avg_pool2d, exclude = "num_features") expect_paramtest(res) }) @@ -32,11 +32,11 @@ test_that("PipeOpTorchAvgPool3D autotest", { po("nn_reshape", shape = c(NA, 3, 64, 8, 8)) %>>% po_test - autotest_pipeop_torch(graph, "nn_avg_pool3d", task) + expect_pipeop_torch(graph, "nn_avg_pool3d", task) }) test_that("PipeOpTorchAvgPool3D paramtest", { - res = autotest_paramset(po("nn_avg_pool3d"), nn_avg_pool3d, exclude = "num_features") + res = expect_paramset(po("nn_avg_pool3d"), nn_avg_pool3d, exclude = "num_features") expect_paramtest(res) }) diff --git a/tests/testthat/test_PipeOpTorchBatchNorm.R b/tests/testthat/test_PipeOpTorchBatchNorm.R index 2a057d2a..f2f5b534 100644 --- a/tests/testthat/test_PipeOpTorchBatchNorm.R +++ b/tests/testthat/test_PipeOpTorchBatchNorm.R @@ -4,12 +4,12 @@ test_that("PipeOpTorchBatchNorm1D autotest", { graph1 = po("torch_ingress_num") %>>% po_test graph2 = po("torch_ingress_num") %>>% po("nn_unsqueeze", dim = 2) %>>% po_test - autotest_pipeop_torch(graph1, "nn_batch_norm1d", task) - autotest_pipeop_torch(graph2, "nn_batch_norm1d", task) + expect_pipeop_torch(graph1, "nn_batch_norm1d", task) + expect_pipeop_torch(graph2, "nn_batch_norm1d", task) }) test_that("PipeOpTorchBatchNorm1D paramtest", { - res = autotest_paramset(po("nn_batch_norm1d"), nn_batch_norm1d, exclude = "num_features") + res = expect_paramset(po("nn_batch_norm1d"), nn_batch_norm1d, exclude = "num_features") expect_paramtest(res) }) @@ -18,11 +18,11 @@ test_that("PipeOpTorchBatchNorm2D autotest", { task = nano_imagenet() graph = po("torch_ingress_ltnsr") %>>% po_test - autotest_pipeop_torch(graph, "nn_batch_norm2d", task) + expect_pipeop_torch(graph, "nn_batch_norm2d", task) }) test_that("PipeOpTorchBatchNorm2D paramtest", { - res = autotest_paramset(po("nn_batch_norm2d"), nn_batch_norm2d, exclude = "num_features") + res = expect_paramset(po("nn_batch_norm2d"), nn_batch_norm2d, exclude = "num_features") expect_paramtest(res) }) @@ -33,10 +33,10 @@ test_that("PipeOpTorchBatchNorm3D autotest", { po("nn_reshape", shape = c(NA, 3, 64, 8, 8)) %>>% po_test - autotest_pipeop_torch(graph, "nn_batch_norm3d", task) + expect_pipeop_torch(graph, "nn_batch_norm3d", task) }) test_that("PipeOpTorchBatchNorm3D paramtest", { - res = autotest_paramset(po("nn_batch_norm3d"), nn_batch_norm3d, exclude = "num_features") + res = expect_paramset(po("nn_batch_norm3d"), nn_batch_norm3d, exclude = "num_features") expect_paramtest(res) }) diff --git a/tests/testthat/test_PipeOpTorchConv.R b/tests/testthat/test_PipeOpTorchConv.R index 2b11737c..2b06a4e0 100644 --- a/tests/testthat/test_PipeOpTorchConv.R +++ b/tests/testthat/test_PipeOpTorchConv.R @@ -3,11 +3,11 @@ test_that("PipeOpTorchConv1 autotest", { task = tsk("iris") graph = po("torch_ingress_num") %>>% po("nn_unsqueeze", dim = 2) %>>% po_conv - autotest_pipeop_torch(graph, "nn_conv1d", task) + expect_pipeop_torch(graph, "nn_conv1d", task) }) test_that("PipeOpTorchConv1d paramtest", { - res = autotest_paramset(po("nn_conv1d"), nn_conv1d, exclude = "in_channels") + res = expect_paramset(po("nn_conv1d"), nn_conv1d, exclude = "in_channels") expect_paramtest(res) }) @@ -16,11 +16,11 @@ test_that("PipeOpTorchConv2 autotest", { task = nano_imagenet() graph = po("torch_ingress_ltnsr") %>>% po_conv - autotest_pipeop_torch(graph, "nn_conv2d", task) + expect_pipeop_torch(graph, "nn_conv2d", task) }) test_that("PipeOpTorchConv2d paramtest", { - res = autotest_paramset(po("nn_conv2d"), nn_conv2d, exclude = "in_channels") + res = expect_paramset(po("nn_conv2d"), nn_conv2d, exclude = "in_channels") expect_paramtest(res) }) @@ -31,11 +31,11 @@ test_that("PipeOpTorchConv3 autotest", { po("nn_unsqueeze", dim = 5) %>>% po("nn_reshape", shape = c(-1, 3, 64, 8, 8)) %>>% po_conv - autotest_pipeop_torch(graph, "nn_conv3d", task) + expect_pipeop_torch(graph, "nn_conv3d", task) }) test_that("PipeOpTorchConv3d paramtest", { - res = autotest_paramset(po("nn_conv3d"), nn_conv3d, exclude = "in_channels") + res = expect_paramset(po("nn_conv3d"), nn_conv3d, exclude = "in_channels") expect_paramtest(res) }) diff --git a/tests/testthat/test_PipeOpTorchConvTranspose.R b/tests/testthat/test_PipeOpTorchConvTranspose.R index d880b3d4..fa930f26 100644 --- a/tests/testthat/test_PipeOpTorchConvTranspose.R +++ b/tests/testthat/test_PipeOpTorchConvTranspose.R @@ -13,11 +13,11 @@ test_that("PipeOpTorchConvTranspose1D autotest", { expect_pipeop(po_conv) - autotest_pipeop_torch(graph, "nn_conv_transpose1d", task) + expect_pipeop_torch(graph, "nn_conv_transpose1d", task) }) test_that("PipeOpTorchConvTranspose1D paramtest", { - res = autotest_paramset(po("nn_conv_transpose1d"), nn_conv_transpose1d, exclude = "in_channels") + res = expect_paramset(po("nn_conv_transpose1d"), nn_conv_transpose1d, exclude = "in_channels") expect_paramtest(res) }) @@ -26,11 +26,11 @@ test_that("PipeOpTorchConvTranspose2D autotest", { task = nano_imagenet() graph = po("torch_ingress_ltnsr") %>>% po_conv - autotest_pipeop_torch(graph, "nn_conv_transpose2d", task) + expect_pipeop_torch(graph, "nn_conv_transpose2d", task) }) test_that("PipeOpTorchConvTranspose2D paramtest", { - res = autotest_paramset(po("nn_conv_transpose2d"), nn_conv_transpose2d, exclude = "in_channels") + res = expect_paramset(po("nn_conv_transpose2d"), nn_conv_transpose2d, exclude = "in_channels") expect_paramtest(res) }) @@ -41,11 +41,11 @@ test_that("PipeOpTorchConvTranspose3D autotest", { po("nn_reshape", shape = c(-1, 3, 64, 8, 8)) %>>% po_conv - autotest_pipeop_torch(graph, "nn_conv_transpose3d", task) + expect_pipeop_torch(graph, "nn_conv_transpose3d", task) }) test_that("PipeOpTorchConvTranspose3D paramtest", { - res = autotest_paramset(po("nn_conv_transpose3d"), nn_conv_transpose3d, exclude = "in_channels") + res = expect_paramset(po("nn_conv_transpose3d"), nn_conv_transpose3d, exclude = "in_channels") expect_paramtest(res) }) diff --git a/tests/testthat/test_PipeOpTorchDropout.R b/tests/testthat/test_PipeOpTorchDropout.R index 3e0a8785..a58cee74 100644 --- a/tests/testthat/test_PipeOpTorchDropout.R +++ b/tests/testthat/test_PipeOpTorchDropout.R @@ -2,11 +2,11 @@ test_that("PipeOpTorchDropout autotest", { po_test = po("nn_dropout") graph = po("torch_ingress_num") %>>% po_test - autotest_pipeop_torch(graph, "nn_dropout", tsk("iris")) + expect_pipeop_torch(graph, "nn_dropout", tsk("iris")) }) test_that("PipeOpTorchDropout paramtest", { - res = autotest_paramset(po("nn_dropout"), nn_dropout) + res = expect_paramset(po("nn_dropout"), nn_dropout) expect_paramtest(res) }) diff --git a/tests/testthat/test_PipeOpTorchHead.R b/tests/testthat/test_PipeOpTorchHead.R index 09220c5b..fd197e33 100644 --- a/tests/testthat/test_PipeOpTorchHead.R +++ b/tests/testthat/test_PipeOpTorchHead.R @@ -3,12 +3,12 @@ test_that("PipeOpTorchHead autotest", { task = tsk("iris") graph = po("torch_ingress_num") %>>% po_test - autotest_pipeop_torch(graph, "nn_head", task, "nn_linear") + expect_pipeop_torch(graph, "nn_head", task, "nn_linear") }) test_that("PipeOpTorchHead paramtest", { po_test = po("nn_head") - res = autotest_paramset(po_test, torch::nn_linear, exclude = c("out_features", "in_features")) + res = expect_paramset(po_test, torch::nn_linear, exclude = c("out_features", "in_features")) expect_paramtest(res) }) diff --git a/tests/testthat/test_PipeOpTorchLayerNorm.R b/tests/testthat/test_PipeOpTorchLayerNorm.R index 06934b94..867d1cfa 100644 --- a/tests/testthat/test_PipeOpTorchLayerNorm.R +++ b/tests/testthat/test_PipeOpTorchLayerNorm.R @@ -2,10 +2,10 @@ test_that("PipeOpTorch autotest", { po_test = po("nn_layer_norm", dims = 1) task = tsk("iris") graph = po("torch_ingress_num") %>>% po_test - autotest_pipeop_torch(graph, "nn_layer_norm", task, "nn_layer_norm") + expect_pipeop_torch(graph, "nn_layer_norm", task, "nn_layer_norm") }) test_that("PipeOpTorch paramtest", { - res = autotest_paramset(po("nn_layer_norm", dims = 1), nn_layer_norm, exclude = c("normalized_shape", "dims")) + res = expect_paramset(po("nn_layer_norm", dims = 1), nn_layer_norm, exclude = c("normalized_shape", "dims")) expect_paramtest(res) }) diff --git a/tests/testthat/test_PipeOpTorchLinear.R b/tests/testthat/test_PipeOpTorchLinear.R index 7e653645..65a7a7a4 100644 --- a/tests/testthat/test_PipeOpTorchLinear.R +++ b/tests/testthat/test_PipeOpTorchLinear.R @@ -3,11 +3,11 @@ test_that("PipeOpTorchLinear works", { graph = po("torch_ingress_num") %>>% po_linear task = tsk("iris") - autotest_pipeop_torch(graph, "nn_linear", task, "nn_linear") + expect_pipeop_torch(graph, "nn_linear", task, "nn_linear") }) test_that("PipeOpTorchLinear paramtest", { po_linear = po("nn_linear", out_features = 10) - res = autotest_paramset(po_linear, nn_linear, exclude = "in_features") + res = expect_paramset(po_linear, nn_linear, exclude = "in_features") expect_paramtest(res) }) diff --git a/tests/testthat/test_PipeOpTorchMaxPool.R b/tests/testthat/test_PipeOpTorchMaxPool.R index cfece7a6..9bc525a9 100644 --- a/tests/testthat/test_PipeOpTorchMaxPool.R +++ b/tests/testthat/test_PipeOpTorchMaxPool.R @@ -4,12 +4,12 @@ test_that("PipeOpTorchMaxPool1D works", { graph = po("torch_ingress_num") %>>% po("nn_unsqueeze", dim = 2) %>>% po_test - autotest_pipeop_torch(graph, "nn_max_pool1d", task) + expect_pipeop_torch(graph, "nn_max_pool1d", task) }) test_that("PipeOpTorchMaxPool1D paramtest", { # return_indices is a construction argument. - res = autotest_paramset(po("nn_max_pool1d"), nn_max_pool1d, exclude = "return_indices") + res = expect_paramset(po("nn_max_pool1d"), nn_max_pool1d, exclude = "return_indices") expect_paramtest(res) }) @@ -18,12 +18,12 @@ test_that("PipeOpTorchMaxPool2D autotest", { task = nano_imagenet() graph = po("torch_ingress_ltnsr") %>>% po_test - autotest_pipeop_torch(graph, "nn_max_pool2d", task) + expect_pipeop_torch(graph, "nn_max_pool2d", task) }) test_that("PipeOpTorchMaxPool2D paramtest", { # return_indices is a construction argument. - res = autotest_paramset(po("nn_max_pool2d"), nn_max_pool2d, exclude = "return_indices") + res = expect_paramset(po("nn_max_pool2d"), nn_max_pool2d, exclude = "return_indices") expect_paramtest(res) }) @@ -34,12 +34,12 @@ test_that("PipeOpTorchMaxPool3D autotest", { po("nn_reshape", shape = c(NA, 3, 64, 8, 8)) %>>% po_test - autotest_pipeop_torch(graph, "nn_max_pool3d", task) + expect_pipeop_torch(graph, "nn_max_pool3d", task) }) test_that("PipeOpTorchMaxPool3D paramtest", { # return_indices is a construction argument. - res = autotest_paramset(po("nn_max_pool3d"), nn_max_pool3d, exclude = "return_indices") + res = expect_paramset(po("nn_max_pool3d"), nn_max_pool3d, exclude = "return_indices") expect_paramtest(res) }) diff --git a/tests/testthat/test_PipeOpTorchMerge.R b/tests/testthat/test_PipeOpTorchMerge.R index 6fec748a..58bdc594 100644 --- a/tests/testthat/test_PipeOpTorchMerge.R +++ b/tests/testthat/test_PipeOpTorchMerge.R @@ -5,7 +5,7 @@ test_that("PipeOpTorchMergeSum autotest", { list(po("nn_linear_1", out_features = 10), po("nn_linear_2", out_features = 10)) %>>% po_test - autotest_pipeop_torch(graph, "nn_merge_sum", task) + expect_pipeop_torch(graph, "nn_merge_sum", task) }) test_that("basic test", { @@ -19,7 +19,7 @@ test_that("basic test", { test_that("PipeOpTorchMergeSum paramtest", { po_test = po("nn_merge_sum") - res = autotest_paramset(po_test, nn_merge_sum) + res = expect_paramset(po_test, nn_merge_sum) expect_paramtest(res) }) @@ -30,12 +30,12 @@ test_that("PipeOpTorchMergeProd autotest", { list(po("nn_linear_1", out_features = 10), po("nn_linear_2", out_features = 10)) %>>% po_test - autotest_pipeop_torch(graph, "nn_merge_prod", task) + expect_pipeop_torch(graph, "nn_merge_prod", task) }) test_that("PipeOpTorchMergeProd paramtest", { po_test = po("nn_merge_prod") - res = autotest_paramset(po_test, nn_merge_prod) + res = expect_paramset(po_test, nn_merge_prod) expect_paramtest(res) }) @@ -47,14 +47,14 @@ test_that("PipeOpTorchMergeCat autotest", { list(po("nn_linear_1", out_features = 10), po("nn_linear_2", out_features = 10)) %>>% po_test - autotest_pipeop_torch(graph, "nn_merge_cat", task) + expect_pipeop_torch(graph, "nn_merge_cat", task) }) test_that("PipeOpTorchMergeCat paramtest", { po_test = po("nn_merge_cat") - res = autotest_paramset(po_test, nn_merge_cat) + res = expect_paramset(po_test, nn_merge_cat) expect_paramtest(res) }) diff --git a/tests/testthat/test_PipeOpTorchReshape.R b/tests/testthat/test_PipeOpTorchReshape.R index 82c9bc57..455d6d0d 100644 --- a/tests/testthat/test_PipeOpTorchReshape.R +++ b/tests/testthat/test_PipeOpTorchReshape.R @@ -3,14 +3,14 @@ test_that("PipeOpTorchReshape autotest", { task = tsk("iris") graph = po("torch_ingress_num") %>>% obj - autotest_pipeop_torch(graph, "nn_reshape", task) + expect_pipeop_torch(graph, "nn_reshape", task) out = po("nn_reshape", shape = c(NA, 2, 2))$shapes_out(list(input = c(1, 4))) expect_true(!is.character(all.equal(out[[1L]], c(NA, 2, 2)))) }) test_that("PipeOpTorchReshape paramtest", { - res = autotest_paramset(po("nn_reshape"), nn_reshape) + res = expect_paramset(po("nn_reshape"), nn_reshape) expect_paramtest(res) }) @@ -19,11 +19,11 @@ test_that("PipeOpTorchUnsqueeze autotest", { task = tsk("iris") graph = po("torch_ingress_num") %>>% obj - autotest_pipeop_torch(graph, "nn_unsqueeze", task) + expect_pipeop_torch(graph, "nn_unsqueeze", task) }) test_that("PipeOpTorchUnsqueeze paramtest", { - res = autotest_paramset(po("nn_unsqueeze"), nn_unsqueeze) + res = expect_paramset(po("nn_unsqueeze"), nn_unsqueeze) expect_paramtest(res) }) @@ -34,11 +34,11 @@ test_that("PipeOpTorchSqueeze autotest", { x = po("nn_squeeze") - autotest_pipeop_torch(graph, "nn_squeeze", task) + expect_pipeop_torch(graph, "nn_squeeze", task) }) test_that("PipeOpTorchSqueeze paramtest", { - res = autotest_paramset(po("nn_unsqueeze"), nn_unsqueeze) + res = expect_paramset(po("nn_unsqueeze"), nn_unsqueeze) expect_paramtest(res) }) @@ -47,10 +47,10 @@ test_that("PipeOpTorchFlatten autotest", { obj = po("nn_flatten", start_dim = 2, end_dim = 4) task = nano_imagenet() graph = po("torch_ingress_ltnsr") %>>% obj - autotest_pipeop_torch(graph, "nn_flatten", task) + expect_pipeop_torch(graph, "nn_flatten", task) }) test_that("PipeOpTorchFlatten", { - res = autotest_paramset(po("nn_flatten"), nn_flatten) + res = expect_paramset(po("nn_flatten"), nn_flatten) expect_paramtest(res) }) diff --git a/tests/testthat/test_TorchLoss.R b/tests/testthat/test_TorchLoss.R index 2937e866..a7efa7d2 100644 --- a/tests/testthat/test_TorchLoss.R +++ b/tests/testthat/test_TorchLoss.R @@ -115,7 +115,7 @@ test_that("Parameter test: mse", { loss_mse = t_loss("mse") param_set = loss_mse$param_set fn = loss_mse$generator - res = autotest_paramset(param_set, fn) + res = expect_paramset(param_set, fn) expect_paramtest(res) }) @@ -123,7 +123,7 @@ test_that("Parameter test: l1", { loss = t_loss("l1") param_set = loss$param_set fn = loss$generator - res = autotest_paramset(param_set, fn) + res = expect_paramset(param_set, fn) expect_paramtest(res) }) @@ -132,7 +132,7 @@ test_that("Parameter test: cross_entropy", { param_set = loss$param_set fn = loss$generator # ignore_index has param - res = autotest_paramset(param_set, fn) + res = expect_paramset(param_set, fn) expect_paramtest(res) }) diff --git a/tests/testthat/test_TorchOptimizer.R b/tests/testthat/test_TorchOptimizer.R index 90e21533..099e4cd0 100644 --- a/tests/testthat/test_TorchOptimizer.R +++ b/tests/testthat/test_TorchOptimizer.R @@ -117,7 +117,7 @@ test_that("Parameter test: adam", { torch_opt = t_opt("adam") param_set = torch_opt$param_set fn = torch_opt$generator - res = autotest_paramset(param_set, fn, exclude = "params") + res = expect_paramset(param_set, fn, exclude = "params") expect_paramtest(res) }) @@ -126,7 +126,7 @@ test_that("Parameter test: sgd", { param_set = torch_opt$param_set # lr is set to `optim_required()` fn = torch_opt$generator - res = autotest_paramset(param_set, fn, exclude = c("params", "lr")) + res = expect_paramset(param_set, fn, exclude = c("params", "lr")) expect_paramtest(res) }) @@ -134,7 +134,7 @@ test_that("Parameter test: asgd", { torch_opt = t_opt("asgd") param_set = torch_opt$param_set fn = torch_opt$generator - res = autotest_paramset(param_set, fn, exclude = "params") + res = expect_paramset(param_set, fn, exclude = "params") expect_paramtest(res) }) @@ -142,7 +142,7 @@ test_that("Parameter test: rprop", { torch_opt = t_opt("rprop") param_set = torch_opt$param_set fn = torch_opt$generator - res = autotest_paramset(param_set, fn, exclude = "params") + res = expect_paramset(param_set, fn, exclude = "params") expect_paramtest(res) }) @@ -150,7 +150,7 @@ test_that("Parameter test: rmsprop", { torch_opt = t_opt("rmsprop") param_set = torch_opt$param_set fn = torch_opt$generator - res = autotest_paramset(param_set, fn, exclude = "params") + res = expect_paramset(param_set, fn, exclude = "params") expect_paramtest(res) }) @@ -158,7 +158,7 @@ test_that("Parameter test: adagrad", { torch_opt = t_opt("adagrad") param_set = torch_opt$param_set fn = torch_opt$generator - res = autotest_paramset(param_set, fn, exclude = "params") + res = expect_paramset(param_set, fn, exclude = "params") expect_paramtest(res) }) @@ -166,7 +166,7 @@ test_that("Parameter test: adadelta", { torch_opt = t_opt("adadelta") param_set = torch_opt$param_set fn = torch_opt$generator - res = autotest_paramset(param_set, fn, exclude = "params") + res = expect_paramset(param_set, fn, exclude = "params") expect_paramtest(res) }) diff --git a/tests/testthat/test_autotests.R b/tests/testthat/test_autotests.R index 69cdd657..a17c8e8a 100644 --- a/tests/testthat/test_autotests.R +++ b/tests/testthat/test_autotests.R @@ -2,7 +2,7 @@ test_that("auto_paramtest works", { # captures missing parameters f1 = function(x, y) NULL ps1 = ps(x = p_uty()) - res1 = autotest_paramset(ps1, f1) + res1 = expect_paramset(ps1, f1) expect_equal(res1$info, list(merror = "Missing parameters: y")) expect_false(res1$ok) @@ -10,14 +10,14 @@ test_that("auto_paramtest works", { f2 = function() NULL ps2 = ps(x = p_uty()) - res2 = autotest_paramset(ps2, f2) + res2 = expect_paramset(ps2, f2) expect_equal(res2$info, list(eerror = "Extra parameters: x")) # defaults f3 = function(x = 1, y = 1, z) NULL ps3 = ps(x = p_int(default = 2), y = p_uty(), z = p_uty(default = 3)) - res3 = autotest_paramset(ps3, f3) + res3 = expect_paramset(ps3, f3) expect_equal(res3$info, list(derror = "Wrong defaults: x, y, z")) # Excluding stuff works @@ -26,7 +26,7 @@ test_that("auto_paramtest works", { f4 = function(x, y) NULL ps4 = ps(x = p_uty()) - res4 = autotest_paramset(ps4, f4, exclude = "y") + res4 = expect_paramset(ps4, f4, exclude = "y") expect_equal(res4$info, list()) expect_true(res4$ok) @@ -34,26 +34,26 @@ test_that("auto_paramtest works", { f5 = function(x) NULL ps5 = ps(x = p_uty(), y = p_uty()) - res5 = autotest_paramset(ps5, f5, exclude = "y") + res5 = expect_paramset(ps5, f5, exclude = "y") expect_equal(res5$info, list()) # Defaults of exlcuded parameters are not checked f6 = function(x) NULL ps6 = ps(x = p_uty(), y = p_uty(default = 10)) - res6 = autotest_paramset(ps6, f6, exclude = "y") + res6 = expect_paramset(ps6, f6, exclude = "y") expect_equal(res6$info, list()) # Exclude defaults works f7 = function(x = 10) NULL ps7 = ps(x = p_uty()) - res7 = autotest_paramset(ps7, f7, exclude_defaults = "x") + res7 = expect_paramset(ps7, f7, exclude_defaults = "x") expect_equal(res7$info, list()) f8 = function(x) NULL ps8 = ps(x = p_uty(default = 3)) - res8 = autotest_paramset(ps8, f8, exclude_defaults = "x") + res8 = expect_paramset(ps8, f8, exclude_defaults = "x") expect_equal(res8$info, list()) # Multiple functions work as well @@ -61,7 +61,7 @@ test_that("auto_paramtest works", { f9 = list(function(x) NULL, function(y) NULL) ps9 = ps(x = p_uty(default = 3), z = p_uty()) - res9 = autotest_paramset(ps9, f9) + res9 = expect_paramset(ps9, f9) expect_equal(res9$info, list(merror = "Missing parameters: y", eerror = "Extra parameters: z", derror = "Wrong defaults: x")) @@ -69,44 +69,44 @@ test_that("auto_paramtest works", { f10 = function(x = NULL) NULL ps10 = ps(x = p_uty(default = NULL)) - res10 = autotest_paramset(ps10, f10) + res10 = expect_paramset(ps10, f10) expect_equal(res10$info, list()) f11 = f10 ps11 = ps(x = p_uty()) - res11 = autotest_paramset(ps11, f11) + res11 = expect_paramset(ps11, f11) expect_equal(res11$info, list(derror = "Wrong defaults: x")) - # negative values work (evaluation problem, see comments in autotest_paramset) + # negative values work (evaluation problem, see comments in expect_paramset) f12 = function(x = -1, y = c("a", "b")) NULL ps12 = ps(x = p_int(default = -1), y = p_uty(default = c("a", "b"))) - res12 = autotest_paramset(ps12, f12) + res12 = expect_paramset(ps12, f12) expect_equal(res12$info, list()) f13 = f12 ps13 = ps(x = p_int(), y = p_uty()) - res13 = autotest_paramset(ps13, f13) + res13 = expect_paramset(ps13, f13) expect_equal(res13$info, list(derror = "Wrong defaults: x, y")) # works if expression cannot be evaluated f14 = function(x = z, z = 1) NULL ps14 = ps(x = p_uty(), z = p_int(default = 1)) - res14 = autotest_paramset(ps14, f14) + res14 = expect_paramset(ps14, f14) expect_equal(res14$info, list(derror = "Wrong defaults: x")) # Should not trigger default message if the parameter is missing or extra f15 = function(x = 1) NULL ps15 = ps() - res15 = autotest_paramset(ps15, f15) + res15 = expect_paramset(ps15, f15) expect_equal(res15$info, list(merror = "Missing parameters: x")) f16 = function() NULL ps16 = ps(x = p_int(default = 1)) - res16 = autotest_paramset(ps16, f16) + res16 = expect_paramset(ps16, f16) expect_equal(res16$info, list(eerror = "Extra parameters: x")) }) -test_that("autotest_torch_callback works", { +test_that("expect_torch_callback works", { # captures misspelled stages CallbackSetA = R6Class("CallbackSetA", inherit = CallbackSet, @@ -116,27 +116,27 @@ test_that("autotest_torch_callback works", { ) cba = as_torch_callback(CallbackSetA) expect_error( - autotest_torch_callback(cba, check_man = FALSE), + expect_torch_callback(cba, check_man = FALSE), regexp = "but has additional elements" ) tmp = class(cba) class(cba) = "blabla" - expect_error(autotest_torch_callback(cba, check_man = FALSE), "TorchCallback") + expect_error(expect_torch_callback(cba, check_man = FALSE), "TorchCallback") class(cba) = tmp tmp = cba$id cba$id = 1 - expect_error(autotest_torch_callback(cba, check_man = FALSE), "Must be of type") + expect_error(expect_torch_callback(cba, check_man = FALSE), "Must be of type") cba$id = tmp tmp = cba$label cba$label = 1.2 - expect_error(autotest_torch_callback(cba, check_man = FALSE), "Must be of type") + expect_error(expect_torch_callback(cba, check_man = FALSE), "Must be of type") cba$label = tmp tmp = cba$generator cba$generator = 1 - expect_error(autotest_torch_callback(cba, check_man = FALSE), "Must inherit from class") + expect_error(expect_torch_callback(cba, check_man = FALSE), "Must inherit from class") cba$generator = tmp CallbackSetB = R6Class("CallbackSetB", @@ -149,7 +149,7 @@ test_that("autotest_torch_callback works", { ) ) cbb = as_torch_callback(CallbackSetB) - expect_error(autotest_torch_callback(cbb, check_man = FALSE), regexp = "Wrong defaults") + expect_error(expect_torch_callback(cbb, check_man = FALSE), regexp = "Wrong defaults") CallbackSetC = R6Class("CallbackSetC", inherit = CallbackSet, @@ -171,6 +171,6 @@ test_that("autotest_torch_callback works", { ) ) cbd = as_torch_callback(CallbackSetD) - expect_error(autotest_torch_callback(cbd, check_man = FALSE), regexp = "not equal to") + expect_error(expect_torch_callback(cbd, check_man = FALSE), regexp = "not equal to") }) diff --git a/tests/testthat/test_lazy_tensor.R b/tests/testthat/test_lazy_tensor.R index 266c0421..4055c9b9 100644 --- a/tests/testthat/test_lazy_tensor.R +++ b/tests/testthat/test_lazy_tensor.R @@ -57,7 +57,7 @@ test_that("assignment", { expect_error({x[2] = 1}, "class") # nolint # indices must be ints expect_error({x["hallo"] = as_lazy_tensor(1)}, "integerish") # nolint - expect_error({x[1] = as_lazy_tensor(10)}, "data descriptor") + expect_error({x[1] = as_lazy_tensor(10)}, "data descriptor") # nolint y = lazy_tensor() diff --git a/tests/testthat/test_learner_torch_methods.R b/tests/testthat/test_learner_torch_methods.R index 48765a55..4ee82485 100644 --- a/tests/testthat/test_learner_torch_methods.R +++ b/tests/testthat/test_learner_torch_methods.R @@ -31,7 +31,7 @@ test_that("torch_network_predict works", { feature_ingress_tokens = ingress1, target_batchgetter = crate(function(data, device) { torch_tensor(data = as.integer(data[[1]]), dtype = torch_long(), device = device) - }, .parent = topenv()), + }), device = "cpu" ) @@ -54,7 +54,7 @@ test_that("torch_network_predict works", { feature_ingress_tokens = ingress2, target_batchgetter = crate(function(data, device) { torch_tensor(data = as.integer(data[[1]]), dtype = torch_long(), device = device) - }, .parent = topenv()), + }), device = "cpu" ) diff --git a/tests/testthat/test_preprocess.R b/tests/testthat/test_preprocess.R index 7280c371..0fcba75d 100644 --- a/tests/testthat/test_preprocess.R +++ b/tests/testthat/test_preprocess.R @@ -1,47 +1,47 @@ test_that("trafo_resize", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("trafo_resize", size = c(3, 4)), shapes_in = list(c(16, 10, 10, 4), c(3, 4, 8)) ) }) test_that("trafo_resize", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("trafo_resize", size = c(3, 4)), shapes_in = list(c(16, 10, 10, 4), c(3, 4, 8)) ) }) test_that("trafo_nop", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("trafo_nop"), shapes_in = list(c(1, 1)) ) }) test_that("trafo_adjust_gamma", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("trafo_adjust_gamma", gamma = 0.2, gain = 2), shapes_in = list(c(4, 3, 10, 10)) ) }) test_that("trafo_adjust_brightness", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("trafo_adjust_brightness", brightness_factor = 0.2), shapes_in = list(c(2, 3, 8, 8)) ) }) test_that("trafo_adjust_hue", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("trafo_adjust_hue", hue_factor = 0.3), shapes_in = list(c(5, 3, 8, 8)) ) }) test_that("trafo_adjust_saturation", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("trafo_adjust_saturation", saturation_factor = 2), shapes_in = list(c(2, 3, 8, 8)) ) @@ -49,28 +49,28 @@ test_that("trafo_adjust_saturation", { # not implemented #test_that("trafo_grayscale", { -# autotest_pipeop_torch_preprocess( +# expect_pipeop_torch_preprocess( # obj = po("trafo_grayscale", num_output_channels = 3), # shapes_in = list(c(2, 3, 8, 8)) # ) #}) test_that("trafo_rgb_to_grayscale", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("trafo_rgb_to_grayscale"), shapes_in = list(c(1, 3, 8, 8)) ) }) test_that("trafo_normalize", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("trafo_normalize", mean = -2, std = 3), shapes_in = list(c(1, 3, 8, 8)) ) }) test_that("trafo_pad", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("trafo_pad", padding = c(2, 3)), shapes_in = list(c(1, 3, 8, 8)) ) @@ -79,28 +79,28 @@ test_that("trafo_pad", { ## Augmentation test_that("augment_resized_crop", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("augment_resized_crop", top = 1, left = 2, height = 5, width = 6, size = c(10, 11)), shapes_in = list(c(1, 3, 64, 64)) ) }) test_that("augment_color_jitter", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("augment_color_jitter"), shapes_in = list(c(1, 3, 8, 8)) ) }) test_that("augment_random_resized_crop", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("augment_random_resized_crop", size = c(4, 5)), shapes_in = list(c(1, 3, 8, 8)) ) }) test_that("augment_random_order", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("augment_random_order", transforms = list( function(x) torchvision::transform_resize(x, c(4, 5)) )), @@ -109,28 +109,28 @@ test_that("augment_random_order", { }) test_that("augment_hflip", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("augment_hflip"), shapes_in = list(c(1, 3, 8, 8)) ) }) #test_that("augment_random_rotation", { -# autotest_pipeop_torch_preprocess( +# expect_pipeop_torch_preprocess( # obj = po("augment_random_rotation", degrees = 20), # shapes_in = list(c(1, 3, 8, 8)) # ) #}) test_that("augment_random_horizontal_flip", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("augment_random_horizontal_flip"), shapes_in = list(c(1, 3, 8, 8)) ) }) #test_that("augment_linear_transformation", { -# autotest_pipeop_torch_preprocess( +# expect_pipeop_torch_preprocess( # obj = po("augment_linear_transformation", # transformation_matrix = torch_randn(rep(3 * 8 * 7, 2)), mean_vector = torch_randn(3 * 8 * 7)), # shapes_in = list(c(1, 3, 8, 7)) @@ -138,14 +138,14 @@ test_that("augment_random_horizontal_flip", { #}) test_that("augment_crop", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("augment_crop", top = 2, left = 3, height = 10, width = 9), shapes_in = list(c(2, 3, 11, 9)) ) }) test_that("augment_random_vertical_flip", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("augment_random_vertical_flip"), shapes_in = list(c(3, 3, 8, 8)) ) @@ -153,21 +153,21 @@ test_that("augment_random_vertical_flip", { # not implemented for torch_tensor #test_that("augment_random_grayscale", { -# autotest_pipeop_torch_preprocess( +# expect_pipeop_torch_preprocess( # obj = po("augment_random_vertical_flip"), # shapes_in = list(c(1, 3, 8, 8)) # ) #}) #test_that("augment_random_perspective", { -# autotest_pipeop_torch_preprocess( +# expect_pipeop_torch_preprocess( # obj = po("augment_random_perspective"), # shapes_in = list(c(1, 3, 8, 8)) # ) #}) test_that("augment_random_affine", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("augment_random_affine", degrees = c(2, 70)), shapes_in = list(c(1, 3, 8, 8)) ) @@ -175,14 +175,14 @@ test_that("augment_random_affine", { test_that("augment_vflip", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("augment_vflip"), shapes_in = list(c(1, 3, 8, 8)) ) }) #test_that("augment_random_erasing", { -# autotest_pipeop_torch_preprocess( +# expect_pipeop_torch_preprocess( # obj = po("augment_random_erasing"), # shapes_in = list(c(1, 3, 8, 8)) # ) @@ -190,14 +190,14 @@ test_that("augment_vflip", { # not implemented #test_that("augment_perspective", { -# autotest_pipeop_torch_preprocess( +# expect_pipeop_torch_preprocess( # obj = po("augment_perspective", startpoints = 3, endpoints = 4), # shapes_in = list(c(1, 3, 8, 8)) # ) #}) test_that("augment_random_apply", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("augment_random_apply", transforms = list( function(x) torchvision::transform_resize(x, c(4, 5)) )), @@ -206,14 +206,14 @@ test_that("augment_random_apply", { }) test_that("augment_rotate", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("augment_rotate", angle = 3), shapes_in = list(c(1, 3, 8, 8)) ) }) test_that("augment_center_crop", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("augment_center_crop", size = c(6, 5)), shapes_in = list(c(6, 3, 10, 11)) ) @@ -221,7 +221,7 @@ test_that("augment_center_crop", { test_that("augment_random_choice", { # needs dev version of torchvision - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("augment_random_choice", transforms = list( identity, function(x) x + 1 )), @@ -230,7 +230,7 @@ test_that("augment_random_choice", { }) test_that("augment_random_crop", { - autotest_pipeop_torch_preprocess( + expect_pipeop_torch_preprocess( obj = po("augment_random_crop", size = c(4, 4)), shapes_in = list(c(1, 3, 8, 8)) ) diff --git a/tests/testthat/test_task_dataset.R b/tests/testthat/test_task_dataset.R index a6c210c0..244c2699 100644 --- a/tests/testthat/test_task_dataset.R +++ b/tests/testthat/test_task_dataset.R @@ -41,6 +41,10 @@ test_that("basic", { expect_equal(batch2$y$shape, 2) expect_equal(batch2$x$x_num$shape, c(2, ingress_num$shape[2])) expect_equal(batch2$x$x_categ$shape, c(2, ingress_categ$shape[2])) + + # input checks on ingress tokens + expect_error(task_dataset(task, list(), device = "cpu")) + expect_error(task_dataset(task, list(1), device = "cpu")) }) test_that("task_dataset throws error for empty ingress tokens", { @@ -261,7 +265,7 @@ test_that("default target batchgetter works: classification", { expect_equal(y_loaded1$device$type, "meta") }) -test_that("cachine of graph", { +test_that("caching of graph", { env = new.env() fn = crate(function(x) { env$counter = env$counter + 1L @@ -366,3 +370,49 @@ test_that("nop added for non-terminal pipeop", { expect_torch_equal(res$y + 1, res$x) }) + +test_that("unmergeable graphs are handled correctly", { + ds = dataset( + initialize = function() { + self$x1 = 1:10 + self$x2 = 2:11 + }, + .getitem = function(i) { + list(x1 = torch_tensor(self$x1[i]), x2 = torch_tensor(self$x2[1])) + }, + .length = function() 10 + )() + lt1 = as_lazy_tensor(ds, dataset_shapes = list(x1 = NULL, x2 = NULL), graph = po("nop", id = "nop1"), + input_map = "x1", pointer_shape = c(NA, 1)) + lt2 = as_lazy_tensor(ds, dataset_shapes = list(x1 = NULL, x2 = NULL), graph = po("nop", id = "nop1"), input_map = "x2", + pointer_shape = c(NA, 1)) + + task = as_task_regr(data.table(y = runif(10), x1 = lt1, x2 = lt2), target = "y", id = "t1") + + i1 = po("torch_ingress_ltnsr_1")$train(list(task$clone(deep = TRUE)$select("x1")))[[1]]$ingress + i2 = po("torch_ingress_ltnsr_2")$train(list(task$clone(deep = TRUE)$select("x2")))[[1]]$ingress + expect_true(grepl( + capture.output(invisible(task_dataset(task, c(i1, i2), device = "cpu"))), + pattern = "Cannot merge", fixed = TRUE + )) + prev_threshold = lg$threshold + on.exit({lg$set_threshold(prev_threshold)}, add = TRUE) # nolint + lg$set_threshold("error") + task_ds = task_dataset(task, c(i1, i2), device = "cpu") + + batch = task_ds$.getbatch(1) + expect_torch_equal(batch$x[[1]], batch$x[[2]] - 1) +}) + +test_that("merge_lazy_tensors only returns modified columns", { + # don't waste memory by cbinding unmerged graph + task = as_task_regr(data.table( + y = 1:10, + x1 = as_lazy_tensor(1:10), + x2 = as_lazy_tensor(2:11) + ), target = "y", id = "test") + + data = task$data(cols = task$feature_names) + merged = merge_lazy_tensor_graphs(data) + expect_true(is.null(merged)) +}) From e8287227e532b1034041421f488c4fe98dae1fe6 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 7 Feb 2024 17:22:24 +0100 Subject: [PATCH 83/90] pkgdown --- pkgdown/_pkgdown.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index 9de89df1..99c0a9b4 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -44,7 +44,3 @@ articles: navbar: ~ contents: - get_started -- title: Lazy Tensor - navbar: ~ - contents: - - lazy_tensor From 7c9aa2c115857635f9073517e6f1b9fde85ee24b Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 7 Feb 2024 17:45:54 +0100 Subject: [PATCH 84/90] docs: escape examples if torch not installed --- R/DataDescriptor.R | 1 + R/LearnerTorchModel.R | 1 + R/PipeOpModule.R | 1 + R/PipeOpTaskPreprocTorch.R | 1 + R/PipeOpTorch.R | 1 + R/PipeOpTorchCallbacks.R | 1 + R/PipeOpTorchIngress.R | 4 + R/PipeOpTorchLoss.R | 1 + R/PipeOpTorchModel.R | 2 + R/PipeOpTorchOptimizer.R | 1 + R/TaskClassif_lazy_iris.R | 1 + R/TorchCallback.R | 2 + R/TorchLoss.R | 1 + R/TorchOptimizer.R | 2 + R/lazy_tensor.R | 1 + R/materialize.R | 1 + R/nn_graph.R | 1 + R/reset_last_layer.R | 3 +- R/task_dataset.R | 1 + man-roxygen/learner_example.R | 1 + man-roxygen/pipeop_torch_example.R | 2 + man/DataDescriptor.Rd | 166 -------- man/ModelDescriptor.Rd | 91 ----- man/PipeOpPreprocTorchAugmentCenterCrop.Rd | 23 -- man/PipeOpPreprocTorchAugmentColorJitter.Rd | 26 -- man/PipeOpPreprocTorchAugmentCrop.Rd | 26 -- man/PipeOpPreprocTorchAugmentHflip.Rd | 22 -- man/PipeOpPreprocTorchAugmentRandomAffine.Rd | 27 -- man/PipeOpPreprocTorchAugmentRandomApply.Rd | 24 -- man/PipeOpPreprocTorchAugmentRandomChoice.Rd | 23 -- man/PipeOpPreprocTorchAugmentRandomCrop.Rd | 27 -- ...PreprocTorchAugmentRandomHorizontalFlip.Rd | 23 -- man/PipeOpPreprocTorchAugmentRandomOrder.Rd | 23 -- ...eOpPreprocTorchAugmentRandomResizedCrop.Rd | 26 -- ...OpPreprocTorchAugmentRandomVerticalFlip.Rd | 23 -- man/PipeOpPreprocTorchAugmentResizedCrop.Rd | 28 -- man/PipeOpPreprocTorchAugmentRotate.Rd | 27 -- man/PipeOpPreprocTorchAugmentVflip.Rd | 22 -- ...PipeOpPreprocTorchTrafoAdjustBrightness.Rd | 23 -- man/PipeOpPreprocTorchTrafoAdjustGamma.Rd | 24 -- man/PipeOpPreprocTorchTrafoAdjustHue.Rd | 23 -- ...PipeOpPreprocTorchTrafoAdjustSaturation.Rd | 23 -- man/PipeOpPreprocTorchTrafoGrayscale.Rd | 23 -- man/PipeOpPreprocTorchTrafoNop.Rd | 12 - man/PipeOpPreprocTorchTrafoNormalize.Rd | 24 -- man/PipeOpPreprocTorchTrafoPad.Rd | 25 -- man/PipeOpPreprocTorchTrafoResize.Rd | 24 -- man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd | 22 -- man/PipeOpPreprocTorchTrafoScale.Rd | 12 - man/TorchCallback.Rd | 159 -------- man/TorchDescriptor.Rd | 172 --------- man/TorchIngressToken.Rd | 68 ---- man/TorchLoss.Rd | 174 --------- man/TorchOptimizer.Rd | 165 -------- man/as_lazy_tensor.Rd | 18 - man/as_torch_callback.Rd | 38 -- man/as_torch_callbacks.Rd | 52 --- man/as_torch_loss.Rd | 40 -- man/as_torch_optimizer.Rd | 41 -- man/assert_lazy_tensor.Rd | 15 - man/auto_device.Rd | 15 - man/batchgetter_categ.Rd | 22 -- man/batchgetter_num.Rd | 22 -- man/callback_set.Rd | 77 ---- man/equals-.lazy_tensor.Rd | 20 - man/figures/lifecycle-archived.svg | 1 - man/figures/lifecycle-defunct.svg | 1 - man/figures/lifecycle-deprecated.svg | 1 - man/figures/lifecycle-experimental.svg | 1 - man/figures/lifecycle-maturing.svg | 1 - man/figures/lifecycle-questioning.svg | 1 - man/figures/lifecycle-stable.svg | 1 - man/figures/lifecycle-superseded.svg | 1 - man/figures/logo.png | Bin 316274 -> 0 bytes man/figures/logo.svg | 121 ------ man/hash_input.lazy_tensor.Rd | 15 - man/is_lazy_tensor.Rd | 15 - man/lazy_tensor.Rd | 18 - man/materialize.Rd | 67 ---- man/materialize_internal.Rd | 46 --- man/mlr3torch-package.Rd | 37 -- man/mlr3torch_callbacks.Rd | 45 --- man/mlr3torch_losses.Rd | 51 --- man/mlr3torch_optimizers.Rd | 51 --- man/mlr_backends_lazy.Rd | 271 ------------- man/mlr_context_torch.Rd | 167 -------- man/mlr_pipeops_module.Rd | 185 --------- man/mlr_pipeops_nn_avg_pool1d.Rd | 177 --------- man/mlr_pipeops_nn_avg_pool2d.Rd | 177 --------- man/mlr_pipeops_nn_avg_pool3d.Rd | 177 --------- man/mlr_pipeops_nn_batch_norm1d.Rd | 175 --------- man/mlr_pipeops_nn_batch_norm2d.Rd | 175 --------- man/mlr_pipeops_nn_batch_norm3d.Rd | 175 --------- man/mlr_pipeops_nn_celu.Rd | 166 -------- man/mlr_pipeops_nn_conv1d.Rd | 181 --------- man/mlr_pipeops_nn_conv2d.Rd | 181 --------- man/mlr_pipeops_nn_conv3d.Rd | 181 --------- man/mlr_pipeops_nn_conv_transpose1d.Rd | 184 --------- man/mlr_pipeops_nn_conv_transpose2d.Rd | 183 --------- man/mlr_pipeops_nn_conv_transpose3d.Rd | 183 --------- man/mlr_pipeops_nn_dropout.Rd | 169 -------- man/mlr_pipeops_nn_elu.Rd | 167 -------- man/mlr_pipeops_nn_flatten.Rd | 165 -------- man/mlr_pipeops_nn_gelu.Rd | 164 -------- man/mlr_pipeops_nn_glu.Rd | 164 -------- man/mlr_pipeops_nn_hardshrink.Rd | 164 -------- man/mlr_pipeops_nn_hardsigmoid.Rd | 161 -------- man/mlr_pipeops_nn_hardtanh.Rd | 162 -------- man/mlr_pipeops_nn_head.Rd | 169 -------- man/mlr_pipeops_nn_layer_norm.Rd | 171 --------- man/mlr_pipeops_nn_leaky_relu.Rd | 167 -------- man/mlr_pipeops_nn_linear.Rd | 169 -------- man/mlr_pipeops_nn_log_sigmoid.Rd | 161 -------- man/mlr_pipeops_nn_max_pool1d.Rd | 183 --------- man/mlr_pipeops_nn_max_pool2d.Rd | 183 --------- man/mlr_pipeops_nn_max_pool3d.Rd | 183 --------- man/mlr_pipeops_nn_merge.Rd | 172 --------- man/mlr_pipeops_nn_merge_cat.Rd | 185 --------- man/mlr_pipeops_nn_merge_prod.Rd | 170 -------- man/mlr_pipeops_nn_merge_sum.Rd | 227 ----------- man/mlr_pipeops_nn_prelu.Rd | 169 -------- man/mlr_pipeops_nn_relu.Rd | 164 -------- man/mlr_pipeops_nn_relu6.Rd | 164 -------- man/mlr_pipeops_nn_reshape.Rd | 166 -------- man/mlr_pipeops_nn_rrelu.Rd | 168 -------- man/mlr_pipeops_nn_selu.Rd | 167 -------- man/mlr_pipeops_nn_sigmoid.Rd | 161 -------- man/mlr_pipeops_nn_softmax.Rd | 165 -------- man/mlr_pipeops_nn_softplus.Rd | 166 -------- man/mlr_pipeops_nn_softshrink.Rd | 164 -------- man/mlr_pipeops_nn_softsign.Rd | 161 -------- man/mlr_pipeops_nn_squeeze.Rd | 310 --------------- man/mlr_pipeops_nn_tanh.Rd | 161 -------- man/mlr_pipeops_nn_tanhshrink.Rd | 161 -------- man/mlr_pipeops_nn_threshold.Rd | 168 -------- man/mlr_pipeops_preproc_torch.Rd | 302 --------------- man/mlr_pipeops_torch.Rd | 363 ------------------ man/mlr_pipeops_torch_callbacks.Rd | 126 ------ man/mlr_pipeops_torch_ingress.Rd | 192 --------- man/mlr_pipeops_torch_ingress_categ.Rd | 180 --------- man/mlr_pipeops_torch_ingress_ltnsr.Rd | 215 ----------- man/mlr_pipeops_torch_ingress_num.Rd | 168 -------- man/mlr_pipeops_torch_loss.Rd | 167 -------- man/mlr_pipeops_torch_model.Rd | 185 --------- man/mlr_pipeops_torch_model_classif.Rd | 168 -------- man/mlr_pipeops_torch_model_regr.Rd | 168 -------- man/mlr_pipeops_torch_optimizer.Rd | 121 ------ man/mlr_resamplings_row_roles.Rd | 145 ------- man/mlr_tasks_lazy_iris.Rd | 46 --- man/mlr_tasks_mnist.Rd | 54 --- man/mlr_tasks_tiny_imagenet.Rd | 46 --- man/model_descriptor_to_learner.Rd | 36 -- man/model_descriptor_to_module.Rd | 47 --- man/model_descriptor_union.Rd | 60 --- man/nn_graph.Rd | 57 --- man/nn_merge_cat.Rd | 16 - man/nn_merge_prod.Rd | 11 - man/nn_merge_sum.Rd | 11 - man/nn_reshape.Rd | 15 - man/nn_squeeze.Rd | 15 - man/nn_unsqueeze.Rd | 15 - man/pipeop_preproc_torch.Rd | 72 ---- man/reset_layer.Rd | 52 --- man/t_clbk.Rd | 61 --- man/t_loss.Rd | 51 --- man/t_opt.Rd | 57 --- man/task_dataset.Rd | 57 --- man/torch_callback.Rd | 141 ------- 168 files changed, 29 insertions(+), 14864 deletions(-) delete mode 100644 man/DataDescriptor.Rd delete mode 100644 man/ModelDescriptor.Rd delete mode 100644 man/PipeOpPreprocTorchAugmentCenterCrop.Rd delete mode 100644 man/PipeOpPreprocTorchAugmentColorJitter.Rd delete mode 100644 man/PipeOpPreprocTorchAugmentCrop.Rd delete mode 100644 man/PipeOpPreprocTorchAugmentHflip.Rd delete mode 100644 man/PipeOpPreprocTorchAugmentRandomAffine.Rd delete mode 100644 man/PipeOpPreprocTorchAugmentRandomApply.Rd delete mode 100644 man/PipeOpPreprocTorchAugmentRandomChoice.Rd delete mode 100644 man/PipeOpPreprocTorchAugmentRandomCrop.Rd delete mode 100644 man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd delete mode 100644 man/PipeOpPreprocTorchAugmentRandomOrder.Rd delete mode 100644 man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd delete mode 100644 man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd delete mode 100644 man/PipeOpPreprocTorchAugmentResizedCrop.Rd delete mode 100644 man/PipeOpPreprocTorchAugmentRotate.Rd delete mode 100644 man/PipeOpPreprocTorchAugmentVflip.Rd delete mode 100644 man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd delete mode 100644 man/PipeOpPreprocTorchTrafoAdjustGamma.Rd delete mode 100644 man/PipeOpPreprocTorchTrafoAdjustHue.Rd delete mode 100644 man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd delete mode 100644 man/PipeOpPreprocTorchTrafoGrayscale.Rd delete mode 100644 man/PipeOpPreprocTorchTrafoNop.Rd delete mode 100644 man/PipeOpPreprocTorchTrafoNormalize.Rd delete mode 100644 man/PipeOpPreprocTorchTrafoPad.Rd delete mode 100644 man/PipeOpPreprocTorchTrafoResize.Rd delete mode 100644 man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd delete mode 100644 man/PipeOpPreprocTorchTrafoScale.Rd delete mode 100644 man/TorchCallback.Rd delete mode 100644 man/TorchDescriptor.Rd delete mode 100644 man/TorchIngressToken.Rd delete mode 100644 man/TorchLoss.Rd delete mode 100644 man/TorchOptimizer.Rd delete mode 100644 man/as_lazy_tensor.Rd delete mode 100644 man/as_torch_callback.Rd delete mode 100644 man/as_torch_callbacks.Rd delete mode 100644 man/as_torch_loss.Rd delete mode 100644 man/as_torch_optimizer.Rd delete mode 100644 man/assert_lazy_tensor.Rd delete mode 100644 man/auto_device.Rd delete mode 100644 man/batchgetter_categ.Rd delete mode 100644 man/batchgetter_num.Rd delete mode 100644 man/callback_set.Rd delete mode 100644 man/equals-.lazy_tensor.Rd delete mode 100644 man/figures/lifecycle-archived.svg delete mode 100644 man/figures/lifecycle-defunct.svg delete mode 100644 man/figures/lifecycle-deprecated.svg delete mode 100644 man/figures/lifecycle-experimental.svg delete mode 100644 man/figures/lifecycle-maturing.svg delete mode 100644 man/figures/lifecycle-questioning.svg delete mode 100644 man/figures/lifecycle-stable.svg delete mode 100644 man/figures/lifecycle-superseded.svg delete mode 100644 man/figures/logo.png delete mode 100644 man/figures/logo.svg delete mode 100644 man/hash_input.lazy_tensor.Rd delete mode 100644 man/is_lazy_tensor.Rd delete mode 100644 man/lazy_tensor.Rd delete mode 100644 man/materialize.Rd delete mode 100644 man/materialize_internal.Rd delete mode 100644 man/mlr3torch-package.Rd delete mode 100644 man/mlr3torch_callbacks.Rd delete mode 100644 man/mlr3torch_losses.Rd delete mode 100644 man/mlr3torch_optimizers.Rd delete mode 100644 man/mlr_backends_lazy.Rd delete mode 100644 man/mlr_context_torch.Rd delete mode 100644 man/mlr_pipeops_module.Rd delete mode 100644 man/mlr_pipeops_nn_avg_pool1d.Rd delete mode 100644 man/mlr_pipeops_nn_avg_pool2d.Rd delete mode 100644 man/mlr_pipeops_nn_avg_pool3d.Rd delete mode 100644 man/mlr_pipeops_nn_batch_norm1d.Rd delete mode 100644 man/mlr_pipeops_nn_batch_norm2d.Rd delete mode 100644 man/mlr_pipeops_nn_batch_norm3d.Rd delete mode 100644 man/mlr_pipeops_nn_celu.Rd delete mode 100644 man/mlr_pipeops_nn_conv1d.Rd delete mode 100644 man/mlr_pipeops_nn_conv2d.Rd delete mode 100644 man/mlr_pipeops_nn_conv3d.Rd delete mode 100644 man/mlr_pipeops_nn_conv_transpose1d.Rd delete mode 100644 man/mlr_pipeops_nn_conv_transpose2d.Rd delete mode 100644 man/mlr_pipeops_nn_conv_transpose3d.Rd delete mode 100644 man/mlr_pipeops_nn_dropout.Rd delete mode 100644 man/mlr_pipeops_nn_elu.Rd delete mode 100644 man/mlr_pipeops_nn_flatten.Rd delete mode 100644 man/mlr_pipeops_nn_gelu.Rd delete mode 100644 man/mlr_pipeops_nn_glu.Rd delete mode 100644 man/mlr_pipeops_nn_hardshrink.Rd delete mode 100644 man/mlr_pipeops_nn_hardsigmoid.Rd delete mode 100644 man/mlr_pipeops_nn_hardtanh.Rd delete mode 100644 man/mlr_pipeops_nn_head.Rd delete mode 100644 man/mlr_pipeops_nn_layer_norm.Rd delete mode 100644 man/mlr_pipeops_nn_leaky_relu.Rd delete mode 100644 man/mlr_pipeops_nn_linear.Rd delete mode 100644 man/mlr_pipeops_nn_log_sigmoid.Rd delete mode 100644 man/mlr_pipeops_nn_max_pool1d.Rd delete mode 100644 man/mlr_pipeops_nn_max_pool2d.Rd delete mode 100644 man/mlr_pipeops_nn_max_pool3d.Rd delete mode 100644 man/mlr_pipeops_nn_merge.Rd delete mode 100644 man/mlr_pipeops_nn_merge_cat.Rd delete mode 100644 man/mlr_pipeops_nn_merge_prod.Rd delete mode 100644 man/mlr_pipeops_nn_merge_sum.Rd delete mode 100644 man/mlr_pipeops_nn_prelu.Rd delete mode 100644 man/mlr_pipeops_nn_relu.Rd delete mode 100644 man/mlr_pipeops_nn_relu6.Rd delete mode 100644 man/mlr_pipeops_nn_reshape.Rd delete mode 100644 man/mlr_pipeops_nn_rrelu.Rd delete mode 100644 man/mlr_pipeops_nn_selu.Rd delete mode 100644 man/mlr_pipeops_nn_sigmoid.Rd delete mode 100644 man/mlr_pipeops_nn_softmax.Rd delete mode 100644 man/mlr_pipeops_nn_softplus.Rd delete mode 100644 man/mlr_pipeops_nn_softshrink.Rd delete mode 100644 man/mlr_pipeops_nn_softsign.Rd delete mode 100644 man/mlr_pipeops_nn_squeeze.Rd delete mode 100644 man/mlr_pipeops_nn_tanh.Rd delete mode 100644 man/mlr_pipeops_nn_tanhshrink.Rd delete mode 100644 man/mlr_pipeops_nn_threshold.Rd delete mode 100644 man/mlr_pipeops_preproc_torch.Rd delete mode 100644 man/mlr_pipeops_torch.Rd delete mode 100644 man/mlr_pipeops_torch_callbacks.Rd delete mode 100644 man/mlr_pipeops_torch_ingress.Rd delete mode 100644 man/mlr_pipeops_torch_ingress_categ.Rd delete mode 100644 man/mlr_pipeops_torch_ingress_ltnsr.Rd delete mode 100644 man/mlr_pipeops_torch_ingress_num.Rd delete mode 100644 man/mlr_pipeops_torch_loss.Rd delete mode 100644 man/mlr_pipeops_torch_model.Rd delete mode 100644 man/mlr_pipeops_torch_model_classif.Rd delete mode 100644 man/mlr_pipeops_torch_model_regr.Rd delete mode 100644 man/mlr_pipeops_torch_optimizer.Rd delete mode 100644 man/mlr_resamplings_row_roles.Rd delete mode 100644 man/mlr_tasks_lazy_iris.Rd delete mode 100644 man/mlr_tasks_mnist.Rd delete mode 100644 man/mlr_tasks_tiny_imagenet.Rd delete mode 100644 man/model_descriptor_to_learner.Rd delete mode 100644 man/model_descriptor_to_module.Rd delete mode 100644 man/model_descriptor_union.Rd delete mode 100644 man/nn_graph.Rd delete mode 100644 man/nn_merge_cat.Rd delete mode 100644 man/nn_merge_prod.Rd delete mode 100644 man/nn_merge_sum.Rd delete mode 100644 man/nn_reshape.Rd delete mode 100644 man/nn_squeeze.Rd delete mode 100644 man/nn_unsqueeze.Rd delete mode 100644 man/pipeop_preproc_torch.Rd delete mode 100644 man/reset_layer.Rd delete mode 100644 man/t_clbk.Rd delete mode 100644 man/t_loss.Rd delete mode 100644 man/t_opt.Rd delete mode 100644 man/task_dataset.Rd delete mode 100644 man/torch_callback.Rd diff --git a/R/DataDescriptor.R b/R/DataDescriptor.R index 622ace6c..54408026 100644 --- a/R/DataDescriptor.R +++ b/R/DataDescriptor.R @@ -40,6 +40,7 @@ #' @export #' @include utils.R #' @seealso ModelDescriptor, lazy_tensor +#' @examplesIf torch::torch_is_installed() #' @examples #' # Create a dataset #' dsg = dataset( diff --git a/R/LearnerTorchModel.R b/R/LearnerTorchModel.R index 41e4dea3..d30f4edc 100644 --- a/R/LearnerTorchModel.R +++ b/R/LearnerTorchModel.R @@ -26,6 +26,7 @@ #' @family Graph Network #' @include LearnerTorch.R #' @export +#' @examplesIf torch::torch_is_installed() #' @examples #' # We show the learner using a classification task #' diff --git a/R/PipeOpModule.R b/R/PipeOpModule.R index c3a8e8da..c0b35bfb 100644 --- a/R/PipeOpModule.R +++ b/R/PipeOpModule.R @@ -28,6 +28,7 @@ #' @family Graph Network #' @family PipeOp #' @export +#' @examplesIf torch::torch_is_installed() #' @examples #' ## creating an PipeOpModule manually #' diff --git a/R/PipeOpTaskPreprocTorch.R b/R/PipeOpTaskPreprocTorch.R index 14a61bab..b34590bc 100644 --- a/R/PipeOpTaskPreprocTorch.R +++ b/R/PipeOpTaskPreprocTorch.R @@ -88,6 +88,7 @@ #' #' @include PipeOpTorch.R #' @export +#' @examplesIf torch::torch_is_installed() #' @examples #' # Creating a simple task #' d = data.table( diff --git a/R/PipeOpTorch.R b/R/PipeOpTorch.R index 44ae776a..3f6d8847 100644 --- a/R/PipeOpTorch.R +++ b/R/PipeOpTorch.R @@ -82,6 +82,7 @@ #' [`Graph`] which allows the graph to be modified by-reference in different parts of the code. #' @export #' @family Graph Network +#' @examplesIf torch::torch_is_installed() #' @examples #' ## Creating a neural network #' # In torch diff --git a/R/PipeOpTorchCallbacks.R b/R/PipeOpTorchCallbacks.R index b12392e7..442c23a5 100644 --- a/R/PipeOpTorchCallbacks.R +++ b/R/PipeOpTorchCallbacks.R @@ -20,6 +20,7 @@ #' @family Model Configuration #' @family PipeOp #' @export +#' @examplesIf torch::torch_is_installed() #' @examples #' po_cb = po("torch_callbacks", "checkpoint") #' po_cb$param_set diff --git a/R/PipeOpTorchIngress.R b/R/PipeOpTorchIngress.R index cda79335..47963c8f 100644 --- a/R/PipeOpTorchIngress.R +++ b/R/PipeOpTorchIngress.R @@ -123,6 +123,7 @@ PipeOpTorchIngress = R6Class("PipeOpTorchIngress", #' @return `TorchIngressToken` object. #' @family Graph Network #' @export +#' @examplesIf torch::torch_is_installed() #' @examples #' # Define a task for which we want to define an ingress token #' task = tsk("iris") @@ -177,6 +178,7 @@ print.TorchIngressToken = function(x, ...) { #' @export #' @family Graph Network #' @family PipeOps +#' @examplesIf torch::torch_is_installed() #' @examples # We select the numeric features first #' graph = po("select", selector = selector_type(c("numeric", "integer"))) %>>% @@ -227,6 +229,7 @@ register_po("torch_ingress_num", PipeOpTorchIngressNumeric) #' @family PipeOps #' @family Graph Network #' @export +#' @examplesIf torch::torch_is_installed() #' @examples # We first select the categorical features #' graph = po("select", selector = selector_type("factor")) %>>% @@ -277,6 +280,7 @@ register_po("torch_ingress_categ", PipeOpTorchIngressCategorical) #' @family Graph Network #' @export #' @include utils.R shape.R +#' @examplesIf torch::torch_is_installed() #' @examples #' po_ingress = po("torch_ingress_ltnsr") #' task = tsk("lazy_iris") diff --git a/R/PipeOpTorchLoss.R b/R/PipeOpTorchLoss.R index 5ae51c50..8ee93c4f 100644 --- a/R/PipeOpTorchLoss.R +++ b/R/PipeOpTorchLoss.R @@ -17,6 +17,7 @@ #' @family Model Configuration #' #' @export +#' @examplesIf torch::torch_is_installed() #' @examples #' po_loss = po("torch_loss", loss = t_loss("cross_entropy")) #' po_loss$param_set diff --git a/R/PipeOpTorchModel.R b/R/PipeOpTorchModel.R index 1d9be2af..576b447c 100644 --- a/R/PipeOpTorchModel.R +++ b/R/PipeOpTorchModel.R @@ -106,6 +106,7 @@ PipeOpTorchModel = R6Class("PipeOpTorchModel", #' @inheritSection mlr_pipeops_torch_model Internals #' @family PipeOps #' @export +#' @examplesIf torch::torch_is_installed() #' @examples #' # simple logistic regression #' @@ -150,6 +151,7 @@ PipeOpTorchModelClassif = R6Class("PipeOpTorchModelClassif", #' @inheritSection mlr_pipeops_torch_model Internals #' @family PipeOps #' @export +#' @examplesIf torch::torch_is_installed() #' @examples #' # simple linear regression #' diff --git a/R/PipeOpTorchOptimizer.R b/R/PipeOpTorchOptimizer.R index dfd6cc74..c7c80d61 100644 --- a/R/PipeOpTorchOptimizer.R +++ b/R/PipeOpTorchOptimizer.R @@ -21,6 +21,7 @@ #' @family PipeOp #' @family Model Configuration #' @export +#' @examplesIf torch::torch_is_installed() #' @examples #' po_opt = po("torch_optimizer", "sgd", lr = 0.01) #' po_opt$param_set diff --git a/R/TaskClassif_lazy_iris.R b/R/TaskClassif_lazy_iris.R index 7419ad01..695c843b 100644 --- a/R/TaskClassif_lazy_iris.R +++ b/R/TaskClassif_lazy_iris.R @@ -21,6 +21,7 @@ #' #' @references #' `r format_bib("anderson_1936")` +#' @examplesIf torch::torch_is_installed() #' @examples #' task = tsk("lazy_iris") #' df = task$data() diff --git a/R/TorchCallback.R b/R/TorchCallback.R index 37ca32f8..fa8bfba0 100644 --- a/R/TorchCallback.R +++ b/R/TorchCallback.R @@ -149,6 +149,7 @@ as_torch_callbacks.character = function(x, clone = FALSE, ...) { # nolint #' @family Torch Descriptor #' #' @export +#' @examplesIf torch::torch_is_installed() #' @examples #' # Create a new torch callback from an existing callback set #' torch_callback = TorchCallback$new(CallbackSetCheckpoint) @@ -247,6 +248,7 @@ TorchCallback = R6Class("TorchCallback", #' @return [`TorchCallback`] #' @include zzz.R CallbackSet.R #' @family Callback +#' @examplesIf torch::torch_is_installed() #' @examples #' custom_tcb = torch_callback("custom", #' initialize = function(name) { diff --git a/R/TorchLoss.R b/R/TorchLoss.R index 4c75f161..d7155268 100644 --- a/R/TorchLoss.R +++ b/R/TorchLoss.R @@ -55,6 +55,7 @@ as_torch_loss.character = function(x, clone = FALSE, ...) { # nolint #' #' @family Torch Descriptor #' @export +#' @examplesIf torch::torch_is_installed() #' @examples #' # Create a new torch loss #' torch_loss = TorchLoss$new(torch_loss = nn_mse_loss, task_types = "regr") diff --git a/R/TorchOptimizer.R b/R/TorchOptimizer.R index 215dfe91..dfea10b2 100644 --- a/R/TorchOptimizer.R +++ b/R/TorchOptimizer.R @@ -57,6 +57,7 @@ as_torch_optimizer.character = function(x, clone = FALSE, ...) { # nolint #' #' @family Torch Descriptor #' @export +#' @examplesIf torch::torch_is_installed() #' @examples #' # Create a new torch loss #' torch_opt = TorchOptimizer$new(optim_adam, label = "adam") @@ -146,6 +147,7 @@ TorchOptimizer = R6::R6Class("TorchOptimizer", #' @family Torch Descriptor #' @family Dictionary #' @export +#' @examplesIf torch::torch_is_installed() #' @examples #' mlr3torch_optimizers$get("adam") #' # is equivalent to diff --git a/R/lazy_tensor.R b/R/lazy_tensor.R index 0912eb32..d6f3daa6 100644 --- a/R/lazy_tensor.R +++ b/R/lazy_tensor.R @@ -209,6 +209,7 @@ is_lazy_tensor = function(x) { #' 1. A new [`DataDescriptor`] is created #' #' @return [`lazy_tensor`] +#' @examplesIf torch::torch_is_installed() #' @examples #' lt = as_lazy_tensor(1:10) #' add_five = po("module", module = function(x) x + 5) diff --git a/R/materialize.R b/R/materialize.R index 1d94704b..02138a1e 100644 --- a/R/materialize.R +++ b/R/materialize.R @@ -33,6 +33,7 @@ #' @param ... (any)\cr #' Additional arguments. #' @export +#' @examplesIf torch::torch_is_installed() #' @examples #' lt1 = as_lazy_tensor(torch_randn(10, 3)) #' materialize(lt1, rbind = TRUE) diff --git a/R/nn_graph.R b/R/nn_graph.R index 0a89cf54..86c6118a 100644 --- a/R/nn_graph.R +++ b/R/nn_graph.R @@ -15,6 +15,7 @@ #' @return [`nn_graph`] #' @family Graph Network #' @export +#' @examplesIf torch::torch_is_installed() #' @examples #' graph = mlr3pipelines::Graph$new() #' graph$add_pipeop(po("module_1", module = nn_linear(10, 20)), clone = FALSE) diff --git a/R/reset_last_layer.R b/R/reset_last_layer.R index d6a761f1..29827f0c 100644 --- a/R/reset_last_layer.R +++ b/R/reset_last_layer.R @@ -17,10 +17,11 @@ #' @return Same as input `model` with modified last layer. #' @export #' +#' @examplesIf torch::torch_is_installed() #' @examples #' \dontrun{ #' # AlexNet -#' if (mlr3misc::requires_namespaces("torchvision")) { +#' if (mlr3misc::requires_namespaces("torchvision") && torch::torch_is_installed(h)) { #' model = torchvision::model_alexnet(pretrained = TRUE) #' model$classifier[[7]]$out_feature #' model = reset_last_layer(model, 10) diff --git a/R/task_dataset.R b/R/task_dataset.R index 6326d600..8f13e0cd 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -20,6 +20,7 @@ #' The device, e.g. `"cuda"` or `"cpu"`. #' @export #' @return [`torch::dataset`] +#' @examplesIf torch::torch_is_installed() #' @examples #' task = tsk("iris") #' sepal_ingress = TorchIngressToken( diff --git a/man-roxygen/learner_example.R b/man-roxygen/learner_example.R index f3e11c88..f2c763fd 100644 --- a/man-roxygen/learner_example.R +++ b/man-roxygen/learner_example.R @@ -3,6 +3,7 @@ #' <% id = paste0(task_types_vec[1], ".", name)%> #' <% task_id = default_task_id(lrn(id)) %> #' +#' @examplesIf torch::torch_is_installed() #' @examples #' # Define the Learner and set parameter values #' <%= sprintf("learner = lrn(\"%s\")", id)%> diff --git a/man-roxygen/pipeop_torch_example.R b/man-roxygen/pipeop_torch_example.R index 37a22048..da60139e 100644 --- a/man-roxygen/pipeop_torch_example.R +++ b/man-roxygen/pipeop_torch_example.R @@ -1,5 +1,6 @@ #' <% param_vals = if (exists("param_vals", inherits = FALSE)) paste0(", ", param_vals)%> #' +#' @examplesIf torch::torch_is_installed() #' @examples #' # Construct the PipeOp #' pipeop = po("<%=id %>"<%=param_vals%>) @@ -10,6 +11,7 @@ # Maybe finish this at some point +# @examplesIf torch::torch_is_installed() # md = ModelDescriptor( # graph = # ) diff --git a/man/DataDescriptor.Rd b/man/DataDescriptor.Rd deleted file mode 100644 index 3eab4374..00000000 --- a/man/DataDescriptor.Rd +++ /dev/null @@ -1,166 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/DataDescriptor.R -\name{DataDescriptor} -\alias{DataDescriptor} -\title{Data Descriptor} -\description{ -A data descriptor is a rather internal data structure used in the \code{\link{lazy_tensor}} data type. -In essence it is an annotated \code{\link[torch:dataset]{torch::dataset}} and a preprocessing graph (consisting mosty of \code{\link{PipeOpModule}} -operators). The additional meta data (e.g. pointer, shapes) allows to preprocess \code{\link{lazy_tensor}}s in an -\code{\link[mlr3pipelines:Graph]{mlr3pipelines::Graph}} just like any (non-lazy) data types. -The preprocessing is applied when \code{\link[=materialize]{materialize()}} is called on the \code{\link{lazy_tensor}}. -} -\details{ -While it would be more natural to define this as an S3 class, we opted for an R6 class to avoid the usual -trouble of serializing S3 objects. -If each row contained a DataDescriptor as an S3 class, this would copy the object when serializing. -} -\examples{ -# Create a dataset -dsg = dataset( - initialize = function() self$x = torch_randn(10, 3, 3), - .getitem = function(i) list(x = self$x[i, ]), - .length = function() nrow(self$x) -) -ds = dsg() -dd = DataDescriptor$new(ds, list(x = c(NA, 3, 3))) -dd -} -\seealso{ -ModelDescriptor, lazy_tensor -} -\section{Public fields}{ -\if{html}{\out{
}} -\describe{ -\item{\code{dataset}}{(\code{\link[torch:dataset]{torch::dataset}})\cr -The dataset.} - -\item{\code{graph}}{(\code{\link{Graph}})\cr -The preprocessing graph.} - -\item{\code{dataset_shapes}}{(named \code{list()} of (\code{integer()} or \code{NULL}))\cr -The shapes of the output.} - -\item{\code{input_map}}{(\code{character()})\cr -The input map from the dataset to the preprocessing graph.} - -\item{\code{pointer}}{(\code{character(2)})\cr -The output pointer.} - -\item{\code{pointer_shape}}{(\code{integer()} | \code{NULL})\cr -The shape of the output indicated by \code{pointer}.} - -\item{\code{dataset_hash}}{(\code{character(1)})\cr -Hash for the wrapped dataset.} - -\item{\code{hash}}{(\code{character(1)})\cr -Hash for the data descriptor.} - -\item{\code{graph_input}}{(\code{character()})\cr -The input channels of the preprocessing graph (cached to save time).} - -\item{\code{pointer_shape_predict}}{(\code{integer()} or \code{NULL})\cr -Internal use only.} -} -\if{html}{\out{
}} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-DataDescriptor-new}{\code{DataDescriptor$new()}} -\item \href{#method-DataDescriptor-print}{\code{DataDescriptor$print()}} -\item \href{#method-DataDescriptor-clone}{\code{DataDescriptor$clone()}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-DataDescriptor-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{DataDescriptor$new( - dataset, - dataset_shapes, - graph = NULL, - input_map = NULL, - pointer = NULL, - pointer_shape = NULL, - pointer_shape_predict = NULL, - clone_graph = TRUE -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{dataset}}{(\code{\link[torch:dataset]{torch::dataset}})\cr -The torch dataset.} - -\item{\code{dataset_shapes}}{(named \code{list()} of (\code{integer()} or \code{NULL}))\cr -The shapes of the output. -Names are the elements of the list returned by the dataset. -If the shape is not \code{NULL} (unknown, e.g. for images of different sizes) the first dimension must be \code{NA} to -indicate the batch dimension.} - -\item{\code{graph}}{(\code{\link{Graph}})\cr -The preprocessing graph. -If left \code{NULL}, no preprocessing is applied to the data and \code{input_map}, \code{pointer}, \code{pointer_shape}, and -\code{pointer_shape_predict} are inferred in case the dataset returns only one element.} - -\item{\code{input_map}}{(\code{character()})\cr -Character vector that must have the same length as the input of the graph. -Specifies how the data from the \code{dataset} is fed into the preprocessing graph.} - -\item{\code{pointer}}{(\code{character(2)} | \code{NULL})\cr -Points to an output channel within \code{graph}: -Element 1 is the \code{PipeOp}'s id and element 2 is that \code{PipeOp}'s output channel.} - -\item{\code{pointer_shape}}{(\code{integer()} | \code{NULL})\cr -Shape of the output indicated by \code{pointer}.} - -\item{\code{pointer_shape_predict}}{(\code{integer()} or \code{NULL})\cr -Internal use only. -Used in a \code{\link{Graph}} to anticipate possible mismatches between train and predict shapes.} - -\item{\code{clone_graph}}{(\code{logical(1)})\cr -Whether to clone the preprocessing graph.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-DataDescriptor-print}{}}} -\subsection{Method \code{print()}}{ -Prints the object -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{DataDescriptor$print(...)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{...}}{(any)\cr -Unused} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-DataDescriptor-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{DataDescriptor$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/ModelDescriptor.Rd b/man/ModelDescriptor.Rd deleted file mode 100644 index 38a350f9..00000000 --- a/man/ModelDescriptor.Rd +++ /dev/null @@ -1,91 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/ModelDescriptor.R -\name{ModelDescriptor} -\alias{ModelDescriptor} -\title{Represent a Model with Meta-Info} -\usage{ -ModelDescriptor( - graph, - ingress, - task, - optimizer = NULL, - loss = NULL, - callbacks = NULL, - pointer = NULL, - pointer_shape = NULL -) -} -\arguments{ -\item{graph}{(\code{\link[mlr3pipelines:Graph]{Graph}})\cr -\code{Graph} of \code{\link{PipeOpModule}} and \code{\link{PipeOpNOP}} operators.} - -\item{ingress}{(uniquely named \code{list} of \code{TorchIngressToken})\cr -List of inputs that go into \code{graph}. Names of this must be a subset of \code{graph$input$name}.} - -\item{task}{(\code{\link[mlr3:Task]{Task}})\cr -(Training)-Task for which the model is being built. May be necessary for for some aspects of what loss to use etc.} - -\item{optimizer}{(\code{\link{TorchOptimizer}} | \code{NULL})\cr -Additional info: what optimizer to use.} - -\item{loss}{(\code{\link{TorchLoss}} | \code{NULL})\cr -Additional info: what loss to use.} - -\item{callbacks}{(A \code{list} of \code{\link{CallbackSet}} or \code{NULL})\cr -Additional info: what callbacks to use.} - -\item{pointer}{(\code{character(2)} | \code{NULL})\cr -Indicating an element on which a model is. Points to an output channel within \code{graph}: -Element 1 is the \code{PipeOp}'s id and element 2 is that \code{PipeOp}'s output channel.} - -\item{pointer_shape}{(\code{integer} | \code{NULL})\cr -Shape of the output indicated by \code{pointer}.} -} -\value{ -(\code{ModelDescriptor}) -} -\description{ -Represents a \emph{model}; possibly a complete model, possibly one in the process of being built up. - -This model takes input tensors of shapes \code{shapes_in} and -pipes them through \code{graph}. Input shapes get mapped to input channels of \code{graph}. -Output shapes are named by the output channels of \code{graph}; it is also possible -to represent no-ops on tensors, in which case names of input and output should be identical. - -\code{ModelDescriptor} objects typically represent partial models being built up, in which case the \code{pointer} slot -indicates a specific point in the graph that produces a tensor of shape \code{pointer_shape}, on which the graph should -be extended. -It is allowed for the \code{graph} in this structure to be modified by-reference in different parts of the code. -However, these modifications may never add edges with elements of the \code{Graph} as destination. In particular, no -element of \code{graph$input} may be removed by reference, e.g. by adding an edge to the \code{Graph} that has the input -channel of a \code{PipeOp} that was previously without parent as its destination. - -In most cases it is better to create a specific \code{ModelDescriptor} by training a \code{\link{Graph}} consisting (mostly) of -operators \code{\link{PipeOpTorchIngress}}, \code{\link{PipeOpTorch}}, \code{\link{PipeOpTorchLoss}}, \code{\link{PipeOpTorchOptimizer}}, and -\code{\link{PipeOpTorchCallbacks}}. - -A \code{ModelDescriptor} can be converted to a \code{\link{nn_graph}} via \code{\link{model_descriptor_to_module}}. -} -\seealso{ -Other Model Configuration: -\code{\link{mlr_pipeops_torch_callbacks}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_optimizer}}, -\code{\link{model_descriptor_union}()} - -Other Graph Network: -\code{\link{TorchIngressToken}()}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{model_descriptor_to_learner}()}, -\code{\link{model_descriptor_to_module}()}, -\code{\link{model_descriptor_union}()}, -\code{\link{nn_graph}()} -} -\concept{Graph Network} -\concept{Model Configuration} diff --git a/man/PipeOpPreprocTorchAugmentCenterCrop.Rd b/man/PipeOpPreprocTorchAugmentCenterCrop.Rd deleted file mode 100644 index 6a0c706e..00000000 --- a/man/PipeOpPreprocTorchAugmentCenterCrop.Rd +++ /dev/null @@ -1,23 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.augment_center_crop} -\alias{mlr_pipeops_preproc_torch.augment_center_crop} -\alias{PipeOpPreprocTorchAugmentCenterCrop} -\title{PipeOpPreprocTorchAugmentCenterCrop} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_center_crop]{torchvision::transform_center_crop}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - size \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr -} -} - diff --git a/man/PipeOpPreprocTorchAugmentColorJitter.Rd b/man/PipeOpPreprocTorchAugmentColorJitter.Rd deleted file mode 100644 index bf55d6b6..00000000 --- a/man/PipeOpPreprocTorchAugmentColorJitter.Rd +++ /dev/null @@ -1,26 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.augment_color_jitter} -\alias{mlr_pipeops_preproc_torch.augment_color_jitter} -\alias{PipeOpPreprocTorchAugmentColorJitter} -\title{PipeOpPreprocTorchAugmentColorJitter} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_color_jitter]{torchvision::transform_color_jitter}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{lllll}{ - Id \tab Type \tab Default \tab Levels \tab Range \cr - brightness \tab numeric \tab 0 \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr - contrast \tab numeric \tab 0 \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr - saturation \tab numeric \tab 0 \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr - hue \tab numeric \tab 0 \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr - stages \tab character \tab - \tab train, predict, both \tab - \cr - affect_columns \tab untyped \tab selector_all \tab \tab - \cr -} -} - diff --git a/man/PipeOpPreprocTorchAugmentCrop.Rd b/man/PipeOpPreprocTorchAugmentCrop.Rd deleted file mode 100644 index 15aa7624..00000000 --- a/man/PipeOpPreprocTorchAugmentCrop.Rd +++ /dev/null @@ -1,26 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.augment_crop} -\alias{mlr_pipeops_preproc_torch.augment_crop} -\alias{PipeOpPreprocTorchAugmentCrop} -\title{PipeOpPreprocTorchAugmentCrop} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_crop]{torchvision::transform_crop}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{lllll}{ - Id \tab Type \tab Default \tab Levels \tab Range \cr - top \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr - left \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr - height \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr - width \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr - stages \tab character \tab - \tab train, predict, both \tab - \cr - affect_columns \tab untyped \tab selector_all \tab \tab - \cr -} -} - diff --git a/man/PipeOpPreprocTorchAugmentHflip.Rd b/man/PipeOpPreprocTorchAugmentHflip.Rd deleted file mode 100644 index 39f23af7..00000000 --- a/man/PipeOpPreprocTorchAugmentHflip.Rd +++ /dev/null @@ -1,22 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.augment_hflip} -\alias{mlr_pipeops_preproc_torch.augment_hflip} -\alias{PipeOpPreprocTorchAugmentHflip} -\title{PipeOpPreprocTorchAugmentHflip} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_hflip]{torchvision::transform_hflip}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr -} -} - diff --git a/man/PipeOpPreprocTorchAugmentRandomAffine.Rd b/man/PipeOpPreprocTorchAugmentRandomAffine.Rd deleted file mode 100644 index 043feaab..00000000 --- a/man/PipeOpPreprocTorchAugmentRandomAffine.Rd +++ /dev/null @@ -1,27 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.augment_random_affine} -\alias{mlr_pipeops_preproc_torch.augment_random_affine} -\alias{PipeOpPreprocTorchAugmentRandomAffine} -\title{PipeOpPreprocTorchAugmentRandomAffine} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_random_affine]{torchvision::transform_random_affine}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{lllll}{ - Id \tab Type \tab Default \tab Levels \tab Range \cr - degrees \tab untyped \tab - \tab \tab - \cr - translate \tab untyped \tab \tab \tab - \cr - scale \tab untyped \tab \tab \tab - \cr - resample \tab integer \tab 0 \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr - fillcolor \tab untyped \tab 0 \tab \tab - \cr - stages \tab character \tab - \tab train, predict, both \tab - \cr - affect_columns \tab untyped \tab selector_all \tab \tab - \cr -} -} - diff --git a/man/PipeOpPreprocTorchAugmentRandomApply.Rd b/man/PipeOpPreprocTorchAugmentRandomApply.Rd deleted file mode 100644 index 169d6b1c..00000000 --- a/man/PipeOpPreprocTorchAugmentRandomApply.Rd +++ /dev/null @@ -1,24 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.augment_random_apply} -\alias{mlr_pipeops_preproc_torch.augment_random_apply} -\alias{PipeOpPreprocTorchAugmentRandomApply} -\title{PipeOpPreprocTorchAugmentRandomApply} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_random_apply]{torchvision::transform_random_apply}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{lllll}{ - Id \tab Type \tab Default \tab Levels \tab Range \cr - transforms \tab untyped \tab - \tab \tab - \cr - p \tab numeric \tab 0.5 \tab \tab \eqn{[0, 1]}{[0, 1]} \cr - stages \tab character \tab - \tab train, predict, both \tab - \cr - affect_columns \tab untyped \tab selector_all \tab \tab - \cr -} -} - diff --git a/man/PipeOpPreprocTorchAugmentRandomChoice.Rd b/man/PipeOpPreprocTorchAugmentRandomChoice.Rd deleted file mode 100644 index f73d415f..00000000 --- a/man/PipeOpPreprocTorchAugmentRandomChoice.Rd +++ /dev/null @@ -1,23 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.augment_random_choice} -\alias{mlr_pipeops_preproc_torch.augment_random_choice} -\alias{PipeOpPreprocTorchAugmentRandomChoice} -\title{PipeOpPreprocTorchAugmentRandomChoice} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_random_choice]{torchvision::transform_random_choice}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - transforms \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr -} -} - diff --git a/man/PipeOpPreprocTorchAugmentRandomCrop.Rd b/man/PipeOpPreprocTorchAugmentRandomCrop.Rd deleted file mode 100644 index c07d5c90..00000000 --- a/man/PipeOpPreprocTorchAugmentRandomCrop.Rd +++ /dev/null @@ -1,27 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.augment_random_crop} -\alias{mlr_pipeops_preproc_torch.augment_random_crop} -\alias{PipeOpPreprocTorchAugmentRandomCrop} -\title{PipeOpPreprocTorchAugmentRandomCrop} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_random_crop]{torchvision::transform_random_crop}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - size \tab untyped \tab - \tab \cr - padding \tab untyped \tab \tab \cr - pad_if_needed \tab logical \tab FALSE \tab TRUE, FALSE \cr - fill \tab untyped \tab 0 \tab \cr - padding_mode \tab character \tab constant \tab constant, edge, reflect, symmetric \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr -} -} - diff --git a/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd b/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd deleted file mode 100644 index 49522bb6..00000000 --- a/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd +++ /dev/null @@ -1,23 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.augment_random_horizontal_flip} -\alias{mlr_pipeops_preproc_torch.augment_random_horizontal_flip} -\alias{PipeOpPreprocTorchAugmentRandomHorizontalFlip} -\title{PipeOpPreprocTorchAugmentRandomHorizontalFlip} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_random_horizontal_flip]{torchvision::transform_random_horizontal_flip}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{lllll}{ - Id \tab Type \tab Default \tab Levels \tab Range \cr - p \tab numeric \tab 0.5 \tab \tab \eqn{[0, 1]}{[0, 1]} \cr - stages \tab character \tab - \tab train, predict, both \tab - \cr - affect_columns \tab untyped \tab selector_all \tab \tab - \cr -} -} - diff --git a/man/PipeOpPreprocTorchAugmentRandomOrder.Rd b/man/PipeOpPreprocTorchAugmentRandomOrder.Rd deleted file mode 100644 index ed629317..00000000 --- a/man/PipeOpPreprocTorchAugmentRandomOrder.Rd +++ /dev/null @@ -1,23 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.augment_random_order} -\alias{mlr_pipeops_preproc_torch.augment_random_order} -\alias{PipeOpPreprocTorchAugmentRandomOrder} -\title{PipeOpPreprocTorchAugmentRandomOrder} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_random_order]{torchvision::transform_random_order}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - transforms \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr -} -} - diff --git a/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd b/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd deleted file mode 100644 index a5f74d63..00000000 --- a/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd +++ /dev/null @@ -1,26 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.augment_random_resized_crop} -\alias{mlr_pipeops_preproc_torch.augment_random_resized_crop} -\alias{PipeOpPreprocTorchAugmentRandomResizedCrop} -\title{PipeOpPreprocTorchAugmentRandomResizedCrop} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_random_resized_crop]{torchvision::transform_random_resized_crop}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{lllll}{ - Id \tab Type \tab Default \tab Levels \tab Range \cr - size \tab untyped \tab - \tab \tab - \cr - scale \tab untyped \tab c , 0.08, 1 \tab \tab - \cr - ratio \tab untyped \tab c , 3/4, 4/3 \tab \tab - \cr - interpolation \tab integer \tab 2 \tab \tab \eqn{[0, 3]}{[0, 3]} \cr - stages \tab character \tab - \tab train, predict, both \tab - \cr - affect_columns \tab untyped \tab selector_all \tab \tab - \cr -} -} - diff --git a/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd b/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd deleted file mode 100644 index 5781cfba..00000000 --- a/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd +++ /dev/null @@ -1,23 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.augment_random_vertical_flip} -\alias{mlr_pipeops_preproc_torch.augment_random_vertical_flip} -\alias{PipeOpPreprocTorchAugmentRandomVerticalFlip} -\title{PipeOpPreprocTorchAugmentRandomVerticalFlip} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_random_vertical_flip]{torchvision::transform_random_vertical_flip}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{lllll}{ - Id \tab Type \tab Default \tab Levels \tab Range \cr - p \tab numeric \tab 0.5 \tab \tab \eqn{[0, 1]}{[0, 1]} \cr - stages \tab character \tab - \tab train, predict, both \tab - \cr - affect_columns \tab untyped \tab selector_all \tab \tab - \cr -} -} - diff --git a/man/PipeOpPreprocTorchAugmentResizedCrop.Rd b/man/PipeOpPreprocTorchAugmentResizedCrop.Rd deleted file mode 100644 index 799dbc10..00000000 --- a/man/PipeOpPreprocTorchAugmentResizedCrop.Rd +++ /dev/null @@ -1,28 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.augment_resized_crop} -\alias{mlr_pipeops_preproc_torch.augment_resized_crop} -\alias{PipeOpPreprocTorchAugmentResizedCrop} -\title{PipeOpPreprocTorchAugmentResizedCrop} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_resized_crop]{torchvision::transform_resized_crop}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{lllll}{ - Id \tab Type \tab Default \tab Levels \tab Range \cr - top \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr - left \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr - height \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr - width \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr - size \tab untyped \tab - \tab \tab - \cr - interpolation \tab integer \tab 2 \tab \tab \eqn{[0, 3]}{[0, 3]} \cr - stages \tab character \tab - \tab train, predict, both \tab - \cr - affect_columns \tab untyped \tab selector_all \tab \tab - \cr -} -} - diff --git a/man/PipeOpPreprocTorchAugmentRotate.Rd b/man/PipeOpPreprocTorchAugmentRotate.Rd deleted file mode 100644 index 6508b070..00000000 --- a/man/PipeOpPreprocTorchAugmentRotate.Rd +++ /dev/null @@ -1,27 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.augment_rotate} -\alias{mlr_pipeops_preproc_torch.augment_rotate} -\alias{PipeOpPreprocTorchAugmentRotate} -\title{PipeOpPreprocTorchAugmentRotate} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_rotate]{torchvision::transform_rotate}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{lllll}{ - Id \tab Type \tab Default \tab Levels \tab Range \cr - angle \tab untyped \tab - \tab \tab - \cr - resample \tab integer \tab 0 \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr - expand \tab logical \tab FALSE \tab TRUE, FALSE \tab - \cr - center \tab untyped \tab \tab \tab - \cr - fill \tab untyped \tab \tab \tab - \cr - stages \tab character \tab - \tab train, predict, both \tab - \cr - affect_columns \tab untyped \tab selector_all \tab \tab - \cr -} -} - diff --git a/man/PipeOpPreprocTorchAugmentVflip.Rd b/man/PipeOpPreprocTorchAugmentVflip.Rd deleted file mode 100644 index 36c15cfe..00000000 --- a/man/PipeOpPreprocTorchAugmentVflip.Rd +++ /dev/null @@ -1,22 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.augment_vflip} -\alias{mlr_pipeops_preproc_torch.augment_vflip} -\alias{PipeOpPreprocTorchAugmentVflip} -\title{PipeOpPreprocTorchAugmentVflip} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_vflip]{torchvision::transform_vflip}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr -} -} - diff --git a/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd b/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd deleted file mode 100644 index fe636d29..00000000 --- a/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd +++ /dev/null @@ -1,23 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.trafo_adjust_brightness} -\alias{mlr_pipeops_preproc_torch.trafo_adjust_brightness} -\alias{PipeOpPreprocTorchTrafoAdjustBrightness} -\title{PipeOpPreprocTorchTrafoAdjustBrightness} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_adjust_brightness]{torchvision::transform_adjust_brightness}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{lllll}{ - Id \tab Type \tab Default \tab Levels \tab Range \cr - brightness_factor \tab numeric \tab - \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr - stages \tab character \tab - \tab train, predict, both \tab - \cr - affect_columns \tab untyped \tab selector_all \tab \tab - \cr -} -} - diff --git a/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd b/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd deleted file mode 100644 index a2bcef11..00000000 --- a/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd +++ /dev/null @@ -1,24 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.trafo_adjust_gamma} -\alias{mlr_pipeops_preproc_torch.trafo_adjust_gamma} -\alias{PipeOpPreprocTorchTrafoAdjustGamma} -\title{PipeOpPreprocTorchTrafoAdjustGamma} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_adjust_gamma]{torchvision::transform_adjust_gamma}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{lllll}{ - Id \tab Type \tab Default \tab Levels \tab Range \cr - gamma \tab numeric \tab - \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr - gain \tab numeric \tab 1 \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr - stages \tab character \tab - \tab train, predict, both \tab - \cr - affect_columns \tab untyped \tab selector_all \tab \tab - \cr -} -} - diff --git a/man/PipeOpPreprocTorchTrafoAdjustHue.Rd b/man/PipeOpPreprocTorchTrafoAdjustHue.Rd deleted file mode 100644 index 1cc75a96..00000000 --- a/man/PipeOpPreprocTorchTrafoAdjustHue.Rd +++ /dev/null @@ -1,23 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.trafo_adjust_hue} -\alias{mlr_pipeops_preproc_torch.trafo_adjust_hue} -\alias{PipeOpPreprocTorchTrafoAdjustHue} -\title{PipeOpPreprocTorchTrafoAdjustHue} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_adjust_hue]{torchvision::transform_adjust_hue}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{lllll}{ - Id \tab Type \tab Default \tab Levels \tab Range \cr - hue_factor \tab numeric \tab - \tab \tab \eqn{[-0.5, 0.5]}{[-0.5, 0.5]} \cr - stages \tab character \tab - \tab train, predict, both \tab - \cr - affect_columns \tab untyped \tab selector_all \tab \tab - \cr -} -} - diff --git a/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd b/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd deleted file mode 100644 index ced93824..00000000 --- a/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd +++ /dev/null @@ -1,23 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.trafo_adjust_saturation} -\alias{mlr_pipeops_preproc_torch.trafo_adjust_saturation} -\alias{PipeOpPreprocTorchTrafoAdjustSaturation} -\title{PipeOpPreprocTorchTrafoAdjustSaturation} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_adjust_saturation]{torchvision::transform_adjust_saturation}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{lllll}{ - Id \tab Type \tab Default \tab Levels \tab Range \cr - saturation_factor \tab numeric \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr - stages \tab character \tab - \tab train, predict, both \tab - \cr - affect_columns \tab untyped \tab selector_all \tab \tab - \cr -} -} - diff --git a/man/PipeOpPreprocTorchTrafoGrayscale.Rd b/man/PipeOpPreprocTorchTrafoGrayscale.Rd deleted file mode 100644 index 014d8fee..00000000 --- a/man/PipeOpPreprocTorchTrafoGrayscale.Rd +++ /dev/null @@ -1,23 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.trafo_grayscale} -\alias{mlr_pipeops_preproc_torch.trafo_grayscale} -\alias{PipeOpPreprocTorchTrafoGrayscale} -\title{PipeOpPreprocTorchTrafoGrayscale} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_grayscale]{torchvision::transform_grayscale}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{lllll}{ - Id \tab Type \tab Default \tab Levels \tab Range \cr - num_output_channels \tab integer \tab - \tab \tab \eqn{[1, 3]}{[1, 3]} \cr - stages \tab character \tab - \tab train, predict, both \tab - \cr - affect_columns \tab untyped \tab selector_all \tab \tab - \cr -} -} - diff --git a/man/PipeOpPreprocTorchTrafoNop.Rd b/man/PipeOpPreprocTorchTrafoNop.Rd deleted file mode 100644 index 1d8eb892..00000000 --- a/man/PipeOpPreprocTorchTrafoNop.Rd +++ /dev/null @@ -1,12 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.trafo_nop} -\alias{mlr_pipeops_preproc_torch.trafo_nop} -\alias{PipeOpPreprocTorchTrafoNop} -\title{PipeOpPreprocTorchTrafoNop} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Does nothing. -} diff --git a/man/PipeOpPreprocTorchTrafoNormalize.Rd b/man/PipeOpPreprocTorchTrafoNormalize.Rd deleted file mode 100644 index a802514b..00000000 --- a/man/PipeOpPreprocTorchTrafoNormalize.Rd +++ /dev/null @@ -1,24 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.trafo_normalize} -\alias{mlr_pipeops_preproc_torch.trafo_normalize} -\alias{PipeOpPreprocTorchTrafoNormalize} -\title{PipeOpPreprocTorchTrafoNormalize} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_normalize]{torchvision::transform_normalize}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - mean \tab untyped \tab - \tab \cr - std \tab untyped \tab - \tab \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr -} -} - diff --git a/man/PipeOpPreprocTorchTrafoPad.Rd b/man/PipeOpPreprocTorchTrafoPad.Rd deleted file mode 100644 index b9c7f1ca..00000000 --- a/man/PipeOpPreprocTorchTrafoPad.Rd +++ /dev/null @@ -1,25 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.trafo_pad} -\alias{mlr_pipeops_preproc_torch.trafo_pad} -\alias{PipeOpPreprocTorchTrafoPad} -\title{PipeOpPreprocTorchTrafoPad} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_pad]{torchvision::transform_pad}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - padding \tab untyped \tab - \tab \cr - fill \tab untyped \tab 0 \tab \cr - padding_mode \tab character \tab constant \tab constant, edge, reflect, symmetric \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr -} -} - diff --git a/man/PipeOpPreprocTorchTrafoResize.Rd b/man/PipeOpPreprocTorchTrafoResize.Rd deleted file mode 100644 index b031940b..00000000 --- a/man/PipeOpPreprocTorchTrafoResize.Rd +++ /dev/null @@ -1,24 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.trafo_resize} -\alias{mlr_pipeops_preproc_torch.trafo_resize} -\alias{PipeOpPreprocTorchTrafoResize} -\title{PipeOpPreprocTorchTrafoResize} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_resize]{torchvision::transform_resize}}, -see there for more information on the parameters. -The preprocessing is applied to the whole batch. -} -\section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - size \tab untyped \tab - \tab \cr - interpolation \tab character \tab 2 \tab Undefined, Bartlett, Blackman, Bohman, Box, Catrom, Cosine, Cubic, Gaussian, Hamming, \link{...} \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr -} -} - diff --git a/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd b/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd deleted file mode 100644 index 10a89e1a..00000000 --- a/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd +++ /dev/null @@ -1,22 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.trafo_rgb_to_grayscale} -\alias{mlr_pipeops_preproc_torch.trafo_rgb_to_grayscale} -\alias{PipeOpPreprocTorchTrafoRgbToGrayscale} -\title{PipeOpPreprocTorchTrafoRgbToGrayscale} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Calls \code{\link[torchvision:transform_rgb_to_grayscale]{torchvision::transform_rgb_to_grayscale}}, -see there for more information on the parameters. -The preprocessing is applied row wise (no batch dimension). -} -\section{Parameters}{ -\tabular{llll}{ - Id \tab Type \tab Default \tab Levels \cr - stages \tab character \tab - \tab train, predict, both \cr - affect_columns \tab untyped \tab selector_all \tab \cr -} -} - diff --git a/man/PipeOpPreprocTorchTrafoScale.Rd b/man/PipeOpPreprocTorchTrafoScale.Rd deleted file mode 100644 index 0a3cac68..00000000 --- a/man/PipeOpPreprocTorchTrafoScale.Rd +++ /dev/null @@ -1,12 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/preprocess.R -\name{mlr_pipeops_preproc_torch.trafo_scale} -\alias{mlr_pipeops_preproc_torch.trafo_scale} -\alias{PipeOpPreprocTorchTrafoScale} -\title{PipeOpPreprocTorchTrafoNop} -\format{ -\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. -} -\description{ -Applies \code{(x - mean) / sd} to a tensor \code{x}. -} diff --git a/man/TorchCallback.Rd b/man/TorchCallback.Rd deleted file mode 100644 index 7c060eee..00000000 --- a/man/TorchCallback.Rd +++ /dev/null @@ -1,159 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TorchCallback.R -\name{TorchCallback} -\alias{TorchCallback} -\title{Torch Callback} -\description{ -This wraps a \code{\link{CallbackSet}} and annotates it with metadata, most importantly a \code{\link{ParamSet}}. -The callback is created for the given parameter values by calling the \verb{$generate()} method. - -This class is usually used to configure the callback of a torch learner, e.g. when constructing -a learner of in a \code{\link{ModelDescriptor}}. - -For a list of available callbacks, see \code{\link{mlr3torch_callbacks}}. -To conveniently retrieve a \code{\link{TorchCallback}}, use \code{\link[=t_clbk]{t_clbk()}}. -} -\section{Parameters}{ - -Defined by the constructor argument \code{param_set}. -If no parameter set is provided during construction, the parameter set is constructed by creating a parameter -for each argument of the wrapped loss function, where the parametes are then of type \code{\link{ParamUty}}. -} - -\examples{ -# Create a new torch callback from an existing callback set -torch_callback = TorchCallback$new(CallbackSetCheckpoint) -# The parameters are inferred -torch_callback$param_set - -# Retrieve a torch callback from the dictionary -torch_callback = t_clbk("checkpoint", - path = tempfile(), freq = 1 -) -torch_callback -torch_callback$label -torch_callback$id - -# open the help page of the wrapped callback set -# torch_callback$help() - -# Create the callback set -callback = torch_callback$generate() -callback -# is the same as -CallbackSetCheckpoint$new( - path = tempfile(), freq = 1 -) - -# Use in a learner -learner = lrn("regr.mlp", callbacks = t_clbk("checkpoint")) -# the parameters of the callback are added to the learner's parameter set -learner$param_set - -} -\seealso{ -Other Callback: -\code{\link{as_torch_callback}()}, -\code{\link{as_torch_callbacks}()}, -\code{\link{callback_set}()}, -\code{\link{mlr3torch_callbacks}}, -\code{\link{mlr_callback_set}}, -\code{\link{mlr_callback_set.checkpoint}}, -\code{\link{mlr_callback_set.progress}}, -\code{\link{mlr_context_torch}}, -\code{\link{t_clbk}()}, -\code{\link{torch_callback}()} - -Other Torch Descriptor: -\code{\link{TorchDescriptor}}, -\code{\link{TorchLoss}}, -\code{\link{TorchOptimizer}}, -\code{\link{as_torch_callbacks}()}, -\code{\link{as_torch_loss}()}, -\code{\link{as_torch_optimizer}()}, -\code{\link{mlr3torch_losses}}, -\code{\link{mlr3torch_optimizers}}, -\code{\link{t_clbk}()}, -\code{\link{t_loss}()}, -\code{\link{t_opt}()} -} -\concept{Callback} -\concept{Torch Descriptor} -\section{Super class}{ -\code{\link[mlr3torch:TorchDescriptor]{mlr3torch::TorchDescriptor}} -> \code{TorchCallback} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-TorchCallback-new}{\code{TorchCallback$new()}} -\item \href{#method-TorchCallback-clone}{\code{TorchCallback$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TorchCallback-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{TorchCallback$new( - callback_generator, - param_set = NULL, - id = NULL, - label = NULL, - packages = NULL, - man = NULL -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{callback_generator}}{(\code{R6ClassGenerator})\cr -The class generator for the callback that is being wrapped.} - -\item{\code{param_set}}{(\code{ParamSet} or \code{NULL})\cr -The parameter set. If \code{NULL} (default) it is inferred from \code{callback_generator}.} - -\item{\code{id}}{(\code{character(1)})\cr -The id for of the new object.} - -\item{\code{label}}{(\code{character(1)})\cr -Label for the new instance.} - -\item{\code{packages}}{(\code{character()})\cr -The R packages this object depends on.} - -\item{\code{man}}{(\code{character(1)})\cr -String in the format \verb{[pkg]::[topic]} pointing to a manual page for this object. -The referenced help package can be opened via method \verb{$help()}.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TorchCallback-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{TorchCallback$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/TorchDescriptor.Rd b/man/TorchDescriptor.Rd deleted file mode 100644 index aefa09f8..00000000 --- a/man/TorchDescriptor.Rd +++ /dev/null @@ -1,172 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TorchDescriptor.R -\name{TorchDescriptor} -\alias{TorchDescriptor} -\title{Base Class for Torch Descriptors} -\description{ -Abstract Base Class from which \code{\link{TorchLoss}}, \code{\link{TorchOptimizer}}, and \code{\link{TorchCallback}} inherit. -This class wraps a generator (R6Class Generator or the torch version of such a generator) and annotates it -with metadata such as a \code{\link{ParamSet}}, a label, an ID, packages, or a manual page. - -The parameters are the construction arguments of the wrapped generator and the parameter \verb{$values} are passed -to the generator when calling the public method \verb{$generate()}. -} -\section{Parameters}{ - -Defined by the constructor argument \code{param_set}. -} - -\seealso{ -Other Torch Descriptor: -\code{\link{TorchCallback}}, -\code{\link{TorchLoss}}, -\code{\link{TorchOptimizer}}, -\code{\link{as_torch_callbacks}()}, -\code{\link{as_torch_loss}()}, -\code{\link{as_torch_optimizer}()}, -\code{\link{mlr3torch_losses}}, -\code{\link{mlr3torch_optimizers}}, -\code{\link{t_clbk}()}, -\code{\link{t_loss}()}, -\code{\link{t_opt}()} -} -\concept{Torch Descriptor} -\section{Public fields}{ -\if{html}{\out{
}} -\describe{ -\item{\code{label}}{(\code{character(1)})\cr -Label for this object. -Can be used in tables, plot and text output instead of the ID.} - -\item{\code{param_set}}{(\link[paradox:ParamSet]{paradox::ParamSet})\cr -Set of hyperparameters.} - -\item{\code{packages}}{(\code{character(1)})\cr -Set of required packages. -These packages are loaded, but not attached.} - -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the object. -Used in tables, plot and text output.} - -\item{\code{generator}}{The wrapped generator that is described.} - -\item{\code{man}}{(\code{character(1)})\cr -String in the format \verb{[pkg]::[topic]} pointing to a manual page for this object.} -} -\if{html}{\out{
}} -} -\section{Active bindings}{ -\if{html}{\out{
}} -\describe{ -\item{\code{phash}}{(\code{character(1)})\cr -Hash (unique identifier) for this partial object, excluding some components -which are varied systematically (e.g. the parameter values).} -} -\if{html}{\out{
}} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-TorchDescriptor-new}{\code{TorchDescriptor$new()}} -\item \href{#method-TorchDescriptor-print}{\code{TorchDescriptor$print()}} -\item \href{#method-TorchDescriptor-generate}{\code{TorchDescriptor$generate()}} -\item \href{#method-TorchDescriptor-help}{\code{TorchDescriptor$help()}} -\item \href{#method-TorchDescriptor-clone}{\code{TorchDescriptor$clone()}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TorchDescriptor-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{TorchDescriptor$new( - generator, - id = NULL, - param_set = NULL, - packages = NULL, - label = NULL, - man = NULL -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{generator}}{The wrapped generator that is described.} - -\item{\code{id}}{(\code{character(1)})\cr -The id for of the new object.} - -\item{\code{param_set}}{(\code{paradox::ParamSet})\cr -The parameter set.} - -\item{\code{packages}}{(\code{character()})\cr -The R packages this object depends on.} - -\item{\code{label}}{(\code{character(1)})\cr -Label for the new instance.} - -\item{\code{man}}{(\code{character(1)})\cr -String in the format \verb{[pkg]::[topic]} pointing to a manual page for this object. -The referenced help package can be opened via method \verb{$help()}.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TorchDescriptor-print}{}}} -\subsection{Method \code{print()}}{ -Prints the object -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{TorchDescriptor$print(...)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{...}}{any} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TorchDescriptor-generate}{}}} -\subsection{Method \code{generate()}}{ -Calls the generator with the given parameter values. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{TorchDescriptor$generate()}\if{html}{\out{
}} -} - -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TorchDescriptor-help}{}}} -\subsection{Method \code{help()}}{ -Displays the help file of the wrapped object. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{TorchDescriptor$help()}\if{html}{\out{
}} -} - -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TorchDescriptor-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{TorchDescriptor$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/TorchIngressToken.Rd b/man/TorchIngressToken.Rd deleted file mode 100644 index 0e56dff4..00000000 --- a/man/TorchIngressToken.Rd +++ /dev/null @@ -1,68 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchIngress.R -\name{TorchIngressToken} -\alias{TorchIngressToken} -\title{Torch Ingress Token} -\usage{ -TorchIngressToken(features, batchgetter, shape) -} -\arguments{ -\item{features}{(\code{character})\cr -Features on which the batchgetter will operate.} - -\item{batchgetter}{(\code{function})\cr -Function with two arguments: \code{data} and \code{device}. This function is given -the output of \code{Task$data(rows = batch_indices, cols = features)} -and it should produce a tensor of shape \code{shape_out}.} - -\item{shape}{(\code{integer})\cr -Shape that \code{batchgetter} will produce. Batch-dimension should be included as \code{NA}.} -} -\value{ -\code{TorchIngressToken} object. -} -\description{ -This function creates an S3 class of class \code{"TorchIngressToken"}, which is an internal data structure. -It contains the (meta-)information of how a batch is generated from a \code{\link{Task}} and fed into an entry point -of the neural network. It is stored as the \code{ingress} field in a \code{\link{ModelDescriptor}}. -} -\examples{ -# Define a task for which we want to define an ingress token -task = tsk("iris") - -# We create an ingress token for two feature Sepal.Length and Petal.Length: -# We have to specify the features, the batchgetter and the shape -features = c("Sepal.Length", "Petal.Length") -# As a batchgetter we use batchgetter_num - -batch_dt = task$data(rows = 1:10, cols =features) -batch_dt -batch_tensor = batchgetter_num(batch_dt, "cpu") -batch_tensor - -# The shape is unknown in the first dimension (batch dimension) - -ingress_token = TorchIngressToken( - features = features, - batchgetter = batchgetter_num, - shape = c(NA, 2) -) -ingress_token - -} -\seealso{ -Other Graph Network: -\code{\link{ModelDescriptor}()}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{model_descriptor_to_learner}()}, -\code{\link{model_descriptor_to_module}()}, -\code{\link{model_descriptor_union}()}, -\code{\link{nn_graph}()} -} -\concept{Graph Network} diff --git a/man/TorchLoss.Rd b/man/TorchLoss.Rd deleted file mode 100644 index 5cd2baad..00000000 --- a/man/TorchLoss.Rd +++ /dev/null @@ -1,174 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TorchLoss.R -\name{TorchLoss} -\alias{TorchLoss} -\title{Torch Loss} -\description{ -This wraps a \code{torch::nn_loss} and annotates it with metadata, most importantly a \code{\link{ParamSet}}. -The loss function is created for the given parameter values by calling the \verb{$generate()} method. - -This class is usually used to configure the loss function of a torch learner, e.g. -when construcing a learner or in a \code{\link{ModelDescriptor}}. - -For a list of available losses, see \code{\link{mlr3torch_losses}}. -Items from this dictionary can be retrieved using \code{\link[=t_loss]{t_loss()}}. -} -\section{Parameters}{ - -Defined by the constructor argument \code{param_set}. -If no parameter set is provided during construction, the parameter set is constructed by creating a parameter -for each argument of the wrapped loss function, where the parametes are then of type \code{\link{ParamUty}}. -} - -\examples{ -# Create a new torch loss -torch_loss = TorchLoss$new(torch_loss = nn_mse_loss, task_types = "regr") -torch_loss -# the parameters are inferred -torch_loss$param_set - -# Retrieve a loss from the dictionary: -torch_loss = t_loss("mse", reduction = "mean") -# is the same as -torch_loss -torch_loss$param_set -torch_loss$label -torch_loss$task_types -torch_loss$id - -# Create the loss function -loss_fn = torch_loss$generate() -loss_fn -# Is the same as -nn_mse_loss(reduction = "mean") - -# open the help page of the wrapped loss function -# torch_loss$help() - -# Use in a learner -learner = lrn("regr.mlp", loss = t_loss("mse")) -# The parameters of the loss are added to the learner's parameter set -learner$param_set -} -\seealso{ -Other Torch Descriptor: -\code{\link{TorchCallback}}, -\code{\link{TorchDescriptor}}, -\code{\link{TorchOptimizer}}, -\code{\link{as_torch_callbacks}()}, -\code{\link{as_torch_loss}()}, -\code{\link{as_torch_optimizer}()}, -\code{\link{mlr3torch_losses}}, -\code{\link{mlr3torch_optimizers}}, -\code{\link{t_clbk}()}, -\code{\link{t_loss}()}, -\code{\link{t_opt}()} -} -\concept{Torch Descriptor} -\section{Super class}{ -\code{\link[mlr3torch:TorchDescriptor]{mlr3torch::TorchDescriptor}} -> \code{TorchLoss} -} -\section{Public fields}{ -\if{html}{\out{
}} -\describe{ -\item{\code{task_types}}{(\code{character()})\cr -The task types this loss supports.} -} -\if{html}{\out{
}} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-TorchLoss-new}{\code{TorchLoss$new()}} -\item \href{#method-TorchLoss-print}{\code{TorchLoss$print()}} -\item \href{#method-TorchLoss-clone}{\code{TorchLoss$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TorchLoss-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{TorchLoss$new( - torch_loss, - task_types, - param_set = NULL, - id = NULL, - label = NULL, - packages = NULL, - man = NULL -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{torch_loss}}{(\code{nn_loss})\cr -The loss module.} - -\item{\code{task_types}}{(\code{character()})\cr -The task types supported by this loss.} - -\item{\code{param_set}}{(\code{\link{ParamSet}} or \code{NULL})\cr -The parameter set. If \code{NULL} (default) it is inferred from \code{torch_loss}.} - -\item{\code{id}}{(\code{character(1)})\cr -The id for of the new object.} - -\item{\code{label}}{(\code{character(1)})\cr -Label for the new instance.} - -\item{\code{packages}}{(\code{character()})\cr -The R packages this object depends on.} - -\item{\code{man}}{(\code{character(1)})\cr -String in the format \verb{[pkg]::[topic]} pointing to a manual page for this object. -The referenced help package can be opened via method \verb{$help()}.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TorchLoss-print}{}}} -\subsection{Method \code{print()}}{ -Prints the object -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{TorchLoss$print(...)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{...}}{any} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TorchLoss-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{TorchLoss$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/TorchOptimizer.Rd b/man/TorchOptimizer.Rd deleted file mode 100644 index a17de14b..00000000 --- a/man/TorchOptimizer.Rd +++ /dev/null @@ -1,165 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TorchOptimizer.R -\name{TorchOptimizer} -\alias{TorchOptimizer} -\title{Torch Optimizer} -\description{ -This wraps a \code{torch::torch_optimizer_generator}a and annotates it with metadata, most importantly a \code{\link{ParamSet}}. -The optimizer is created for the given parameter values by calling the \verb{$generate()} method. - -This class is usually used to configure the optimizer of a torch learner, e.g. -when construcing a learner or in a \code{\link{ModelDescriptor}}. - -For a list of available optimizers, see \code{\link{mlr3torch_optimizers}}. -Items from this dictionary can be retrieved using \code{\link[=t_opt]{t_opt()}}. -} -\section{Parameters}{ - -Defined by the constructor argument \code{param_set}. -If no parameter set is provided during construction, the parameter set is constructed by creating a parameter -for each argument of the wrapped loss function, where the parametes are then of type \code{\link{ParamUty}}. -} - -\examples{ -# Create a new torch loss -torch_opt = TorchOptimizer$new(optim_adam, label = "adam") -torch_opt -# If the param set is not specified, parameters are inferred but are of class ParamUty -torch_opt$param_set - -# open the help page of the wrapped optimizer -# torch_opt$help() - -# Retrieve an optimizer from the dictionary -torch_opt = t_opt("sgd", lr = 0.1) -torch_opt -torch_opt$param_set -torch_opt$label -torch_opt$id - -# Create the optimizer for a network -net = nn_linear(10, 1) -opt = torch_opt$generate(net$parameters) - -# is the same as -optim_sgd(net$parameters, lr = 0.1) - -# Use in a learner -learner = lrn("regr.mlp", optimizer = t_opt("sgd")) -# The parameters of the optimizer are added to the learner's parameter set -learner$param_set -} -\seealso{ -Other Torch Descriptor: -\code{\link{TorchCallback}}, -\code{\link{TorchDescriptor}}, -\code{\link{TorchLoss}}, -\code{\link{as_torch_callbacks}()}, -\code{\link{as_torch_loss}()}, -\code{\link{as_torch_optimizer}()}, -\code{\link{mlr3torch_losses}}, -\code{\link{mlr3torch_optimizers}}, -\code{\link{t_clbk}()}, -\code{\link{t_loss}()}, -\code{\link{t_opt}()} -} -\concept{Torch Descriptor} -\section{Super class}{ -\code{\link[mlr3torch:TorchDescriptor]{mlr3torch::TorchDescriptor}} -> \code{TorchOptimizer} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-TorchOptimizer-new}{\code{TorchOptimizer$new()}} -\item \href{#method-TorchOptimizer-generate}{\code{TorchOptimizer$generate()}} -\item \href{#method-TorchOptimizer-clone}{\code{TorchOptimizer$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TorchOptimizer-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{TorchOptimizer$new( - torch_optimizer, - param_set = NULL, - id = NULL, - label = NULL, - packages = NULL, - man = NULL -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{torch_optimizer}}{(\code{torch_optimizer_generator})\cr -The torch optimizer.} - -\item{\code{param_set}}{(\code{ParamSet} or \code{NULL})\cr -The parameter set. If \code{NULL} (default) it is inferred from \code{torch_optimizer}.} - -\item{\code{id}}{(\code{character(1)})\cr -The id for of the new object.} - -\item{\code{label}}{(\code{character(1)})\cr -Label for the new instance.} - -\item{\code{packages}}{(\code{character()})\cr -The R packages this object depends on.} - -\item{\code{man}}{(\code{character(1)})\cr -String in the format \verb{[pkg]::[topic]} pointing to a manual page for this object. -The referenced help package can be opened via method \verb{$help()}.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TorchOptimizer-generate}{}}} -\subsection{Method \code{generate()}}{ -Instantiates the optimizer. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{TorchOptimizer$generate(params)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{params}}{(named \code{list()} of \code{\link{torch_tensor}}s)\cr -The parameters of the network.} -} -\if{html}{\out{
}} -} -\subsection{Returns}{ -\code{torch_optimizer} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-TorchOptimizer-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{TorchOptimizer$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/as_lazy_tensor.Rd b/man/as_lazy_tensor.Rd deleted file mode 100644 index 5452ab75..00000000 --- a/man/as_lazy_tensor.Rd +++ /dev/null @@ -1,18 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/lazy_tensor.R -\name{as_lazy_tensor} -\alias{as_lazy_tensor} -\title{Convert to lazy tensor} -\usage{ -as_lazy_tensor(x, ...) -} -\arguments{ -\item{x}{(any)\cr -Object to convert to a \code{\link{lazy_tensor}}} - -\item{...}{(any)\cr -Additional arguments passed to the method.} -} -\description{ -Convert a object to a \code{\link{lazy_tensor}}. -} diff --git a/man/as_torch_callback.Rd b/man/as_torch_callback.Rd deleted file mode 100644 index db5feeb8..00000000 --- a/man/as_torch_callback.Rd +++ /dev/null @@ -1,38 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TorchCallback.R -\name{as_torch_callback} -\alias{as_torch_callback} -\title{Convert to a TorchCallback} -\usage{ -as_torch_callback(x, clone = FALSE, ...) -} -\arguments{ -\item{x}{(any)\cr -Object to be converted.} - -\item{clone}{(\code{logical(1)})\cr -Whether to make a deep clone.} - -\item{...}{(any)\cr -Additional arguments} -} -\value{ -\code{\link{TorchCallback}}. -} -\description{ -Converts an object to a \code{\link{TorchCallback}}. -} -\seealso{ -Other Callback: -\code{\link{TorchCallback}}, -\code{\link{as_torch_callbacks}()}, -\code{\link{callback_set}()}, -\code{\link{mlr3torch_callbacks}}, -\code{\link{mlr_callback_set}}, -\code{\link{mlr_callback_set.checkpoint}}, -\code{\link{mlr_callback_set.progress}}, -\code{\link{mlr_context_torch}}, -\code{\link{t_clbk}()}, -\code{\link{torch_callback}()} -} -\concept{Callback} diff --git a/man/as_torch_callbacks.Rd b/man/as_torch_callbacks.Rd deleted file mode 100644 index 563a4251..00000000 --- a/man/as_torch_callbacks.Rd +++ /dev/null @@ -1,52 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TorchCallback.R -\name{as_torch_callbacks} -\alias{as_torch_callbacks} -\title{Convert to a list of Torch Callbacks} -\usage{ -as_torch_callbacks(x, clone, ...) -} -\arguments{ -\item{x}{(any)\cr -Object to convert.} - -\item{clone}{(\code{logical(1)})\cr -Whether to create a deep clone.} - -\item{...}{(any)\cr -Additional arguments.} -} -\value{ -\code{list()} of \code{\link{TorchCallback}}s -} -\description{ -Converts an object to a list of \code{\link{TorchCallback}}. -} -\seealso{ -Other Callback: -\code{\link{TorchCallback}}, -\code{\link{as_torch_callback}()}, -\code{\link{callback_set}()}, -\code{\link{mlr3torch_callbacks}}, -\code{\link{mlr_callback_set}}, -\code{\link{mlr_callback_set.checkpoint}}, -\code{\link{mlr_callback_set.progress}}, -\code{\link{mlr_context_torch}}, -\code{\link{t_clbk}()}, -\code{\link{torch_callback}()} - -Other Torch Descriptor: -\code{\link{TorchCallback}}, -\code{\link{TorchDescriptor}}, -\code{\link{TorchLoss}}, -\code{\link{TorchOptimizer}}, -\code{\link{as_torch_loss}()}, -\code{\link{as_torch_optimizer}()}, -\code{\link{mlr3torch_losses}}, -\code{\link{mlr3torch_optimizers}}, -\code{\link{t_clbk}()}, -\code{\link{t_loss}()}, -\code{\link{t_opt}()} -} -\concept{Callback} -\concept{Torch Descriptor} diff --git a/man/as_torch_loss.Rd b/man/as_torch_loss.Rd deleted file mode 100644 index 42317b61..00000000 --- a/man/as_torch_loss.Rd +++ /dev/null @@ -1,40 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TorchLoss.R -\name{as_torch_loss} -\alias{as_torch_loss} -\title{Convert to TorchLoss} -\usage{ -as_torch_loss(x, clone = FALSE, ...) -} -\arguments{ -\item{x}{(any)\cr -Object to convert to a \code{\link{TorchLoss}}.} - -\item{clone}{(\code{logical(1)})\cr -Whether to make a deep clone.} - -\item{...}{(any)\cr -Additional arguments. -Currently used to pass additional constructor arguments to \code{\link{TorchLoss}} for objects of type \code{nn_loss}.} -} -\value{ -\code{\link{TorchLoss}}. -} -\description{ -Converts an object to a \code{\link{TorchLoss}}. -} -\seealso{ -Other Torch Descriptor: -\code{\link{TorchCallback}}, -\code{\link{TorchDescriptor}}, -\code{\link{TorchLoss}}, -\code{\link{TorchOptimizer}}, -\code{\link{as_torch_callbacks}()}, -\code{\link{as_torch_optimizer}()}, -\code{\link{mlr3torch_losses}}, -\code{\link{mlr3torch_optimizers}}, -\code{\link{t_clbk}()}, -\code{\link{t_loss}()}, -\code{\link{t_opt}()} -} -\concept{Torch Descriptor} diff --git a/man/as_torch_optimizer.Rd b/man/as_torch_optimizer.Rd deleted file mode 100644 index 2722bea0..00000000 --- a/man/as_torch_optimizer.Rd +++ /dev/null @@ -1,41 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TorchOptimizer.R -\name{as_torch_optimizer} -\alias{as_torch_optimizer} -\title{Convert to TorchOptimizer} -\usage{ -as_torch_optimizer(x, clone = FALSE, ...) -} -\arguments{ -\item{x}{(any)\cr -Object to convert to a \code{\link{TorchOptimizer}}.} - -\item{clone}{(\code{logical(1)})\cr -Whether to make a deep clone. Default is \code{FALSE}.} - -\item{...}{(any)\cr -Additional arguments. -Currently used to pass additional constructor arguments to \code{\link{TorchOptimizer}} for objects of type -\code{torch_optimizer_generator}.} -} -\value{ -\code{\link{TorchOptimizer}} -} -\description{ -Converts an object to a \code{\link{TorchOptimizer}}. -} -\seealso{ -Other Torch Descriptor: -\code{\link{TorchCallback}}, -\code{\link{TorchDescriptor}}, -\code{\link{TorchLoss}}, -\code{\link{TorchOptimizer}}, -\code{\link{as_torch_callbacks}()}, -\code{\link{as_torch_loss}()}, -\code{\link{mlr3torch_losses}}, -\code{\link{mlr3torch_optimizers}}, -\code{\link{t_clbk}()}, -\code{\link{t_loss}()}, -\code{\link{t_opt}()} -} -\concept{Torch Descriptor} diff --git a/man/assert_lazy_tensor.Rd b/man/assert_lazy_tensor.Rd deleted file mode 100644 index 77945f09..00000000 --- a/man/assert_lazy_tensor.Rd +++ /dev/null @@ -1,15 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/lazy_tensor.R -\name{assert_lazy_tensor} -\alias{assert_lazy_tensor} -\title{Assert Lazy Tensor} -\usage{ -assert_lazy_tensor(x) -} -\arguments{ -\item{x}{(any)\cr -Object to check.} -} -\description{ -Asserts whether something is a lazy tensor. -} diff --git a/man/auto_device.Rd b/man/auto_device.Rd deleted file mode 100644 index cdf002a5..00000000 --- a/man/auto_device.Rd +++ /dev/null @@ -1,15 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R -\name{auto_device} -\alias{auto_device} -\title{Auto Device} -\usage{ -auto_device(device = NULL) -} -\arguments{ -\item{device}{(\code{character(1)})\cr -The device. If not \code{NULL}, is returned as is.} -} -\description{ -First tries cuda, then mp, then cpu. -} diff --git a/man/batchgetter_categ.Rd b/man/batchgetter_categ.Rd deleted file mode 100644 index 7a721561..00000000 --- a/man/batchgetter_categ.Rd +++ /dev/null @@ -1,22 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/task_dataset.R -\name{batchgetter_categ} -\alias{batchgetter_categ} -\title{Batchgetter for Categorical data} -\usage{ -batchgetter_categ(data, device, ...) -} -\arguments{ -\item{data}{(\code{data.table})\cr -\code{data.table} to be converted to a \code{tensor}.} - -\item{device}{(\code{character(1)})\cr -The device.} - -\item{...}{(any)\cr -Unused.} -} -\description{ -Converts a data frame of categorical data into a long tensor by converting the data to integers. -No input checks are performed. -} diff --git a/man/batchgetter_num.Rd b/man/batchgetter_num.Rd deleted file mode 100644 index 4b8ffa84..00000000 --- a/man/batchgetter_num.Rd +++ /dev/null @@ -1,22 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/task_dataset.R -\name{batchgetter_num} -\alias{batchgetter_num} -\title{Batchgetter for Numeric Data} -\usage{ -batchgetter_num(data, device, ...) -} -\arguments{ -\item{data}{(\code{data.table()})\cr -\code{data.table} to be converted to a \code{tensor}.} - -\item{device}{(\code{character(1)})\cr -The device on which the tensor should be created.} - -\item{...}{(any)\cr -Unused.} -} -\description{ -Converts a data frame of numeric data into a float tensor by calling \code{as.matrix()}. -No input checks are performed -} diff --git a/man/callback_set.Rd b/man/callback_set.Rd deleted file mode 100644 index 60bd5db7..00000000 --- a/man/callback_set.Rd +++ /dev/null @@ -1,77 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/CallbackSet.R -\name{callback_set} -\alias{callback_set} -\title{Create a Set of Callbacks for Torch} -\usage{ -callback_set( - classname, - on_begin = NULL, - on_end = NULL, - on_epoch_begin = NULL, - on_before_valid = NULL, - on_epoch_end = NULL, - on_batch_begin = NULL, - on_batch_end = NULL, - on_after_backward = NULL, - on_batch_valid_begin = NULL, - on_batch_valid_end = NULL, - initialize = NULL, - public = NULL, - private = NULL, - active = NULL, - parent_env = parent.frame(), - inherit = CallbackSet, - lock_objects = FALSE -) -} -\arguments{ -\item{classname}{(\code{character(1)})\cr -The class name.} - -\item{on_begin, on_end, on_epoch_begin, on_before_valid, on_epoch_end, on_batch_begin, on_batch_end, on_after_backward, on_batch_valid_begin, on_batch_valid_end}{(\code{function})\cr -Function to execute at the given stage, see section \emph{Stages}.} - -\item{initialize}{(\verb{function()})\cr -The initialization method of the callback.} - -\item{public, private, active}{(\code{list()})\cr -Additional public, private, and active fields to add to the callback.} - -\item{parent_env}{(\code{environment()})\cr -The parent environment for the \code{\link{R6Class}}.} - -\item{inherit}{(\code{R6ClassGenerator})\cr -From which class to inherit. -This class must either be \code{\link{CallbackSet}} (default) or inherit from it.} - -\item{lock_objects}{(\code{logical(1)})\cr -Whether to lock the objects of the resulting \code{\link{R6Class}}. -If \code{FALSE} (default), values can be freely assigned to \code{self} without declaring them in the -class definition.} -} -\value{ -\code{\link{CallbackSet}} -} -\description{ -Creates an \code{R6ClassGenerator} inheriting from \code{\link{CallbackSet}}. -Additionally performs checks such as that the stages are not accidentally misspelled. -To create a \code{\link{TorchCallback}} use \code{\link[=torch_callback]{torch_callback()}}. - -In order for the resulting class to be cloneable, the private method \verb{$deep_clone()} must be -provided. -} -\seealso{ -Other Callback: -\code{\link{TorchCallback}}, -\code{\link{as_torch_callback}()}, -\code{\link{as_torch_callbacks}()}, -\code{\link{mlr3torch_callbacks}}, -\code{\link{mlr_callback_set}}, -\code{\link{mlr_callback_set.checkpoint}}, -\code{\link{mlr_callback_set.progress}}, -\code{\link{mlr_context_torch}}, -\code{\link{t_clbk}()}, -\code{\link{torch_callback}()} -} -\concept{Callback} diff --git a/man/equals-.lazy_tensor.Rd b/man/equals-.lazy_tensor.Rd deleted file mode 100644 index 9be38b0c..00000000 --- a/man/equals-.lazy_tensor.Rd +++ /dev/null @@ -1,20 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/lazy_tensor.R -\name{==.lazy_tensor} -\alias{==.lazy_tensor} -\title{Compare lazy tensors} -\usage{ -\method{==}{lazy_tensor}(x, y) -} -\arguments{ -\item{x, y}{(\code{\link{lazy_tensor}})\cr -Values to compare.} -} -\description{ -Compares lazy tensors using their indices and the data descriptor's hash. -This means that if two \code{\link{lazy_tensor}}s: -\itemize{ -\item are equal: they will mateterialize to the same tensors. -\item are unequal: they might materialize to the same tensors. -} -} diff --git a/man/figures/lifecycle-archived.svg b/man/figures/lifecycle-archived.svg deleted file mode 100644 index 48f72a6f..00000000 --- a/man/figures/lifecycle-archived.svg +++ /dev/null @@ -1 +0,0 @@ - lifecyclelifecyclearchivedarchived \ No newline at end of file diff --git a/man/figures/lifecycle-defunct.svg b/man/figures/lifecycle-defunct.svg deleted file mode 100644 index 01452e5f..00000000 --- a/man/figures/lifecycle-defunct.svg +++ /dev/null @@ -1 +0,0 @@ -lifecyclelifecycledefunctdefunct \ No newline at end of file diff --git a/man/figures/lifecycle-deprecated.svg b/man/figures/lifecycle-deprecated.svg deleted file mode 100644 index 4baaee01..00000000 --- a/man/figures/lifecycle-deprecated.svg +++ /dev/null @@ -1 +0,0 @@ -lifecyclelifecycledeprecateddeprecated \ No newline at end of file diff --git a/man/figures/lifecycle-experimental.svg b/man/figures/lifecycle-experimental.svg deleted file mode 100644 index d1d060e9..00000000 --- a/man/figures/lifecycle-experimental.svg +++ /dev/null @@ -1 +0,0 @@ -lifecyclelifecycleexperimentalexperimental \ No newline at end of file diff --git a/man/figures/lifecycle-maturing.svg b/man/figures/lifecycle-maturing.svg deleted file mode 100644 index df713101..00000000 --- a/man/figures/lifecycle-maturing.svg +++ /dev/null @@ -1 +0,0 @@ -lifecyclelifecyclematuringmaturing \ No newline at end of file diff --git a/man/figures/lifecycle-questioning.svg b/man/figures/lifecycle-questioning.svg deleted file mode 100644 index 08ee0c90..00000000 --- a/man/figures/lifecycle-questioning.svg +++ /dev/null @@ -1 +0,0 @@ -lifecyclelifecyclequestioningquestioning \ No newline at end of file diff --git a/man/figures/lifecycle-stable.svg b/man/figures/lifecycle-stable.svg deleted file mode 100644 index e015dc81..00000000 --- a/man/figures/lifecycle-stable.svg +++ /dev/null @@ -1 +0,0 @@ -lifecyclelifecyclestablestable \ No newline at end of file diff --git a/man/figures/lifecycle-superseded.svg b/man/figures/lifecycle-superseded.svg deleted file mode 100644 index 75f24f55..00000000 --- a/man/figures/lifecycle-superseded.svg +++ /dev/null @@ -1 +0,0 @@ - lifecyclelifecyclesupersededsuperseded \ No newline at end of file diff --git a/man/figures/logo.png b/man/figures/logo.png deleted file mode 100644 index b786c1123a0ec72443f97365cd225fb10c261668..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 316274 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�noZ%R&$7Qm^w9_`HSSmkZ{C{nXzY^ zZM{B=oVU~O(PWajU9VSumNYLny!Mk(l$FbR?zbbi!0KL%D}Sw!8f|s=vY^@)7Fxp1 z@JbIkC-dGoB~p_z#wl~*;cd7v!Sx@^7#msCP-_7G+DJ{p^Kmk6<6rY;JxRAU-eyB- zJ9UZr*XDBIVV^qQjOTeZiFELaA@G56+_mQ+ov;n&W83ym$bz1uD7`2bm)H!i*}`b^-8foWYq+8Ps_WYh zSLbj#rZ^|BcTG8V>i*&2D>SdbqFcS<|A{b&xoS(L1cvGXT`t_yN|cODYr`fOkYm=9 z+w=wvYERp_FAXjI3_(#J?(VYj!KuGmq9_X&I54J*6+eUTu?%ou>f9dJt?$m7Fma+G zwrP&OAYMxo`nZ9!0rUZC*5+C=Y)1G7F}?TDJ1j=&;9=Khm-p+KCEYzV)n;0PRvN zpaEOc9?aGwXP{wNB6iG#HTq#e~jPC5UvaJH|q#b_2^5l z*~(N(y1K+=Tj?#XsZyJ)u6^BE_)?32UjzIsb?Hr*O$`O7jhXl4Qe}1Zvl+7uygu?5 z!4Hn!qy4AfUD$nis}~XfVfa` zuhVlG_;>2D591BI&dlm1Rv{~^{;vg~|7Th~nomo1GNVe`1YPI$v$p1p-)jxcZmvP( zE(=Rzb%&_jyh9s8eU4tZpmT8L$7YfOrShakCC4uN_Izg*J{HpbgGTurR#R^P*s^ub z_%mnE(&6nsxZlo&d(z3w*hDkTPTRO;`vIGslAVkne)Y~_>h;-|gTr2Lc$GOmxlqeu zz8;-*5E_Z>n>SlPq*>sVB|x$~BG95GlHrZ&LEv`k!_}poC=c&jiMH`6aJzy6tv2Z?k6Ec^v{aF-ktr^37Y+9Re{nZJ`}R1RYiT3uZY$R|-9IhH^I^TwU9Y%%2Ab zN2MV|&w~dp0xQ-RC6a-!qX8YLsrc3R_NlvP8{f5PwoWfG(P-n${ev$~-WxF9C~86H z39YCxjbFEaI{pPH9|u98;K%2ex}y`qNplTTFdU1@valXAX&t-t=&@8D#)!yFs|}%V z0Ml~lK`J3)WEzt(^ z>671NUjM$0uD{b`#d_t%mKGM^><$hN56&zwWLkPH93LYREeL13%)B+FA#{ixLA|#% zARsi`rI4wmmiF?K?l-9s!wNF~$!y@aS3g`So0(bB;$RPBl=RFlD{H5aGd6Y#I{qyy ze;FonDxbNQOtkK}eMn;DgwUn_uy##-rj3L-`jy=-V)br=XsaBe6hf}aFv9Ye%y-l9>;?+T0 z^^|-PHqUArIJ973R_vwFSGQoGvZ%eQkUPpdLlY%T6PQvJk;09>7@Xd({@jV|AjTDR zgaEk9Vu67Otf-|MD69(%Jb{W&8qNj{8VDX(-Py)B0qF3(y=R%V!?r$oappH8i_j)) zampjg8f`QH4ej#!)5cS(p|6gM4hx_{dIP$!#x##q4}zTl=0u=Q(HlJYi5z9^0YZ~| z!TOeS2!x~K4K(Y6K`Skm#;d9SY?9ewg?l(dz5`nC(>?+>3xrsY2>>rG zt}R-phe*UGDdpI)7ju)0{+W5grX)J2pQ5$XMB$3@j8hd&M{*%w{W4XwIv^p)NR~$* zOG^WFhrlZo|63XZS;2{jGLJF_53I(hN~o{_4#j_(3jMeoe6wYASq0;ZVA|lHR({NE z1}3({@7Yd>?8wM*`!A*IDQ#_=`Ox08XpB+RvoD$TfxF1S&`_)d&`3AncJqK_>Zqxz zPN-bUKmWXuug>G>IQD{}!O0weI+%cLTHI6+SeV_R-FLbnB9?B%8f`oZ{Nwa>60&v6J1d>$4cb+IsiL zY?9X-R}^VtRgA{X4H28om@zWjEU21WZg8pSoDl0ZUBB)|ptZGQRja7bS1kqgLSgsy z-Kkqr^m8JXfo@Csr5?^lg7)tyE-#wEu~I}~8J}`bQ&SW9#>wacaN61RCH#JrHyrr4 zKWgI5o#>pA)bamMbb|%iy2P;o-R8mYJ8BN&=qIuuG6ARW^nz3A9_}1Vz&j%1@+|)Y07%no#1-n|@V?BWY6_ryOWR43##F z95*O0FV7vK_to9RR-)99hv+J=?cvGzxKkGboRkEzS1z`*!Nh!3(tJ~3y1V*$C zn7$!&kFnhP%Ho_c*!Bx(1&zhbTO$xYbk&zn&c2b#H0s`cnYfDAMFIXJdugt$+_A#` z&{fR*55>e-6|5UKwZoU1{#4y0727nDg-=4Cp_*Y$U;wR{Q!I2P5P#TXJ!>K~)iUty z)R|Y5PtSdaQ6Ny4&JVKnD4q}Li*|&AUiVm8ZbD~tV!3=IL^EVnb^lOuap(}zm2|i_ z!P(h>5ljx-_R|S=;dxk=upgjXqVtL9d#wrPS# z4$cd`<|Z99WSSflk)yN(E`nCa(2g)IqML9i5_no}=8PyQk zWi4&ArQaaF1%>2~x%rpjg>AJfO_Ul^$IS|%gsYoG8^(a+K=84qPgZ_vactVfjfkm; zsm(LyJ-G^H)9I$Fp@G-CuQ#GX_vipYL0q^aCKKeHe(&kCXFVAVov?D=Wn=AThzF?llHUd-=7iLwvuBYO}A{@_Uu)twKW?!l-13;QnZPMrDS1% zQ!BWY>(`sPU)_`qq9zTr6iA#@uL6efu7!wf`8ZX zyC|~mscuLZL{$a8c4qa@b8)pOULN!rhik9p()T8wpRb_(JgZO`L=-6}ByKJFM8{RR zw!J~pMEV~tX*M_iv!0wa%PXu3pLZE40Y0gGbZqKf5p#iscS^*)7aP>0qrD*8*Z*v*b zBcDkHIk)6Ov#9IO1f^XfRfU-sDT$>mc{0$)DQG~5Vk$0AYI@LtSm?X02aLg@zmo?8 zos+lwO}WGW9hJh25T|DzD5@x%BI1txN^|XY+BM~7?0F&14b;%j?j%^7#~&rIacm%oYBe4^iu#n{-57%5LSr_xAM!ErGC~Zv}3>@Q8#UN z`p)~IxGS&nut6u8 z?ig5Uo6~prN5R-zFbt_^G-lTtYI!%BIOz8?tG=5{V=a0y5YUJS8)R2h9}cnfhx1Ew zn&3ImNRTE3A9R57yn!=jkV157ZLRMPLEeV?f3#x-$6yP1VY&4)8xWk2Ck#X;iyBqAG14+XWM;yK949-G3s2O%e_4+ljU!kaSaB=ZSb53!Nou0XR{-Q;~=f<2v5+>6y zsJmx;tt_S3g_``zD4_rZGTUDNNypcJQnB>e)UL1U;JP2Zx!&;lseZ2=@#ktw{9fue z09LFC{16J$;RPq`{4X9D{IuO!@Gk}nra4w@)*pse>92C@IxV0 zDYFDOeqc`0gyfDbJR?Fwhv0sr7ghCFKXo&c--9(Sr#;kBn>Qme(r1AqwuZ~j;%VO4 zpKE>BqiSzEbu(pdi3nnWbml`yQ)P=peR`Of*}crhOWV->N= zc*~O+wDPfs4#C+H5e}@b^}K$5?;9&>Ty<@2Hx-IXYGOIbz5dd7@HaYcxfF`B%5b;C7vt}rsSj)jbg7gd}&{sdZ! zhMbw6$tid&Tw$*1){E(evtY@HzqV;GOIss10tJ7NRI+c-Ds8DSM#YON67Ou0jxIPx z$gz}n95{h;gQzIZ)w!St_%l33b^{qw-^@HbbwrBc{OKKc-cWDX&Uv{1z;efe_X2rCnboVP9|YV%KZg9yHVv9n+81kw(+iAG9wD4EJ2&3Z7wR^j zQ32b7zA%zQ?d{br{i^kryum9{SR)!BnQ#)F+Np={o(9qV2FmT;j0M#RctBx2xP3u9 zP%0B?6@hM|`G0b9tryRN?~Yu(t4^H=F5*nwAf_bDwWjY3g(4sAKMsR4bzR+Vo(F8F z-tp)onXF^C%`cxnFQv?Q(S7@f%WPagg|hYic&aS678pn=e;o)r4=o`@K^_W%d=Nw; zAU}WR-2{gRxc-8s%W-?vLkel_eM|xnqMBkBI}%wSNG_HTC#Wq2ga_;MlR%U-jOvdR zzQc(eJ5^@kkTzURyfzJY-c2Md(bVY4DYo=W9hOx0vxd6G&UR5T=Yfe{vCit>(Qw6? zh0m3-gYrmY_(d3FBcrBlb6R3E!g|(pidty~#rac^ir=)nz*~fE!`JgH)g4w{mFy$@ z)G{<)qJT3*{!jI5IAT+l%z{&tk-GZR|EfRCLbP|tG4bdH7I9%{8@H1SPh)zaPh*xElLO$^` zEe@~fnPe>b*U#_6S`Qa@9^f3I*+8ORNF5ZQ4IFoO21ic=Dkz5nhFxe)sqt}TZH~zB z*&laN8BF0CS7Cm~uV!8Zs;3dE$8x7x-h+RAHG~J~REXsmCa6*X)OYNzMVcG=2!z%U-c7( z93{!KdOTI$Vd^SV%B~zvE@!n~WGyPHbLX^?eO`fu*wi85M}B@4VN$BNqzq0fA`sC< zOJPNU8wjgXoZd}d2vgCyl!t=ITpNo{)D$tFZ5mk{1bhwJZ!UQgE*&vdnEb780y?Zq zw(sJz?;lIT15!Y{k1IFf8MATRYjb@Zr|8=5bE{ z8(%{H*o6NWsf|=`NT5a{IF^WHYc%}=P7@H30o9KNrM@-^a%#)N!q!eC#LOAl-WS$Q{O1V(dphnO6O6v>^t>nS zQLyqHhruXuuT?-M_`g#S-w(@t&RG^XHEAau+!{uJ+>m*K!mVRwXxg&UCc=QzUo4PJ zyAa5*DH0=Lv+2W5)LLg!^0I?W20)fKX<>sm`K7OA&2mVRR1R%-CVcGTd~a-qbK(M_&2pn+K3RaI3%chsjBRU@T_aC>6+0%#1D z;&Sl?NDjoO$P&j~RbN-Ly~{=fF_-aq*}P+i(d#{o7a;{bH|_n9g^L%j*He-)An5m$ zd+p%uXpy-ujE6EQQF{uBk;LkK{g;k)JT(SHfo>DZJ_B8COmH?z447bR8d)hbnDh|! zGm5wF-MjP4nUD*8(+S8VVVVqVVdY-=C9_VK$PS7qS}$6Ghq_*SSmNfMy2=)nVmyKIbHk}zsg+>YzBB={meo7^MvI`lr^i#6&+YHd|C<28E# zE1=F}1L}S~x^6!XowqQiRJNO|4=Ar&gH4!0_wK6ow4{yo-T8n$g0Dco z`Y9Kdse_Wj8@y0;|BbO2gsk8m3+V^9L6bYMX!l7-?4Xd4Pt7r3{W-Yt&>=*4nQ6g( z$fhWME1C>yPnl~A+f#Fwx-2YmP_0eD_ht%s9kixSP^Euu*ZKP=f&-=O{9iw0yVK+p z%;?dvt%;0m$w8kL667=)iZPc;*kSy5!^9G3QtG4U4s$u>YZ0@|n4!n{lucwV08BZF564Ak8{qAI7C8Y9JZ@Uw7E@$eBB)@pAmv{3bqb_8<|f+$pQU_x(gs+O!H@+Ke!?oD zf`~OT4+YoScFUV)4z0HwI1qv8VN}r{ia*l#zQ@sa7~xIPq?P(4pd}HDA`Tj??R*f4 zC{pS};|>nur2p6pb|>y%!C37xIS91@+R3r4Q5%Is0Q&PUs!u@qc+ z&YZ(>wHzq=IyKIE5P|T+cttcQ{AV(+iHM}5t}UX2`l%Lv93|rt8~UY6{z5e3V0+{3 z^6QZl%AmUdJbYf*dG99H&*qbjw>*ZBCU5J?r1-BME57LJPB{A$>x09ccH4H^?^j^c zIcUugB|W{34Yn9eQ5&u{d}!&2p?ZGZvs+e-vbwXPM?q^fwe|Mhb=P*>Y-OVtR6WFh zoYCysZ$Gp9eoLHqb4*d(yZf#t_t(7~@Yk(>HuU@S?$p7bFf}+*Kqi-pyo9pwRic}f zlD?OlR#VEIWgnk4BYWL-eRlNNu@OY^3l}fC&7M8Hd7Y?6pPHlZ7SaZ+l@kflw>t(tkg zRT?QODvEMf>fTqU41?5KU`#K}ziH2&vZM*gC2eCUBUw3E$Pqwqb1|3f3feqvlZJ87 z=CKoq6ug-kg5GuMBHp#YLF(Y=a8d=AJ_o5;^~quVI(xPm>q)v;bDxTtANb(M?EM}i z>2;;nXI`Qyv&&u`kn}6!oynbTdG+d5T`jloNeKyA)ER|E_f!;^NT5#B-(sVtqcdjm z2v1uUNeHgE@_R)FS<>;X*05p2B+MgFvK5{@e8(%0IijgT*W@@`SwCpAb5C>g;Q07XIM&8~&RGct z4fLYkx^?4KtA46RZ2mC~IXQS#5US?Hi#Cs~O*G5Nc{htQYG{rFV|+T$oe%z5-3p2^ z_~=oS@Q4XrT4Nk27GMCP)+_Rsp2SoU7)z06K1{8yj=p|SwGV-_ z^5aJ<%pG|aGSPrC4&9gl8mE7@)wlk$OSF~J>(-F9!t6_5fTb#vy;^ZojK=HYgzl8R@=>Ci2U0W+7^&L8KVq41cn2K1-4OY=obO=Y7 z_WirU8lEP8L2H<(SUkfoNUdOni;Ig4l`63Jaw8_516Kdg5-^s*`tuXgjP>LGIuxX= zA16hp8-qhqKLeGp9>{!N$tF_2R=ak0auj%1<~Rk(kg=PaKI+iBmLuXFWiknC7*Sd4 zsVP}njDj|)Y~Ptlkznov-V_c^s?&}zX26G z{h2r@fA}!&%h>%QjF-Sc0daTG2rMk6bmIK?H|@nsn5q?wp`N;^X7LE-J>h{V<5Mqh z9n9k|x%v90RG2o?zo^v7Nl9OKM6|usEV3w)I-zN>+YC21*;Oq&nulXoq5oUC? zbUA|4aHrvrug7w&{ovIqCtNm>W*?nd(1@csfByVKW=*YZj?}-XVXRdLwQokN!4l^t zSh@-v$QDDU##|Njc;os$zP{PzRWkN~;ci+|Lzf-HDWQ3uc&0StIu~s`xgW)n%(}`n zw3G3KkbSX?TG1eyvKJWzz4M+zO_X}H^+JZ=t$hFer@rRqLSgVh38-A=_!UV@oF-2W zqx}{v(0bLXi$!^?KNGUe&CPA<;ZYmato)4`AUkvB3|pm}a2DWvWp0gsP%@0F>tGb* zXE7>4&8lcBQR~;w4*~A@)36zLEgKG*EEmd<%vvy>5Nc(ql50v#9;_fgD?B{hOZSLl zA}bgoC~z$-Epr|{+PBrXV$Ez>hgBxp%3s(FdR1Qz@Mc`Zkn%`lLt}P2y^=uIQHL`Q zcnAAuz7h*v-CE0b?b=m+t#VH_Y0ezctG92*JI06e;AqrDu>e3Ad-9}Xh5PaW?M16a z9}$hBsCtr`m5rjiR#RS+3;^TSVo$rsyJOm59lNn9Ck?jP6uW6y`J2{%(Fs&_=qNUD z&ts{?v6~c!PbnK2UBU9#H^fFsKQ6?(w%6ka4?;0CNXwYQJf!4X#1o8@al-AwVto%e ziOYt}9?1G*v^>t=U0Bx%?viSfT(x5omT;2mdGGL0Zr|w2Qy`hGqudl!aC5_$EK%i(mb!Ba!AkZ7*uV)&0as~^j?04=%J|$ zhLL92nJQhqC>t2?s_qoUvpj;6BG8S`*rbGH&jmFE``h{XYr*|~{_;YEy&gP<>a-ju zI_$P4e0RY#TNY2C2*!Nr8uLk3(YIgyAS)1-Y{rfq0nHsU@NT}-_Vd)W7~-TQP2b4b z`t|EerdTBK$6g&eZyyD*u#wj5%(-(p1qEBT8f(v-q=_0zmdE~kaBw8E8flTw=Uc#m zWaA1U19nMSMnP)bO#Ai?K~TeCVwdeY&~(bxr%**`2nuuEq z7Mx@bzJy4PQ`6E4mn`FO`|I=OzJC8c45$XVRjhm1#*Jdl!{bzGKR|2cpv=IScgs;r z3Z+KJE&8m@HXXe>+$f!oa(xYHR=_<`?Owb%kU@}hdFcR6sbn373A7m ztye3UL$@#6*wEAr`F0+-!SA%!g7gq$8V{A5-l!{@$EL~ z7@Qj1Zb<)+kF=CY_`Tilay`pbMMp=cQbt0V;ckrKEvuE7QmF)bFGI$W?@^pOJ+J!N z^;W=TSy!(%#k1XatmPE^g9J71GxvEQ`#$ss51w9rYaEuROw?=jo}kQ6yKbNOB?2OZS-Gc)I;3FRI6WRu9d2LGsR1X(^} zQJ;$SzaV9v#_ya~d-FR7XojzEIO5Yosi|sI_}cSQ;vExN!Mq7=9t*bG()vn$>Y=)0 zw!`%4k)o3&zspqm)#g=vwg(TiMCie*c>3<$kG;<#!oyoY9B$dX`B2plf-VBZEH*Ng zzIvrZqUG?PbFS;KV>U?>(ltn^B*5O3b7Q~bF(&dLYRSW22rlQ;up)*I&f&|Gni7s5 zm)&q>Wo0ww&1(s4Ty$WIT0wUy%{;gBG^OAbLrj{uY>MNTFGHk+2B<#$xUoF3E0o&A zBeKg-#LWPRH~#*6Pe$75)YL;>Z7#SRnlnk0&JHu&4wV@9>h5L?wD!P($W%?1YDv#DA>j1D$O&?mRnAqJb4$}%4+)k{d}Rs0UlB=0nF_E>xLJW z?H55~{h;LFIvq%c0E>TlPh34B`~78q_S`XBTvEV7OjR0<9zA;3u3gn{ytmJuM5i$z z;FpddHsaQ`Z{N|XwA|A9Pr*r%G@*j^Md-=O|v@ZNKlu#}e_aoKwnxrOD~xZ1ol` ztPB_G4-2mT`^y$iS1X#dObA3?EFqNnvC3cd7;Tt2VdRKnyMF1rtvB_LtV}t+A z4@3Cgz|N(7EBS%MrR1$DB->@IjT2!aa8csVUuF}OB@{KxtRTqO{@v-CFu|Gjl94|fgm z)S`1E2`H`4nYJKhBW2|IB`q-99?DlE^gT$r1<%-$+XrH+#Rc{}uf=gNlH))mrpiJi zAc>v3IAfCLfddB!Xho{rK|2Q`dW5JhpPrQrU*$*U4wNE8A+-l@^yH*#0#KXS`SL57EB7W{U_B#=9|O{j^RC) zpL!;1-}=txHLRqBVW(6wv%KVaqdO*bTs)~4j2CpIJfOnf5{Y6h*E1To8=2vw06l*h2$jO!o8tjBx5gEwzm zFUw!*N$cw{XW0J0d$9RCwXyd&OSn6O$(@ za5{*1_++=od?q0|+51jIv&xw_(&!j+^YV_|v<;r_K1mZUM#gAFnL~RY{&I#^Q}#Z| z)*nuDvhmI}ZJVWwL;*i%HpR^=)CsWezSGdsQkx2J_+E`QS#@=;-AqhUeIE8go)9~E zda?+wA#-T6LikC}ow8Tkv7J@iPKFE_a(>zozQXAv(a{Y!+9K!UD=r(*e%gu(Gt4P; z880bPjpT$$S@rPcS z_tQR!CbkP0}g~7T0})68q$FcNUJ1#TvLRRM9mVZwG+CN}2;OxPM_r zfx{kuU#Z+t{j7_Pbq_hvQh@?y0fv4u)<-$!d+eGA>zbNFHVL!~coD?4!u?;bwQ^d) zqV=;U@p^1JYVe7rfaB!i0Huk;qrPTX@$&(+>*?v~vdJFO=L1 zN^VsDVq*wGGyhGC(Mq1`(zMjYa^e_R5X1{fZnmikm}xzC-LYfPTvK9DwFfdm#6(I2 zmJlrC%qJ%Q*mL%5Kjat6d|C?&i#~PWdrc$r-li(=I6SHaBqO*P?K#>!MbfG?wIJn~ z&rL22coxZN1)LDOSl~>U*!f2$roVvl1^^S%b#kH8G+mZ*P_wh&Ra-b5psmy2`~BL4 z2o9cOK2G|AjBpJrYPB(N2Dqm;QW!aM}W29*X0#bzBY#NBw1iB z-+;dD>B6)1330t7#E%q+TBP8sH20ggY-zA#cF&oYl>`>n>N|H|dTu?Y(d5QS3w9d` zH3^fEHaVvBK8OxMlloPWf)b~CNG|^QxzdkSU{)9XJRaW?w3Ugq*4J2WV(`;t7!3Dzyk8H3{1Tj({b3cZ zDIdK#D6E(UURkna2?)j9674Y*H!JfB`njO;ZOrsv@n_MAAB)l9tbf|m&JiBOnb^$iSBrXpbf;|2g{a8L;;{Udr z*y|~&sNAiMI*P)BE*Coj9hnzpLT>S^Z+nhS#D9F(?%mlrISnP80Jud&j9t`Z^qn(@ z-$WfY?g|CH!MfoImq#nZcVHxU;)FWF+uYUv?s1ts83pPeg0_k(ASGb6B!*$YuuKh7 zSYBZV11)h=iUbC4OEEiT72n+@q4YkX;PGk-JwAs=hK6R5(AQH$(}-PQn}P7TWct&( z?e&AyV$1|L8a+CfEgcJ3kV;rv;u`zuuy5AtixxLcRkVVE*1z4fN<-;1D&A}Co-VC7 zjtx5{)dD7N4aSYTHFn^<(ZCdlH3gF-G^d~K^%6Hh;Yw$a+sCS>>)tr27Ip=6<|+q9?${AblZ!R)@tYeC1KUVzL2u)GM5#E!O^YHa>)t(0P$@B1jdS!ol9#{j zk@u)~KYxuI-!S#m0t=lBY}69KiQ+wRBIF3~YxQ8MlbNrDc_2y+XQdQH6Y3zs+U-up zbDQZ;Rb0HoC~haqp1!_{jTFNVR@;)C%d!2v3i9pQ!xJ>+Ssl;}cL6Dk1^dJq>%1MW zdFQ(@6y02D|SulY#8#;BQI#ens1=MpVG;%z zy^`%LUl9XkpERKi6X=N+C6^klSfAQYf9eiGIyD?pfJ9^NsxEg_(<{uf? zLDZR|Iy*RM)oH3w4rTn*3(HP?TN`v>Q*LS2<;#sxham3i^}N!~3z zct1~>5D~dIL=rhMU;m{80I!|h73xg4IdhuA8>N_A98XNl#!RMz;BhJ5cmDZDg_bb4 z}22l@vA9ZKMYD+C&Exx-|V*bwcStI9*#tSK`_ludMVJ`0Yf|EcLZ zx=ZVvl9Kiub(!I>MD1TH0&LJKspZRNUUWt0xly?+7u}=0s%~0@oK0|kCDyV zSo!bfq#d1dRzs%zVg0D4Nh4VV%w z6CVu74IW!U6)@WAb2)MN9gB0G0R8*+NwiE_?m8OIQwH)jZgl*!Yp+Ew#)w-6GjO6m zph*{BYVfG1P=MW>SNNqLzIB!DQ{rcZ0hg(7Q6Euq%J4SV46}ha=QKO=G!vjB?1Fh* zKe_^Gk@Rx`$8gbE=VCH~ad=7!xlKG=p(FA&f-5#Yc?F$Th6F>#apu4LSC?1_C^}P; z^`KRjf-u!rH0LhBG0MOsTCZ*qW_|ix77Ru%43(CQ%1@f~$NQ3tVKS`5Pus6nHN6$M zC<01)mZwjjDtLQ)LoH`tyY{MO-bBW4C{Df1_V?}GJ6Di*R9QyEtnqc38QFN;ktR;@+~_>aNllQ{bgtMX9X|KFmsIeh#)1 zGO7g=z^A)R3SEa9Go@x0`-0_X&~TwdQ)cVOgNF}=@}Xb2Sx%jE0>p+FfA~tjvs1b= zQ7B7mB2@OnVYIZLI59-zzU<~20tU_^vz|-dxrkJiHvFF8{oRDhyD038%;G|ekkjC> zX7XMI4eGL+7#NiBnr8JXJvEj5WSw?eTA)Ts7#1rm%g@AfDTc~`3X=&cwigY-WJT1s z{3y`BB{q*#a))qJu{seNh6)a4OzFFKDzFSn>#evPY3W0XP}Cwhd|YM$i-IzxtV7*b zMQ&A5`RpJ1gb%^>Fw?}8FQw?DEbyZE_*#8uoZDZ2g@_Kbj9_LnlvaFgUmD^SeLb2@v4R zU@+MzV{)hFw4^ZE@~J^hXfWlziHS)is$zF!6q$+3V481UblIaZ zbGqsvV8QJAf3FIF~OLqQ)cyJK7VIXdoxloBp=!Yfo9W;+P2w=&qW*|RYER2ap zoG)~u{7Wfoas%*7dUXD0M~&>ecWLA_1#=1vY=qFh=)zAQFE3+}HX_uo{JYE4 z&1&zzwy+;x1V9Go=h-x(6GEgVm@(Sv)9F?=J**@sn}UyWK7Btjv#EQ+=-wIeh%TJG;oH}*Gl*_bd3Wb+HLrM% zEP+VpA6D2^CAUwHUjP;vD|Du2BbXK^8&+~=SYWK7#!2y7{6vRCc(M77ld?Hs(6?u; zfDWxF)cJF^FL~}%Y@?+AxRF_W=eQ7fR)(#I!>bAXv}1N@d3hjHJ6sl9DMR>sYzNI2 zr5%l+W=5+rJ~z>lPjlb>ptBCXco?20-n;h~ICeI}3B=IbFTMmqg9Dxbt_UCpIpn&1 z3dy=H5ma33>?gwfPZzum1jrLjFV4UQeqjmFqGhbD;HkW#|Mfk5^hee(U~(^fHJh>)I~;jm~ahvxcO%! z(MQTD*hfiHaKvVFuN^~C0rt$09KwKX5EHOx?VDBJ042!$M!+?MxwFW6&dojR5s-a( z^=#<)>CwEFgb9r1CJJjba%5ga%LpDsWY+VA&^59Egu`$CMSb+BQR}D-QLA|NxBV@L zD99D1vs_YiR}BmhuVZC4G(tT$b^a4gniLDIofV4v! zBe#fiHuOUT$zdS51`yauq-{=~PD20hMB4-2iQ9dxLoj04iM)DHRGA zb=Yed*Y+IBAZ~OBEtkR&WSvYCwggrhb(o){&(PNO`5#IK;_8)LnCuRtnKDY-Z=|f0 z$Il)l#I+nN;o}R&e*vEVXJ5ZoOjKFpL5TOq)diHN5C(oB^~DT|L&UZCw=nk3-pWQ@iEuQN!TV1Sot-z@L&VZ zXh|3y4;FtEUu%)~(r*)OQkPV?;$)Ea<`PtY4QSZr_GP%r2^YRGEDS7BpcLu&a%m#x z_2Wwh`Nc8r4Cy{BB}pmR?e4V870tAQWpIfK>F~Y4c3eA*kRppdfzH%h`1<*sz8e1Y zkKhKmrlQLr_nYE_nbvCX8x7_4qI?x|WHjb$k+@VV5Q{y0e5?_sb64kMS|9#z2g1Dw zY&5;8w((wgXYSkM-s1~cHL@Y=pzA?a0Vfp=e#tq!_Tk}!2Qs84EFuUy8XgJik1i~a zf+(yWa{BL4Hhnv9v6)}}%3&qzFhG=mmc-v&Nb&dYkNtO@0pUR88lVvy@4XU0?fBb? zbLbSX*-49P!>GpN>7NI?)iVre&1Lu=+%USzN`wq2PV^ka{&ybg;;)($39PbOKt@QQ zoYRwx&ycK{%DId-gd1_UOmi9;n=oGAxXp$4>)-$UwDJ23g7V5SnQ^Qz-p-r{o>3{S z48S1^T1|3wEyHko1oJP*a)|b(xQ$K8Ts<|#%hAf_%g})YtgCO(V4(DxL6#L+YOblc zr{D;$1ls#wg7zlQ!q0dwntn1fr*yug3$9mn(%<&MZnx>2q10Grapa0`{^glHVPATB z+&)zItuL8GqBblyLhggEH{SgX9T z2MOZ9i<*M~9Z)o25b8V`K9`iW?><~1Vl)OL?{ztFK(6`D9@7y3F9>t@#!#@L!fr)L zE3khv3Vfkm$%1?}aV7)QR-_O^5>)V^t(Cu$)QfiX(WTsWLCc{mn-GrxfJA>nvwx>v z$YYbSbJwm=NQhy^+tV%XA*TXbh6tO`+4^1@TFSnCk4$`dF^T4$Ij_}s6sCa7$|^2^ zk_E7k&c2cGhid>)MAIa#ZvRy){^b23qf^nbP$QTx`}O0j>xaDKAQJ;td{$}MVG#T$ zwJZCuf83;ssp1tqr9Sey`2h_C*W&ZvtNlrWfQ?vU%nTc+cw<&Cz^ukin$Tq>L>YAC z0NfGb2!;h9p8_ibG{LqiQynmyZioglkT;5{F}PK4GlG zr|_F-L6|I1Vsfe{vs|ZLJI(U++(4S7^dzIYr1+j)eVj8d&3%s^AxxIibL^?>hFa#y z>hB^untW7=QVCmo-{VKedd{3XH$uwN2{*;z5WNFEX3gJ?TNA)OLpe5M=!aabkE#P4 z#AeKxpxwLw=rlp;bpzxjHhrtbj|)su*rS8D@(2X7Q4CVStA8J2SKLTk+_I^$3zHN$ z2=$vaM1N~FYibm+o`bk~*RBUMJFRgtUXNNA{+~5Jn^2rTr9Mk3Dr>GlQWQH}8COQ4 zICZA}lBO7HtAC)9lzePY;hQU0wJ|%`*;|n+B+$^ z{*6HPgWbfWHqHMIq6>GN0AW2|$0-R`-Uq=B$TNaFnU|t#lJ_&PO|B`xi|i7UCX+15K!zwnQGgQ}4#z3$KW?3y?$mj#((7K#Pp$_c#%6C_ zZs`n~!>^fj-v{$s|9jVY!rCK)B)I06x$t4dMvI(n!v(Kd9~>-RtKA~L*9_B3`DO`L zCo33n*RKok-{d#kc9_)4q91IDNJ5OYrlYU&gf|3_GL27BX9W@wH(~`>r z$Oj-OWAi{8Teo(Vs;WOI+yndv(6da|xj~us_H7uv#@NuKD=3po=k2*!_s5Red+QP? z&4z7x80q<9`DS}Ik>%;VWB(d6~lKlwfzq6|H)SBTFrV~q`_ ztA8wmGMWj?`*>lP8K|HPaqQ~1$cW6--{-tD#h)BC9o1Ejz024q2^@!LH_gJCi^Xe9 zIc8+Q^ICnYs7RaH`5f=#7n{;D^Re9c`r_(`Ws9H*9&7x`4(ki=-xphY;Kz|5J5*2N z>?d*p6myaKBOoHbfB; zoR+q@vo)%bxFgY%90;o&&paOZ0``wlfq!~~Zbui$mW=2dwe!fhK`+liWtgfjMJ?-h!r_FC&F;xKy z-h>{al)0$D#6-{j)(NYiA_zbt=H^~Q7~Y<1+Xk{z#wn<59$Qx3EkWj=mS)B%QhjwD zaFr&HbBy&!v8}qOLtgV20EiwvdL)8tt~3p}Y^q|y24~+66LxA8v_KKDx%(RtrND79 zvyfFfUkqhsl@w4?k!rXktSw^kiYsn3LW(OVn2?d1!OV{($7wxcByf(l-KP+`eQO3l zABs#!)Y>?aRi8PWLga&(Me-WRP=W|!9mee*%&o7?$o$ztl;+-_TJlneTg-vPT)OnD z2hCY?8eep1#Nn9V*|(j{Xt10OFibe{-*YG;wd2T2NWPLku8aQE+ejr(@LFEXVi~#; zKz&1=nQzDl2@5tT!(?=W@%=*W4%*tIE{^|Y4eKG%jPK-pD?el2bXY-sc3*-BdgQ%2 z*Pb6P8|x%r0z4J>*=gTJc0Nqq8=#LRJ};3e9(Q);hI<6AALjUjW)HV+2n&S_Qkw$|FpMBhr0g@2o8C5$RCu+%FsdR)H(M z9@L=VPGEre@d;9emeRHG_Fj4lIxj%tt51G??hC+Oz41Fk6AI$tquXCtUTM_}XKoy0 zWxP^XlOSy_kvd&ppv?(Xh_LiU|kV$JnoB0`XC zNFQk_Cq8PVUZ9(wF~sVe5-5TU7IMqML}2w<{?kzkU4|Qf7rNChQi(|p5;$lE>v6Y@ z`L>_mEd%qABXnm?rT=QyfFg;rB9b@(!;X(`%EzGE(6N}WAev*;fo7Nfb=h%+I4L70 z?;f3Pg~CX;weJ^mO7Jw}%t4b7jCh|agBsVjUCO3!dQMkk- zX!GEqZ79_m0O5f3zzl~ck~IXp z3>iVE1d?$1vA^F$yU-oB@s2cFt%Pr*dsC1R_6IDh0&+a9!|04!!72JtaaCf*tXsrv zt){|ubW8d*7|?KqQE$Z0~al$lq2W6oslg9i_mY)bu3#L8y(UBTf4#Ju=gxtVl>Y&Qquj?sCdT+{x%yZG2?fi+76x^9wr-4Fls$2F`3T+wZ??JA<0}~Ws~~P zF14~S+0@G1WrFPtP)7KiLp{!L_G~(X^eh9PreH^-mnSbC*NK`pJx)?qWFd@Z7tc-e zn$h2SbB)MWQd6A2^>{yH1LDj@%P}vbAA|hd6KqaeFz5B*!;`lk`hktXvoW<@GIM4s z`YDxMJ=lAuH-3kp;yx3Sn0=HXod1{`ydTiSbo$)vbwmFzx_$Ir9dX$J`2p);&@2aB zMfS`w%h;?+qbfd1%Y1r_eY?*3>}KE2CC90`nD(D2i=+qez%_dCA2 ztX^m_hGz-LvEQ|L!Uk&tAp7h`k1h~!T&YoI0V&QcVs*;~sQhJNJ?MF*%dxOHZLwqa zBz|ZaS%%k^(&GH&6^!#jo~Jk$Yy{l-VXAuLB!40vxw3+bSa9V2rTYpX;cIBm6SkXl zV?r0sy}!OO2lv@<$LCDGiI|G-Nq7<_k8)@X=ei(SnxC<<bb0=DTRTctzRDI{zq^&=S#jtsCA6b_5 zxv$64>56MZT890@%z(ipF-wd3@3o%xSPFHZ=BCKXFa?qkPHH`B1e@c-1;Xhlj@``q z01xYJALZudB|b?a19qxs9Q_PXLJ+hJ1)^y(3u+i=fwJ(vC9mRMoeKt^6Ps!=2x0%} z)#eqnl2k{uq#_s>l|Ok6%t)77q+9#xQ>LgeQ^!nG^7f$DUC{?h{g|d{E34%3L6l)r z4-bzaSsshopAF%6vsnGmzmW}xF z6izY@2rfexFoc2!umD&;0l~@Z#Zt<4rp?VodLgs(G2BQvD_M@h{>kFEmr_M*QnaM1 zY&c&m=E^U1z7aluIMGvlF77=1$SPFY4|vEB0fk9T{K2r81Q%intSu-u)^JVR<_#Hn zV$J24Foweae(_6_|5ZEh_SB#FLR{g66l(XU3z1Eol=xz5$bgbP6UOik;VT}&2?``=DsGBkg}0m4%R4HN{vv)B0R-IYP!mlHEv#+%s{aA_Ewr17=Vsx@mQN2y7L0EQF{R~$d{mzR%^z?b!s5Em#Hd1UZER8ssaSQRCDJ&qc2_2!)k#%+kBG7Cf-DGHp4 z6Eo6!9GOg_63mDVw$!3w<#Yf?j~*48r~XOk_ekoxfB$|S#FKqvY)6j{ge60%E2>x| zITxD>#WI9uS%h)qVBsA_3+)=%G;MJk=n-ccP%xqKu0c^z;gKP?f zRKxW{VP61;BPkr@|d=oGbeb>8iifEe+ImJynM>G*)Tfb3|C1X` z8m=?hSf;Uiho_g9XZN$-XAdV%ntSHRj>P!G+s75VC&zc26CZ!rBqr3P;op}&sPxV< zZPc4pwW}*DmcQAu+iiD)f4|p!EbK7#%fP?pbkE!UcFO&JGZ8RltWbWNd7{4aK;UnH ze-&ht&~deAtF2$WctII50$u3&>s{EEKzjmip5L_%x8t$MNf?_#Qo)-DgzlnhVB)|O z-HGd82620=OeIoP>uO7l_EKa|bYj|Ov5LQ@oK|ht z>~&c}^>H{6VQSEL%Y{H~p7H_Fxb(j=CraB~cPayPQ)|Go)T=GBFbtXq8R)5t9Uc{3 zxW**%YsZeyI<#7qa?xAU#AOYti)hpxmRB4ZR1<$1?j2Zg_}DM6Jn6>)sD9o4R=jcc zBpJQq<2-IH739axgcdm&7;-mKpjQ*=HF)&BT0dib>%M-{)7*aaXp?w?h)M9GMZLir zP9Wf?uTkZ_*8avmqv$a!uXjG^aeBxt>hkyJKYV^u()DK6-Gw*)uLZb?r{%RQAY^Q> zk1sY@@1{j}C~|z!>%~S6O3MEi`Q>P89Qk+^2d<(|6~KxAV#VS{l~84WK(u%+CG|@% znYOa(N{CTB!wjNeL`F{+Y&dY>)VJeDGCctgh9JGcjgu5UocLFT9|8g9DAExt-h2PZ zsY`1L*k$idfH_;t8T z5&N;LMg*$d3K_@&q^WfpKY<@}c{4DC2=D|cFP`c$N2@7AJVXw=oyD-bS;RURz|9Xwt*&|f*)K9mL# zQ;D?x>4}NW&`Z?A@UrLeKg$hw-jH?U zZd5KnYFqDxy~#S*$q1i>`YwxV!Sc)c-pGFV9e@LUEaTC+HxgkgU5w?x1JJcjV(l-A zmbn|cf&dV^+;|qQop*5M#T-FPONmmFatlLtZ{2yc4D>Ylw{NrG;`p=`Ue~Cy#r5xe zvymA8pk3z-A$*4RN`2R7HOZ00750HjG)D<`7heX zvoI7uOa_jW zvallJI16nFiprBG7mr=OautkSjtJ9V7jz1L@j`|}VXRgA?rEdcnDS>RYXX^eqhvgN zpcRK*2293|o%`qTd&Q%s@xPQpKvx{_VuFh%RdkwEV&}RFKk#hu!=j>@Xd%R)0|ZSR zV7L;(w~>Ol#+#?Dm)ma7M1ZjLBot3H>JvFmoVu_9Wa4oMP)45oz2& zefnSU@Ks{W<(^rYBrvB9)%<7E|&xgUx{Q0>Zj7yPjaX~>t zV3bYTW=Z4SZ|~&O05UY?TWE(rVFV0;?}M(9Hz_92;?X?h0u&>ST#Ng`oAxQsk8!>! z*@Reu9$qqPWpGwOfd&Fh?Hb1|HXX(52BP=Ol)3+1@y;}`G)oL>O3g>ngdji`@lw_U zEL2N9HR6NiUOStg#>i!n<_ z!6ss!8T!|OZ$yr8m(!It{# zJhlUkr~jh-xZ^SR-1+n68#*6&Rc&F?ty@*W=pLevk+4@g&^ft~U@j9b51P-4GD;>R{3p12ivUu2q= zVwVI|HlGF!?2f^63hDIw@Akl(TKS)Q@nR0EX~x8!0176@4ZJkv2>AvPtt{uprgqp7 zYi0O*x_sF=jwa>Qjiry!YE3G4Y%QQIL}KLh(>=O$$)fQxvuu-NI%emkmQX3<22?c` zt08=nWl+S@S4C7JvXn~vIF6K<1Rq}P;6*ynzSy2I6XACIS_>FFU>{SUqAdpz;hX~A zDogvwy#A$OhH(=QZJi$U3giBUC?2wzNN>n)Lx^6HL(?5JIC$&+QgNgRokqFHbQ4G_ z?J9Zh_v8aYRsJOwnX250zj-uj>(*4p{s>GN{qG51PwT|yjh$ES6yk><9H7WV#Wtbq z?wK&SGQCHf&>FmYWyZcUh;r6p|0DL8?>&*iH$df0T88LP=@7>3duwG;iBiS@?MdW? zmWT3?_K5)tI6QGs;g9J3QCxV;og3_$BGYEK-{M0g#}Hp$*VtY@0Nz>L+w&Jn&!Sa? zS!)%nMsa%!@7*ioRMSy@KFVw znNwvNRvrziJK{4_4pwA(e2OSkiZ!|r{O~OHZT>tZET2>wG697k*{0Ts~U=_ad>PIYB4(rrIS~1`36Lk`4&9r`O|I`vB(Q*kom-AV(E9 zN4G^)4bfpZcyL{GIdM)L0VtAl9zXsWU9PRI4bDJ3eRywQ8h$H4vh=Fb-g3qHZhQ9b zC4YlgW}P%492IwCPE9WTpS^z#BmhY@!+mja@yF@f0ibrs1Xq)p@t6$^PRS(u_6Wc zS*~C1nSq(y4zPPDGg`fRNhp(Sg8Oge{}WHR`g?(h9i5!A9LI#s@311_#pM(yjyFk_ zpzRFO9vA}GFcxnWxu$>d@2Noo+^-kjSg%HBqwAUmd*^o$H#!3YX%Bz;U3W;k{`WQE z890!~(QLyii%)7w8!bOUPC4|ATmSxhT2a$;I4ep<$wNH2tog`-lJqSJ!{M$~_?0j` z|M6pQHi?i#JVV#*SpT;GxG1^CpUA2kUr~zY9@n!$3>_4U7Uk^kQ1$uqZKNjH)z;yb z--GAFTFQ+|B5Em0tcuHtsGxx0uJR>FQi231 z4}GZZ)y(r((`7~LnfO=v&D#Q9mn}<0LuHck^(ik&W8)Z`SJLA?sTc>?R@<17+j!H zWz%yWvgrx$IxuP^{sweU1XBVK<}X{;3Ol5nv}i_r#JaGj5W{L*)U?;$G3^SE^O9$j zB4@vfO7O#tE#^#&u`Lc=Q;{i<qN%(g_CmCjli0{flSB3U|BT>32Vp5IAGl1|*h=y@eGp>=Mr(y?M?On!ULL_Pteud*#b|6yrtY0}#r;qcUpXYH7;cE=Gc~o9dg7jl!0nJN=dRb6imVKto_M+v#u3O=7piJl-y`1(^0sAB-jD< z$9<~j?<-G&9hu@Kd3l2u-1Qr{Bd#0-Ay+s>tIM}I3+G`!srkjR20{53pHO;VZKqij z{!?|{?wxb_(lKb#IR3;qa}W>aK5ya6BWUyx1BJxR!!J=ebz;^40oL`;c(^>{hCohP zUD9g)W|eGB&gR;*A|+sDRyKG8_`zXUB)aFLQFS{xMPk$@D+xrE78;RQIZh=JS=TPE z3&#G9l;y2-cYm~SidP37NpJ#|w$s^tTf!V8eKXU%Ymo8R8ER&y5~)m#svlcNM@MI@ z>En^Y=7ifJCB$k_&u6t*%$my}6JD_M>?faYuEe?YHP2b9*PwnE)nKh5`()b8v9_9X zAao$G7jTP6kGhc2E-sT7(a3zfX+PSFC_!)_{k4D5bBkTRK0Y1qrmCBGv{>c_g_^Xr z+udDw+UN6kK?mR%Qv^eP@etxFJ?m9|$ACp7jJAc&D+UkC6r=*mRvH8~sFsY~!!J;y zVsA{9T@3BHbnj#+RN9h~u`4BZza5A}`4&+M7o<+r(sKMgmj(c?R6M1UNyAj|@oHmF z8&d9b&7mQc8@9W#iV5h*VXUBIpDgp(#R9$+IQpSv6Mvi4HoqV17Zfy(;7)uiRn^qC0HU=Qj8vM75wMKn7F93P~NA@H}LzFjk#`^&(+Xlx?WW94AbSSj2B z6!MMGLtR2%lt({F8p%PWcXh5R*D-!8NkPNaX9+2_f4^$XM=*@|+c-Iau1Ho@emA#* z;Gt5;lenH5Hspp6y@QnC8^6D5DrsYY8>%cI119czn#fNTRE7jhXqIHYkrBfXO{NY% zewnnU&4Or@jC*yk>3)*;N5Cdo*1m*}O5PadK}6d713zQS-keti7X zg{oy37rBD>Cf!*Z&8MAx!=t?@QPCws8tYqLDr7 zWdlN$i5la&dOo&SQIe!XCIRwbxfsy{w3ZpF+NLr0>Q{EUAvphxtFC+J3W0fujWW-XkwqdK!}|&bVZG<{qFGM z`npT`sZ}>Z?PBEOhFSez^YtBSbAW4HX{!3mR5MP5Tf$u^NRZHU@I(t{A{vC2)A zF1S}K@>I9Z+|QijC(h^V9}9#lvNmk~Rx-c}7Od+4K&`5BxvF^83O>VcIVi}XX0$An*{eQAuy=tp#73XW1dm+a4pIZG@1{wN%4Q~PILe?UQz{o zh;>I%pk`S8b9*CfN?>ZqOrCYwrSwVKvZ=H?;~w&ZB*Ru(R+YyE`BF|?uBo*~bJfgp zhj7Wrd5(Z^ZS_%-^@Ri$-}>jzTVM_#F)7z-f)txluhPs+BTg%UVeYTjEcu*}C2B_yoaaFh&Ln*ABkxN{UqP$GUn^Uc&Ck{^hwqrn;?r4_Qq)ft5k1gyR!}uT@nF zf!OMgid>AWGludPOezU_Jdmk{;mQjx)V~BSAen0=j%qY?B+eC3V7s$O0;2icE;^?!Kl?ORz>Vh9x*1YMi)Noe)-W=P8mVIRQ zC(f?eN&og*Nje#SK+E6JF=;I{UX;bok+Zr&%MaGnHsfX4+{JhqPwo<5K_3-fU{3KIs50F?g&FuT@ z;Hg9p7*^MM8P6|z|9&TESCX*gcT<0Oo6L_Ixn%z$4*W(GRP^RjX>=89wS*h&o0!ux zEQX8bAY)~51hfSFyU5HSIpD0-QW5=-IMG>J^0eg((e#LFLPKF$T-uL$ zTpTc*a$Vxb??GQ6P@Sq()Q?kf8FidMGU#3eQwphkkJFgk!)Zx`!MaUZ+=4cOQ>Q?5?4r0@iEEl8$@@K#OH8ViE)@1qQUp>PK3{cOxT7lb1Xc3O!@1!G#!2Y zn#yCTWIWmGS?7C@MJkp-R1BI|KkQvUv_5+ae*(f*59Y+knx$UmULZrz@XgA&aBz#Q ztuICp>C(g8At?n6uAM#b)82)=Z6CU+q?rOagTldTflnKgmNVF{qH}V+Dcq8YTx^=H z1$W2zC5h`vfl@};SwR^rWbB?YV+mZ>?Dw59h;rRdcH84Xb~9$!(@9Lm?A!xK-GCI*qaj8RYEY{9lXoT%WZ6_4DnEY2_dGr>Kt0Db zz5A5-{mzNZJ(1xb^wLW;N9_We);a0sc&*zkOHo;o!_*(YQ=zn}+Y4YjFxR8GScN#q zXzGz5TYQb1M&4}xLvdpCu8~tUcT0%LGv=Vp%}p z@FI7_#%)ss z>0mG@0|!eN3CUm*cuu-wZ(VTP$t`$ES~I}YHzCKcrlR6#i1hG1&xfFt_P-r4!gr;KJpI#5`8 z+KKvrHYU8;RxkkaC9Jt!_ePX~z%U;ni~fH=QzfbWM7ABHT=(gG{ZC%2Av z9_RAlER{bXgo}@RtDCg&F@1A#uksAf5uIAekWkJ@`3|A&K7`?G@$fJZlfS6-KtqF` zTR2y}dhxP=JD-N!R7!!?UAu-^?6~{|q(seDzqc7?eAapzr6@AsD-@5rT(8|! z{SABS@wz1nSi&!fTG=*o>i^=*>Gy1@q1O`OO{l9OVJEzD45nviXRl`1Ahk!W$t5#Uz7ywyPZC~-M{%Fv7_xzyB~Vm;;Dv0Ad(e@yV>&PpDc1+z|+!>p>ur`Is@AAAZ?;=M_$qMxyCS zA_0~zQ3v_M#!i8k7j!ro^HfG?GCE8G=cps(44S$eq$xqbz+3FLTj*>Vb7N$T=REj+ zl9G3FzJyL}_k@HVs8#3>$$_5H|6|6Nz2miHo{gN5h_GcwQ^~TEejs*)!>ijqatlLW zQn$4%^UN?WpB;bck}1Dka`)Jfz+`g$N{*}*6Bd^tN(Id$gK#~&t$NL-G1&3PT#qt9 zJudl4Ty9`A@i)RR4{3(qrD_75N^(u`++ocd@{KSGb_bduCj9X={0Pa)nkLpnbjMQ5 zQZ4j8aoY%rBlSY2Z0!n6tx!8wcQ881VN^Yl7?e}891b&$t%Z~n4H)1+0iGW&) z)>60gPrj{?35CRkBkdcGuwxyEq8=3eFK~}lFP#pOZH?`rhQ5;!HXS?S;XU`o7_(93W9z9hxQr5{^lnMZLO%aR`{chQ>m~a5 zBS>~Jv5IbX9_~DaV}Tv}-83qVnhF&~N}VSRrr7o7oJ{NiSksL@{@r@SVWFz%c!^5Z z{q)g^myYX*XsSiq4o8F>JXk+lci1B%hYPY@PvB+F#RE?obWkOMhha zr6u^3(wbc3_@l$X4$>*c1{=b3oMw%-4BRne4K^m}ot761rz}NgmC?=rP4lMggKGD5 zjJO!@^?*!@)fOkE^SMcrB0kD(07lEt@gG_No9F{uTXrf6sAx5N_Sx+1aS-RfP?)56 zgY|7W)C!RAiQ~5;$(_>p$cE)`cyVpDBI4MG;G2D$EgjpueO8p%iYTW<1O)t&!z8eh zuD|j>7=ILWV7Y8op`+famd+e)eahn-7is`4!%uQzjMNGn}!m|aXNBZGqgAkwyA7q+EAtx>!ru++Cy;_N`x zk53vm-TIV`OdMDN;DOe6_WZr6K|}F>NkbRMOWdZK)-*a&dB~t=I#kj9V@9bUoAW}c zg}0+QZv9;VmFf?KLuV7y782zd(LMpb#Huh>KoNG8xFXU0xEAG_LQRZZJ@kZEU9HIF zA}Eo1Xkc793SJh$j;j3@VF2QHJA3wVSr^J>$`VSD(HPOgMm4}D=1T+~4*>&uF%KWD zO;YPvZZeJfg7NcarP>0%Z%gq(r_(WFWW@4=Cs=jR+{tMw*rhrgfrf4(DU48A@z(-D zSd__dWT`4sjT-Qk>~?vO1VU@i766ot3XrGWa}@ZR1vG0~3PC2E350^Q7PhY*O>H<7 z65^1)r>DS52Aa8C7-cz#YD6;W`5AWeG&r6R%(F*&~$SdE+^QhC9 zZf$N6Gs9mMvxB+0ukBO9KV+^bR2`q-xKabw-DtaDZ3UU33d_oAB%~kMCF+q&RuuJo zl?UhJ9myFcx}P>e359^nghQ=!-cY zidZTBEw1FRxxNM0VlQ7drva6h%}gy{R%F2WzlnAH?>}#PV98t-H?hy|vOt<=p=deo z@chd$|D@+F_CII8d}HJV47!ub7yirXRtZ(rWANY%`{2XA|IvU!9RkKkhTYD{%8JNb z4XviVPeP+1VL{2q%v4!EZLq3fdlf$gl_tXaSlR=LsB3s}hWI2(^;m#6>`zNLqzQAY^;9A5*#V*D}k2`FC;GEV{L^2Vy-VHUNLj(lrP76L*V<%BB`& z1||$tAE0JWzd{$IwVPl$x{$lW(RayWr3CJx$uU?*_gTs^1!&FNShnLQ8a41b8Y}qo zBCG&*kSxtpP^z2BdLy+CH)bGAPRz(boVy@fnYYNPqw#*pSm#rh#&ucOh;mEJo2I5) zZNJe)2uE9JTbS3f)OxY?>0se&^L_t+w;2Kw;@19=FICBoAm{tWr#R#LlC> zu&xi?&iBOx%9`gWWgwlnz|giyTTV*ec%|F%OLAD+ah1p!K{i#!lVhKuD7P^}5bGGI zG!OY3QeWDJMLL^P&gNu$+f$XqRXlA@V~V8y(sBgNE}2_`P5%;s;pOF^%aIj5a1 zyk{!?{2(yszcC0gK$?{(8w?rQY|$-v?aL8k%Ph1=y@yrq!MEf9RX=b#Q0KTl9t*&ouohVxFU7zhaAMcsbw67mXVJ(*0x z&Gp}81ziuAt^G(gk1F-))$W*%=ajsN(f8`9XLK5q@t#{%Rsj*a1fn$v+v zkZoLl)YKr+h}VhyBo1|9*x@CsyY;xC-qU9M`F~IpB)3HH711tSWnuRa__4+E9C^xx_2cxFM7QKJ^KwjCiK{p3`A|VJeZ20|v;W=G(H59go=XS;zc|4OxG8 z$pq)~`0+-ubj7vz;y|&NvVV#+P2-myo4$8oDiOfXL7EtEXJ@r{Mg@h()limpiIG3Ry<}LN-F}tL7HnIN?Pr!Bd=2YC;0g#yOxli z)eDZ#0nPDW<6Ld#&$Nv!XGP0MP@%>9v~yp%w~>N)dpOg07BL<#;+Bn8H*j-QGk>~{ zj}O{pJ-4LC0coK0$a@`<{{WmqE@T;f=tarK6~!ql7I!pWoof~(yAub?{pia$2DNcy zSDI-+Es9TA=p=3daXIbZ&&=Bk<2DrbG*gp%#+PaZtxXhNg(RC(+0(l z!*$5~rOao~nxXniwg~-&$20;B;Xd2#-c`K~Uz+3v8H9fFBp(}h6n`3?x#h-i=JU*EEYBZb=T`Hl$eZ>^`qCHp zz`CI(0~FuBJ-IT1KgKN}Q39mx+RWwJZaKO9od^CV>MjEI{aJx*Z*n2W6uwf<>Wl8{ zah6{w-v)}+n^IPu9AqcXHsR!iq!)`7CPJLh6Cx`qDde(d`rOjWN4G$*JRZbg>&W9f z@VIj;At$+37;B5DM(yMH!b@%uN&D=w?zOVrGo8V3(L9S(0Kd+%Y0^1P&NW0VuBHW8TNhlH4I^WFVo;VzxPkRXDZ=A;d}J|zr;#fUUbjE90r)iHmq_- z&HW!!{?;>GjA@uQG-b5#k*Mn6Id+JdW-^?t&dBQU)>NKyWDpS7GTtu#GYLHjs7X{_P*S31 zP`Y~~y%?QFZR|Ak(Ak*gzk##WovEVQeAefD76nRr>+HT`F_nW~NG9$1OK$-OrS|{` z?x-_2+|r(QaGDLuitf4L9ug5!aNlD;j1#ONX+WgQpxn3F_JMYjV#kgf=lpBk9!f-{ zZ}*i8uT8>P23V4r4w-8qoCKWN7-Zf85s4(Z7Sn>R`gt4e%H*b9JG@__O{~#spdcpA z4gx8764aXYgCj_x%%rDLs=PKRtX;-w?^{6Vf@Jl4`7wimMS_j(+=SZM#nrHl#zT7l z$3)Jl!?ySg8gsxjjp3Z52;S)bPI2X-i)KWBHKzJ?6!;V78e!6mUOjH4|igFkGVJSQQ61$EvV}{`P$qIxD~zSch zRwP#GznDXCbj&^jX{3;JY*d7R)SopqG72nieEwECd?iMk@I2n2`ka4if34%fWE~#1 zW)e3evN-*8)jy%bwI20rSIy6=!TdSNdD^mdt8UFs+V8o2uOG8IWx|11BRvMf0mIO= zyz>$pLGt=fH?~3BfO7pT`2bZ%PN z`#^~~ojR6IW{rz>Y3P2|Trnp`sf^r!e5K6zpn8T{4wLK>w;jyYf+uF4nEx`rK(}5v zXgLGN7AK8D`}j_|Dcw6MyO*BCjo91b$Y`KQq64xaW|7f7OFg0m1OBec7VgM#!?bC8 z#`LVK?@nNyUS5{p0$7gaKoV{x;9u#ZPXF$Q=|&l{76MmvnUUXLHUtLoOfgp~tMra68^zYwDLBJYm z4jIu6`m=H)TJvRZ{`#y4>8ztpFW+WdR_-fpj`yP|lwKHh&ru9&Vb7(Zs$T0JyNzFQ zhmtiSa|X|k+>A-Zd#vtOP-KgRjLqS^#>M&bCl*WQ)hia$PvMke(L`m=0O(5pa=~b` zY5(s9;8uzIak}Y0n3eFDkb#ib`HYSB$}exHQ2G36S9DuM|J=+=i=_jcZjUi255zxqD z?8^PY|6PCdbL9C;k;*fDl-jRaDlT(e268+kFC04m<*m(PKH(i6=^WtaSJJv;%O(=# zW1`lZ%h!Qt=lJwoXv00bjg7xPb0~R{a4E%L=6)G?%bsc;Y9AXVYr-zZHu~!zuOEu^ zVuf2)^fq%=g|21Gn?`2NI4d1GaJZobzn*h|Q|)*=A*e2s$lSoa;e$cE-tjJ zW29(bJ=Z)fx0+)}Y*!hF;p6Tf?97Qn_}gCwtIHN%WLA`fPf#qj8viwo3!z7x$g)7(E$J3<5G

|MtcfzWP#m7P;stWo-v9K~5X3OnE-o8)SdbDLrXM#yo0Dk@ztP5Ur!i+VeY!=Q;1y8N``hI3ptsa^YqfGZ`N!}Zc07mG% zadrd56U#px>8*6?Z+lap*;$~LN{q(09d&L$eX53sC=~@AbN!!HHA=frpEgN`I043f z&zj@ZnID33(a&ZUppOm?eCBy0a&A)1h*416Mgyph6p3x)E~{g=d~Lo<&VtbX_vavvqhoAE z;GDPdhs2#fv*~^y&9_Cu5lJ|}Pkskf@sgN0Qie1HzKomPMtS%B;6)t~2;1dVf1=u= z29IEg@KXcb7<;N1I<3Jb{+aB#yAQY5{*8kO%F@T_)79cuEb(U#x8Lh{)T69#xbHId zJ*)p%c4?m{ePg<o^Er;@EQtEDDPF@|0}`V*S^Wt{}E=yOOj^MC_#6y13`$TLmWQ-7J z;Vl=vV$s2|Jgm#xHCtUn`}NS4O&UrsnQY+2mpWpeWlo0y+~zH-K4xZ*wFS64ZV1+z zApWV&YhJwK6*~eT=%w&EfBt-m-Ho|HgkUOhleQY~euq5T6-9TOADrCFKfbep+bty1 z{%(DB;zy!73G%c2z!OB0`E;Rkq{2(GY(*yA$4xe7W(yTj(&Y0&pm1k<^V^DervJG2j~I2ACA1SWtpj%l4*sSJMx2)7 z6A1dCqHJ|W>=%ylcK)lOA=Z|JZ=+0k$5&~|tG{h{I;hi#q72`Ec?dg@Df|_Sd6JNV zc$-#P4qc^#g9ouh(RHp9O+XxmJ{Eep(lpF7_OV#br;y2_ZlkqV?WY|~ETF38|1BOS z1A&3~Bf7O$R?gi*CCC9gWMz>Vw6G*g*Z%rp(b0dB)|P%buiJvBNX7mip99v<&l?`|CD_`;KY*7b_32dm%T{}|a9%Vc7;)2;D_2r#{)h&K-Ex&EjZ6}2 z!3Qg>{p@;A*pqS5VH{-G<=1nye;lB%f?r!Oz$DUjMB2*>6lZe zl%3R7ly{c{5pL1)R#8`5ShscBDKm1knL6<1!l%w=PdIIkoWo7ZcS~U>cDp|mPo^{{ zgb(S+k$;Jye7=%3!!MUv160A_$XD+j`3AP>xLoGU2~9EJ7Z5AHb&7dtd^;rM z!SHpTwGeE4$_PJmeQNYtokke$=gb@H*M!$__T)U=E`wB?7jCY+t1^|j6xp1d?GdWG z_v&RHJ;9U9h(hnrdd}kx7AK#A{zscxM4iJbzkY3FR_71GIZQbrDi_49B?LAXxtKy> zScV&_%O{rFm%ePpIY*BiKKyT{&N7odT1YfFT$&9|g+Z#&yFqly|&lg=d!CduNtc3mOWiv&d6B0Jo<)S+cxbFAIoa;*q2okYsIqQZ{4Tme8P_M48dedTZui%tCo^vzZ z&Cwrt2BT-sK9aGd46l3VUHs$w6W~>uUx%;S557)VYg*dX4!0P+aO&(Ey|x*0P|K7! zN;O&>?D=(TaiL<=53Pr_mvwY?!xIv67tG;3cn{oo@-l~gLm(`Ev|}lD!Rg*e1Br|J z_V3@W%f5^glhhL5bbI=k(~DxcdCteY`1{L7a1R91n;4!4e4gz%KQylu@f#>p{Jt4y zA3S{cHl>Oy_n_7Uu|s2aZZKhwCF>u1t?=&;1I?EOvON0$3^Bjc7*X|P_Xl9p7tINp znojY{2G&;AwyRmAHNk|gGgRw(T*pFv-g8^B{b<<3IJ=k>JANOFHMeKegmaKcamx$m zmfT&7&oyI0)N_dJK5mDunnxx>9Hc+8(T}w3lab`P9u8>6S=|mTNu}7?aGJbz5l|UY^nW{!q*Yjt5#Agtn5k5pU|-^3`HB{o_RHcI`T-YVHk25M+!$ z_nZKyZjUW1iQb-gVu5Lj((2Nz#{3YIcn&ys3sW<*ud4LsN@y5wh%-q#LnSilsEJn8 zd{duJ5%9;-HHVIl{v^#RGU$!#ca6J_CUErx$2!u0Njy;HvV1~l&f7{m0BO04-rdwy z+J}w=D$X@(n2>}_9qv03wj3joOKr{KOEbS)oTfi8X==U=)%FV0u~mgjSnYH6Xh}ZZ zL7k;-DSQ=nBLCY>8Dt^wVh_}7jBbd&_ABf zfrZ_jyIL1US1PNFIjw2^HgQNeiy5weT=~2`T5cs7o4-xFdWxf(_cZgYgpILITx)B@ zkVs+u-{MOtdGIsgXCHr+^Ra*b$%P2|1SMI4 zeoF0Q6FC?*e9c`Vy1s&tV$$y%^iFWflA(vZ2SzsCL}yEQXyN0pfCYft=*Y}pX;gg_ zCqC+KPqLiiO_bV`FT?DZjZ^=z=FO=VM%@Z{lmwIyxtTQg{J8n^!!2D2IeTWg(gDb0 zqO_0S+4OjKP0ex5TDH846LJ^5)D!mXqK<^aX@ienKAkV0t{;1m%-$9#1-`6%7&&1y zKW6mQjL=JV(Nom7F>otU;A%ANtvNj>W|n@qkJEZx8?&j=7$iB1V#AA0;!yQ2jKTqa z`A7K`$PunrlX&t#ua~C<(6iKB*XHUybF;^n<@%Oj2}&ytKQgm7)7kK4kH@M$oPFoe zM=I!Cm82G4mOLbST<#8O3oz|9;~$frdV2en+Uq~zkifw2zq(g&`as1^>=Koj{k?V4KooR}Tp6U6gv(A30s(QVBlzwl6&-Wd5 zBI4p6H`wmycP~@Am>54kevda>T@nV=j&>Pcwd6v$iQW<&^-7dW8FNap%%!vT?V%+S z0=r}!O2%(n4aLWJb8Y={h^#d-cAI4j5wO}z{lIWnWt@f zY|F?@$Ly#37j>+!%yytCQ2!SQ0nr z7SGAej1DMnp`U95xgn-7dZZ6NSnO8zxH)}2Fx_F$LX-zba$QuD-aol>XDbW(BptG9 zr^dRM%%Y9)Rd6HL{`HdQ54H#P-n%IGt>NggVb&+6t-Q29M8&we@BN|NN)7o!yN6+o zc!~Tm4m)!932iB@rD5q+p`+QAt%WA(iz!KD^fP|GV+jczIS8d01?XOXKi?a8w&S`x z`Hw$N*`xI;Wz_D@HBTM6P+@NwOD2Prj1aXUlsAAZpM4XTNkVou8H2|?Ay)H|} zMe6Oix&K}-ti&?-1fICLf@C}!RorT5VZl0C=oO*3V~^I#2D|$2S;WpZtgcSKacFX{ zSKl@pkIXhxOaC!<^>Xt_s}kdG6WV_A;i_p!l`ht{OpX>-Hkd=EvjRu|ao2I$`phzX z)C2p$k}YzJ)(8I5wbkXmpo}jC?En&A2u-Lk3DEW5`}nKhK!r(r8gW)~Dwq7UiOL4Y z<^HNZRoy24!SeIHF5X)@GB|zVf$SlVJ>Za=d7X69QEv*g(_Hd}k*ox#Ngo5}vG~U3 zUOyPwHT|vp_77YwGGJ)oOt9AQlNO;nxQPGM1NodSuYA-8PD|9!tQ`MDr_^lbCDU0^ z*(<~I9+Xylyn1^+Chg9IJz6g;=WorsF*Dn;60|;=-?*yroNI2$l!O>|{Q+^9kQ(CX zQ|aPGjjGhX#+s(53LN{LLAaQh@8WF>q9FT64JT1TW71#nL4@07R%$)ggE9*@_c6AJ zo{?=ynEcDu7W#14-L6}@mM4argB31OuD7sw_uQV%`91e^zjJW=2%_O>%bkw0`cO z7viH}Bhw_*2E&ywFDM+!YN8S6)LUJf0a_2)zI zv!yRj7>@q;#k?g6UWlBAhU)RkF3}mTyBBp7?h3B5(WTs-=*=Q9{Xh26+*Zj@$Q3It zSi0it*3e$|AIH_8S}vlzs`&P-jDPkYIG|VW_2BsjwB$NhP-8CI?8D za`OC?m`UXKSz1rQ3OoY^Ux1(*UQ#)p$m8gBtKW6tCl@I)HS{@v@0E)3Ys zx}P_tWtvAKEC_?oZx4IT6_F=Z8E`HIhiAq zZ&|cdTYr&`Ivp7JFgtZd5!TtQs^u17b|4(osa_JJ(_qne<#%jGyDQWz6O2jB7zEt?>EH3pPF3>+KN zK|@>XEd3Pp8jfMw3d|-A(J}&Z{GQkK9Eb&DD||GxF=4tyU+s(DaOhC3wz~EoC?o$W z)6fn3i$_(-{4YJI*s>zugyR%=Yz|12rPHI96K|O6j%+RLvg|ZR$qMUFv*DEL4510D+ zMaN4wy2x{o%q&S^uQ1W9bnoxv!#(Ohxt9vzEHSgbGzJ!lN%VGFS{fv#pWl%|dV03s z2W|#@7)EuUZewND{jue4t>*ahVkb4>+{WYF!qs;Ku3ZF*_j|U^K45z$h2zEBd}HHA zjYfxGcr72KQx zAeAmit2uK%ymx&3FIzwrt3)fAFv-q!t@n5f&Xj~mKu`dA&B_kVzT5Q9ao%p)jQwrCfSilr@`@CN_EuXFdm^PF6d7jnn z$F074DCC>b_7@ZO@7iU5KzRpMgNLY*sK-qHkZ=tFWHJ+X;m{GBWSX4qUN+_*$Nq6`js^!q zs=Pido!q!8{Z|91kPPBxNmm^zRg2I~xruAeXZQ_uGL!@qTiaf4kF1#u*hy#>yAaf7 z=>zI1b|(vrn{C$FYG_5Am+$wd zaP&dkOU6cu9d)yf&B81FU)ynTp&>I-wYyCrK$psoM>0Of)`9w`gRzGWM}hR<(_bbA z3EA4*QdP_2DgF46cL`l>0*b-cC^tM;8h?T}R@)39Ys! zZz5BM#c6kz-ingkOHsnPSUI=DUJol!^ki`)RyPWP&cMSMj;X5Uoky%{#4eV6QVwBp zz(AV+_h(g3;}2$rn>G#iDWi|;pLaJyP-B=5XX3CI6-|Vt#J6(iC%S*|wywXwV}niS}G)wPQI71(9IIGugjLtlgreUUJ~VO6bof#i(%`@nC@~ zmP}BBXmT#pt+Zw-UmHbVnc3QLwIB9qHAg2gWfY0!Z>9>qKfG=BR!U@aBOY&mn^BaQ zhP|&?@8%Y^6M{PkuKI56%Xu%puhETIz1aLlW&78@za zT}EQVU6K}Iy9w;ryUErD5_5wRcI;`nGK4N|pLwf~>hoG=Wt_6^9e$_|%8Jg6mwnso zui$W&DFW2<3tV9fJMC&#k{92P^V!GTpEqR|-O(&&7U)V;jDc%{itP`c|9>w4+|IoY zJvnU&-JmQ~%(?XA=~t>;jNaX7nTZ}rYhKCYK0K={+~KksF&$E!)*CgL2wZC$S?5$w+G`_BJ@9?7<;|iX-~AJ_eb7J zuO!6f7!luN&YgQ3I%?T5NIRL}lW{wl8=rCC#hYxzRtaU_G~8Ny)US$$ROsArM*w3* zIAf6)Km%=%q7th zpMzl?yi3Wmi;)>OLs*;~TSX6}^d|E=M5j4(=F$ueOp=Jb!@K1u0eT50-IbDJ&L%?F zn^KbWms2P=3j&o-YMX*i9eZc(yyU}8%9YtHbZ8%P`B2Tucm(~SkSM>yQVb^S8O#hG zLc$PpD6|{z(VCBffpg(YOyV2i3z&ifm`;G>DcMiEeV%=x99}DG?1@J$I4OW0(-EOUxz{Y)S{o0G+u(c2Rs|ylS@=kSvx;S}Oj5*CI7O zw&hq~Kn9A8e}LIRGlQM#?lyGKi`E+2jb5fU_L4kKSW8yEsCtwm_v_CKJK;8445*bw z_vTGypLH5N?+?X^BL}@rA;k8!4>e7fy_mZ4>6|sq2kcZ+Rh4FrUqf=u0R=L}*(4sI zZw8Yes`C31hG#;XCYI>raQ?0!BeQAG9^;0FJis#=Y3T|pO!+h7qracuS$BTktJ0{j zCM${!vzR6!I>&39*E@g)2%j=UMhvM`0%0RPsf=3>cZ<@J?bil_2QprZoVlnM*oVC{ z9pnDdUKPjLB&OQik+IUhR`(;UPNq39vMMw?e+5ciGu@TQX!6BuYqtcUXRqVNrx!1V%e=g;Jvl(DfpYdzl1>dw=m5<_4r~gp1%Z6a*qWI?-@T5SdP4>eE7#aYwN8d zMWYX`9zAr`afwl3bKS0n)0TN<^?~OkdYJJp)ipFe9BflkaKjK^Mh}}1Iuo$G#Qu1i z3LW-}=04@qA6_I3ySC<2t9U!tcQ$pB6>btHJfY;OfGrzN+Z_p}mgfpKWzj!|)RdeW9e4JFH26RqfiEcpTqq%Vti;mt}Vf3gv>$j`ZKKf2^ zpx9ru*uRMQ@rjO42gDELWW3;EX3KJu=t1cb;+L&`y?fjRvZE4phv=v)9bNafV|X4S zN+<3znjbGsQe9OaSc2z6wVay@W%*Uy%3IVh=#24le(@e8d#d0>7D-C4yA2y=9jynO zNGbd7>L5+cYpw|WlK+jhjdDPOBC$}>@{)&0;d6od5eLpzk^^tM==JE*dnLq=g%G^M;3&C`=uaOr22~*6BFfxNszb>ah-X88l?I3 z2~9C13r&c=csA29-giLss_uU(9my&!CJxod z_6!MqsVIgJ9Dju2m;#PvTd#+ZNPXJHdo!P(gfS-rgWQymFDW@r{a7Jhw; z$V^z(3Hs}Go&qiajc1ml{u-N2189~06(CQy2U z4#lP`haqv{zGe0A4Z*6uRXWRiYnkj-hDERw4MfW&Uq? zLY*AyaZ7_UQZioWN!J~Ys=PM|cy2Gal}=;ALJOIvETSb`{V3x+N96L`8cyWL>Jvj8 z_~54PWGq|n-pOb+dFx@*m1IuNNwQSzcV}EnAOS05raK`p$7b|>2ufls6AFu82y8h+exMG z+q|9ust~S5sHBo=58++eN}F!pyjjn?#y96@5G(TR#(I6A*0PHu>64W^kmIFc)^1~{ z^!eNYywOYLn#;I0BsWr8vI$i~U(0aRx#HRU5{<$1)WNs*fBU4=4eP^QRK4Ct+B;`Y zV#A8N2Ko+R9JPfxU6??vN?HX!PhUk)ghWn!$B}&z4>FJG`Rm$X3@GSN4cMk80j{eC zP({fcF{&t_hU3MN>@&m}?KDpq-zh)7f0r4Ff{_0-V+ypwAxk+kq9fdsIY$WAX!KxO zmm5e6@4UL|d7_Sbxv;8pchPVJ2PBgy{o`Z%7fawcXr9Q6&btC#(&5y>p~C4N%W>-b z`7i|uorvF=Db3}=8*fqKW*}9o?q_q-$@n1jiH$`ANvUCJ1AoXt`0(g%@7~~LE|$Br z>EUKwc5yCs1MMjy54#?goOWs1lXXCz%Y42piShBJ&UlCfg8{j>1qB672@84u=}*2& zPkbKUa{X_W>@e{!vaj#u$6>?aZKnlw-G=^!Uz~H4$y)0L-kBgX$v1^}@%4{!y` z38&zEY1BIc$)ssZf}T-*16VMLfp1RJmn|J2J3Ax?IK+%+{mE0}^dBvP%s2Ag(bWjZ zc)7`qYHAs`=QX#|E#id3$t;qSdVu)Wrn)2!fq455yP_W_(io^TG`F=}?wP=m@cZMp z`}vJOqBQ}iGup~ZnHy$6)j|Hme5ShGR?7?iLJrq_@TK%t_Zqg45kW$TbykrxG$FpV4kSpvYMc?{4Tn#Ifh_%S z<%xhqC`0^B&%$a#?S~%P6&4mG>p?^vhD!6!2}xfboH@5{d;j|kTK@|hgh1!SB-LEs zTo(zTm+_t9k2DoJkl`}dqqJx3QM8%FN&+_+WxFiYd=Mi~2_N?O`aXS%#xzHiAL@z(59!v<*uI%f z&!NaP#*|(O=}AKFiuNx>W;Gdd;wxXi{@t4gyJyiDcKiCeFT0K&4J4`(;BQzJv6kBr z$Y@V34!gPfS^1u7*cFZ>NzSE^8ecL*(sppCj&R+KlVc#z1R+~e*TZw1<_|rTk+^1g z;)`M9&IR#I=Ie!2N?;Nyl4YNEGJgQd>5i2Wh}``N`-yz4m$U?#_`jtMOjg)ndxa3~ zft>T`UF{`B4vN#eOEG~P7;paKVRB3Y{)aIV*qb5o5=CGaqq_J~ZZE}$&@7HRCg)}D zT4$M!$+m?6I+p3k4ODw7AtKYU4Lx@}H%1KpSM)_Az!+;3OKGMRAs0acGe`Lee z!KS6%&)CT7&F%kL_sFnpk<+hT3+aLo(ePbs4$M%k36%6r1rZ|($@zq_u_Wh=+NX+D zrr?LoA&I?lQmqCP$ay4PCrjc~&~6!*YJxD#{n1zF_FenI$1Y!1MKCpIA_NcbUrt&! zn1K3>h;zui46XHU+GXv_d9|OYPo=wO$b!4g6!guVC@c8kAs^m8Ep;O{;;yuB@X*mv z)Fj}6D9CB28p#Zj0;k&TI|oT@Ib?^#CqZnkw90Ob@Fm@8bdc@H_-R9563jl*`r(Sc zUwN3&5kizpT$nUb&%U}M`DBk9&^uK585qT+Vg^{tbpjJGptdti7}+_a$+Y0?Syleq z;#|*R!&GEUq(zj<=}&N^k{FFN`D{c-W#vpI>`=gV(P?3w6) z?+MnJKBx~JxXq-)jU19~!o)oquDnMp8Df!ISK4JH{ZP6R$l=6ayOjeG+Sa>vBLy2Y zUj*wOv&!2gr~MO1!8+AT+UV&SWeG z@;k#bXXvBo$?oQFvrK>9$*Nj#K&-aM!9x~id72+@)@=kXm(H{3PI7@m z&gs90Z~Qe}JS0b-yXf%}+HlMBJApm1GnZX6=18ZSxI@0FPhBUhVLM^Ud+6%!3)2Of ztkAz1SzhhI_iqa3q`@N+`23^HwH6-*VKc7aPgS3(s`?vqT5b z4`~YN&7G@udO3rkC>+@K!$Y1nCas&%t(T)!>`Xxe`l zkW?Xp4TZm8&`ay_a1Eo~LAo*IV&G$m+jQB4-Gga98)##Ah%G6-Is|vL2=ezQ z{FFG*!GwKy87x|;7lPMJK*}rfbdzyWZDNooW~G9Yhxo-6!206lUOzRCZumSw;=(w{ z>$1kv;rxuD$Pz?MogIlI^7PXohbB{Em_i|-rzNZWZE-xiv?9psS3@F`%|xJf5PFrY ztyL(^{fwl4Jrb5|MT3;iJycwl* zUfnc|K)1aV>FFs&&X7NVJw{G79**S4L#~#;cYLkj5*=rSby-gK3lLWDs1jNt|M;vg z*WjuKY&&`xI-y5;tM$goBwwD}KCt)SoyPB9#QBDEzKL{LK3MY>^;T4T%swV&W_MkU z$5BeiyT_=<$_4!7xn(}LleQjdt8&y)PnzD@Z2ux`Uvfz=XVwHH_t}ksh=(%pRSpRu zT~Mu_{qoeB(3VS%?3Tgq?`IhOe1FMn_=5L!r`bzXN)l=rvIuv_ZEhbfy}D5@MY~+_ zGf|a*7GJXa%}EieaKL$ADT4%1lwuuBxaU`L-pKvJ?P;&04lB@_(AV3p3D2KZ%*B6l7@xh*3`6@^NZTDaL(%8qSFTq+8`V=*sZ#X zRsX~efI30+d5Ou)eB;JiSL1ESmeRx_-7NHyURXMk^PS6yDC+tIf6$81K^bOb$gvBm&5z{z|d~xk0|l+I!}0&GE0(n4*5@H z3AAjoHKSO@`jQxo+mn+1;FR`;!_)($;*#tKP}#HUc$Ta$aU2c6C(N$51y=m#4`Z~A6HF_2pHh6_*K$MG+56sKW_rh~Bj{qVZGpb=uM zh=lCA_~DW5(z;Ld!=<%#m|ws>$uiDF43X3#?&(-|yjeRE;*8Epn%IT=bel#Ct!Nf_KkX1;}(Lf7Wiu=u>(8&QKze5q>7GYezqn_RqSj0f!i39LN(nqEH z2?#4&tIPWLLx^HSBw$JX?n)Az$-Cdh8i%XOB1_}Y|6)$?{&gQzv(Q&=Drko7zvlYdVw9@({eTk>npA=+w z3Xh58YXhh#wiUUeap+eRp3~c@v`=p_=yENMAmqGlk)|{1G||b_X7M*?TY|`0X+rJ1 zS~-ngEAWT}_RD>UF!rV0=>XJOd!!fPpJe5|N|QsIM(2Yxj&n-OzdNJ0r5ZT*`SUKS z`&+k0<9yG*ru9M{6kAx>6~ovV@OCEfNGL1vKgZEFW2)W{Fu?Ysky;T=yrsC5d&hU@ ze&#%D^6C1Qhps_CVs-h~FV?*al{*Ddwz))IQ4#sVAZJKEfM9`_LfAmUU{|+a&CpaO z1Rr>zaC2P+sJU0HVivt%%c-ZI?c%ED#*SMkJK29*)-kb-D zT%MGV5{v_sf;96g`zdorC9t2YQBc@1nl0qL16P*+95Hrjyd4WtlNeY^-=gn>G(Zs~ z4fh=Re4x8*KB}+W;cDk^s)A!3DNGf@=?Pi9*;_!WtBVFl>$WFchD^@l_p)IwhqKk8>R> znfhNGa=1n$h6<=jCc!=Sbu0F@seE;Kpau#ej7Xowpn)6*{{KhRnSgVhukU}B_I;Zc zty5AdEta$^6%k2EMQO1{QnYH(v~M&Kg?5Q73DGL4kdTl>qC$lvm9+AIJv#IIpX-|I zoH;Y`{eC|0_p{vh{oK!NWp8PAa9AZc_WLo4e1r@^R*IpPdEUmNyCA5nGQ?iv!!C=uw4I9?h=|*)E zu`M`0W5AE~q(}OVV&rjC5argDxorf%>^0sMB&xA2EDs5Zay|V7tt*2SvOW*N26*F2 z^XoAze~_KsvZ?2F#>sW_)Jm0*i!eGaEgDc63n2ed)Y}wc#>jwl3-W8FazS<(WX<5o z9T^5jpC%=(O#7)TxaYW?AWn&kfb_*wAcc<|NTTmpGI6AX*IuC1B#;6E+E`#Af?d?w_IbUEE+c@OxL>i2Cl!vYpHZrOP;gSw_FZH#u)yR!Iq~A){ki5fJ9L7pW(m2^!_q??rq(TZYxom5dg=wK(eOsu_~1DmH>5P zu?mueT;R$~l~dr+Fap%pH~!&Er(8I4X}`F%({eGyf2BBf#td|7T)9msoCOI0><-`3 zM$c1b=VdVu#=W2zKaTjp$H?{sIaS{tB6#5pz?wj zl%+c|EknVE*tsh>MT1OeiYfgEJ&7#sw6G|2tPHt{UpYSyPwJ$NkA|=SBtLw1cbEy& z@%*d&M{3(7P^2Ms(>@@h=70TGaOJn_XU^O%zabO>lhlY~K$CC{{MK8ySwX?ic&(1i!`Gx>-}yjSAVO zrZ=vY6ux6cj0q!T{__hq#iB>%KD;_3ht7;V0x~;l^EY)QVKUz*&HyyLJgt#;cj*sa zhfF~9>N4;7+jDHuZUHwOKSmncvx4l}MMwgmJ`qT1JO(FyL422e$(&Uh#2rSeS2_}t zfmC~*-2Ay4Aae0jvxjkc2Hmu_+?dlcO!zUDa#0}w-?d;mBBw&3RTGfH-w6b}!8x_H zZ^y@dxgHkQ3LGPmG=6}-Jk+9CiIErq^k_AADe8&zWK30WMlb~rAUz=6<=%u}yH(JW z$0}wD;zlG`i+R=TjaiI>^Nop&coH5!Nw&YAAG#Fjab6sL?W!D)TsGUl9L@mtkb|qc`;mn#tRQ=!grx$MZu{$}h7z5=L% zZ8x)@xm^b&<3(EoH}TYbSC2EHKij~lkBrvV7Pz$C{O!~E(5(+rQbv@m`MxNlpPHH% z)d}JQRCCxizxFWt?QyT{SSIuZa`vjqeg)mg2NqLckN_sg>s3dv=Ry(?CL^yYOO!ND zK!3f2cCpGlGZh2jZa=?9V}VXl%1W1OXZ0svh{!HOSkhNXX&07#OajoYTnVU}6K7!r zNpo`3hvqn-429iMEgLnNgGsIa!1CaDrOtjl#T_Fj4Lwr)?%fQ6DtkW8!Qtb@^6py2 z&}#oM_jb*_P2U1^(dO?ue7F<-!^o)r9yjiXN8Qq4&9?Pv=C~7!Sz3*0o>F^szrmKf zIkK*t`!Rqozjf=@Yp?FF>&u)MiEBO^)M&{D^y_!$Y~yDXyU|;Iy0XP{`G>ZB^*q_A z8ARNdi9~)Cr@worg9(dIg@qje^K%Bgl8poF*1cx%%9i0|Ov;YQtJ2c-HAo`Ah)tE$ zu`EvCsXd7^E?fl~WE)HhXeu8aZ~1H<;wn%OZ?G%Q%A(w+Z)R8y?+RzL3C)c3CSW}O zVjb6{=JfEXj>A0Z0#=V%xV_^Q*SHgy)?Dk?6x!6SwvOQvAmuNwwdzx_ngP<)9Q1&H z7maNqHD(!H-S&E)9Hlt|aZ#?ZW1w|i8he&je*IuA1MX-o*jVFHkao^AboBc7efWN_ zD32fyM}C>$onqCfapP)?L06)o+uK5e!+zS3^MecXHX5#;uuS@|!V6%v9WQEIpQFas*8O=dFMHR2*{yfo?RN|lg{-1D zv*zBdThQ-4NA4rZRAva!aM@(7aMSY?JqD%aS!#EijX%K=r%j)3NihgJm3elwm1;NS zc}QZmq9FAD(ZkWvaRZF0*!)l()u+A=&aD`vqSAlBfZYfks;P59I@7WSK70Jw2azz~ z2x_B_#Q1f0>74Z1PC*xz*^kFo@R$1SdSz1me zyKMk`+Jo+jsUP$sIK@mu=&6^%)DIn@XdP&?-6yP=9+B(i?VSjssgUE9R9JWd&>Xcw z5>1yo>y!NB=Q@Nc(Z@CXX+85VRYhT>W@+?kFcdvzcI2kyE5?|m(MgC-?Np^jy-))&Q;v^ouu~OwoYV+2u ztwEX#*5oc^<<6y)#uHHq!R7~KBJyY=1JGU%YIfHTeTA_raK8j>3=u}ST&l;_INc#4 zE{S_!gj8g{XU8N@#l2Jp)$lrMT!AJ%uLtB-q@<==Qfc5geS`*#a~x27IV$Q5W5r=+ zF+xRMPT80PJC|LC2*DaRG-9ytF?9{o%AZ4yq;6nlcRmFZJ1XM4d!0O)fxSr@J+*=B zFpA3aCLd6u<9m><;@eXD}q@HSEG2x4|voGSZH!f1}rXJiL| zVY$69$b7uN`}8^W&cZP~#XH|>5kxR0p9l~UjUng0p>+M6q8_GXm=agl*4kpQ! zUhvOSOYD%iq_(_R6qmjWavC39Q1-H-A{CKV(b?olb4*MG$SvGlyAUu{Aty8`GxN}% zJEKOGt4;+9GbYSX5TyP3&l0MO}xge28sfH+yR!4{fOV_hXZ z&nZv_bP|^NmzI&;{YSiv2kzSA?jG)-V_{~Nub878vsq2a;OH%+YGs9S*YjQtCG03G z?}N~8-?8Il&S!wvWL4h-K!}f@g$ka-B%D`@S>m=BvP@KzC(qS|5esR2DN1$t16~%n z*lvS-efwOQI=;5x4yswq2S%1haufjv-_z7dQL3(B=#|u>zW&U2?yj6b>PE*8@w%iN zS&9q1?L`Dtzc%b&tX=7&mJqxJ@W)p&G<2}@)fjfDEO+->get#Rx)1FnmChZm`>xU@9q zOh!zEn zga|~{(D`^hN^@t*VsMzrCMJjHckty5f+UJG83V!$w#Ss^MGxSmtGt>voZ!TnUnrS;QdMEc?*6UINF{|K*inBx4 zu6AV)8+F{vHHn6{5nfkOkD-T?(%6FVP2b)B*UJb!fBpr7kFR*kuV~0@92P&juyCww zbE~Q84@i!e6tH%7-_D_}oBYWy5IUKCSp=57`}ecb^zrijH!ufU%Jl%Jh?wv3<=a@W zSi1hU?9_6n2#p>mg%YYxUri4<>XL_LagMHsaqRjW{{iorLdW_?DF zzN&XZ7i<>Ih7}^Xbkp{qbwOGX?d|}j@TaGYP9JbG#)tC_ zfwXpsiYJQVK45W_C;}jPo!Vkr^VD6 zpN`9hJ+5yW(19wpgk#IFkw2y7f`tq7@FAvaa@(KxLb2fme9Wq-VY7}4_&LHeZ9FCN zUJ)siaPwx+g!`utXaw##0K!#QH`&I#t6JAqAmB)34Vj06Rv=P|xB{w7A?M@s%aqD; z(^Q33EX)4v?Xh24&kG}~X zHvUgplE`BQT0X#t3`coQt%GBY{%k%iWF0N+74QM{lk&@Xo)pdGtz{pk>?6scXS4*H z_*9X55HF#{EO2=208Yy4(^Lct>F9^kMn({jz%H!Wyn%RR-j7kiJb$p+uhd~8#Y#6b zRP;(=?^Pl|D(4kz!X11N3VxIW*@RN1uZ}_4W$5IvNt8VmNF)r{6G%cUxVae(lVxmt z;BP!g78-j(lhf2^F0DHuS7uuv(hok^U0NS1Wb85A;j;XI0EkdWClbP%^FRPcWpfW0 z5RXx;rp%Yu`bag~Ol7xD0I=*oVqYkI-P`2mgu*4PIO4mreO^Ksfv98GuG6@?6y;3F z&v3VB_Q*blM@OL5n=#`R{S{TE*P%m`Xh0R*ck%6`=M?|&F;FU|N^UBuc2bkg$@mfU z>+^v-81q~4sGv5!bgm|arJ_|rn9hOlMapn5; z+&Mj{CtkdH^W>~ZgOmdzM3E79*goYrkZqsk5h2-%NaHlP->M9qq-E)G7l$t^deW@BW z1xDoD&VUXEe|Jz0zsqM5Rb~nx@adVdEF9r$;GGT)nXNIqAOx_Zli@fWyY{i#-%nAG zXO>eLb-^$S-<72-7+EkhVtOp-3GF|hk(-Aq85H{!$B7;<=WWZktyfWRL}SrF<2a=A z9VgsI8JJFhFiv+}V8WCxBD8)4yqG8L$1yn|meEw`+kr&4+FYIMpy#>c`t`8{RWV?^ z!u9~33`dI{CGI+tdEewR*iv>I>F|2JRJ1h}SLk`tdOts;+v|n6JEo_H=N03HX8oZg zMKY}Y3GN*3_Yw1kB-qOI4(Z?)4+0Y4(&|yS+y?lb>EBDxf|rN-w9)?JKs1oHh8!v&l@v!H`-x3|)tm7p&!697oGO(+OXnF#7N=5D z8m%0vl4&2aMmH2#dVeBEE*V@Sk2WYzVM_fW$_F}d0(xeQ!`%Hn(~HZ?@6(t{y)OC8 zKIU4UrJV}KAGa8Jx&oe(R@ggm0$l?o55Qbf$ed6Z1l6Yn93+8B^*V?rWM1CYsVetz zpN~cvOSJZj*%zYGyiJ=|G9_#0Y$|WaYmE# zaz*{f7N=AWcehb1PyKgOc6z0j;;wT7UDpwYX?d?;xA+W}c$jxuy>@L9QmSB`H}Khr za{h(=Q~!Qu1)4bs?J)Dp9;nSS-^Q)1n?`ed^yoBVj)#W_@Jm8p|FxhXo5jDRIgBPv2?(%9IS^ZH}4y&q@Gb<1JTM-)oPPtE3V&-w9K)sx@6i-@23>ZDy7ttR@06DvJ z#QkAIhFC$0z}8+U%rJHAeQ0d;oJcpstycD$xd;Z0E?tq3MG&lxze z!F&12l`AW`jx@Oy$62bjUuIFt%kx{czk`f<9(!k?dl}ulcXl)@8s@WU3(;rm6W9&m z*>)RBnAO;Ae+vTtP0m{Ji*{a@{{vcpo|Pktgzz7Mp#dSwq}3 z!Q1gyK%zvY*oslJ!sRFLXdxYdSQLwhfDmV(PiY(px1#b2pRh_ruLDrQs4-&{*4*{S zx($92`NH{bX9SDc@i-lvk8TD9liFxRV4jL1B^zOx)M~%_ z$xaQ)Wes(k7%0;(#pLz#hOQCCGqZA5EGLsHMIcLyfuBEr2CCt4mAQ7=6=SACStS&j zp+Yo~0=}#9eMh^A;^s2c6iJ zk01z+iPqwkQ*w?{D#(E$YlT7=U2H=7#e8``vPV`Hxw|IMh4n8hOQ8q$zqCymAR0}V zC#%AJ3I9#BEIbvN9yOwp#71!WLrb~>3P$>p?Nr+$BtLl2XuG9d7-tMEM>>-rR*$}5 zwkivK;1usoZae-iqFRjJ`wkwQ8aCe6k436LG4Es%xK;JbL^LTbJZ{&)PCyPI)It)g zgf#V#+Ut@D(%541C~Cu5xCqcU(zUJlY_UQ6j^3`=8&f0y8myv{n45cqU=JQG&@7XT zQLE=kobPiMJ@XF`Vp#)IvD`+U_I!gFmxGcL0kq_)qFi!L*-X;c@jB`kUE0F7MTG#8~;0K10>^njvDmQ zeNu$MyXO2bFtrC#TUc1QCa5oEY&3If1bLIH1za2%9-uus*T!7pL;en| z2XUF*NoX1}dIZot#GqW$9&VDYy1zX({8??PxS#pAR~*lmjCjGal4U z2Mh>uT{m^?m@%G*4^P>&>4tI3M8d0#0)|}=M}mWT=LIjR6s761_kCR|M~uV3OO6Xs zs%}{q|LxoV#0{8*89PC*a9JsQzOy<%YhIRs!;c;+3Z~B(I z!p<>oz(WQQ6G)YuCFZ}hc(iAPYWUJPi=w`s+hUq4^Zy7Yfs^3|7HIe)(F1@+GXj97 z?7a^Kyz6VR^-oUT%@2#N2_;2RJctkxht(Cc`p#eBDnK+It0f7&w5)1>z1!S0$KK_^`I;g1c} zw;#xegAQoCm?{`0(Bk2b#$O8xt@uw1py@I$Ie(*(lGhSTOIh>s?%g}+*euNGL~&)o zmU3Zec>s8jJULnCbM49%tP!WPb3Ja(65a$A{s;X2e1BH$Y`CpcX;|o(=n63lP6SVc zxY0C^AD5thhEO{OkvI`_YD8}C@x-xAZu|#n4344l7MB*+WIfNjm|4xEv940^nrmuG zFLeiK7>p>0&5|)@hKyKXi$uUh=dN&kB_{}NKD()9b25X|Z1jL-qWQC>B&K1BG|t7Z zT2{FbfF6%EJ#QidhCIveYtqdKgEHVCod@5%-EbbdE{A^IKF_LYB}M)I8{}pl}~iDLk~@r`sDTB1!ZDuD=&4g%!A)s7OsnSMWrJaE z2Ir)EK}FW$;VZ!$;rU0y9HTHsGiD4E$1g_S#S`X#kdMd)974oFC_fbS=Fu)UG*Zbd z&1FLxYtSMuUzWe2Yh_TDn}S4272P1Ugu>zXU%tLRxdCl3Dg?7QOGbDhlT^#AyyTQL zlY%!k7HeAJhASx*!stdcKe6+y*g6#y^50&2a-DqnKyfS$`c*W0htuaEt3H$VT{ zyWUNkHWkhvjDm<0fXoQj8fwI}*nV-r!7>tv{Pu-w$BDdvaW#)-i`?1$W*xAW94N+b zl=_d9Ue*`qbpndxOe3+CfmXT))^WhBPhCG+yicF3*dHsh4{|~DjowV+s|;g7Hsdoj z9&4PPartS(Vyb}Gx%M$wlzc#s=8V7)RTosD(}xhIV*wFSQXEA+A{Z?QT1DkfyWw3W z%7T&{G|m+bHszafz}n%RJ9QG-^#nX=DGUu=9ia$hq6S2M2o1d3MkhgkIDF2y#i5?; zzDb3{!;FT}gs+O2-(LkJ3>1bPl^ahNRh9F0`j!yWN`Ov}vMZBMvGXt|2% zER;OjP0aq3JqI&wYQm&N2?+o4~n1)#eo`5D1dJ@uvkucqKNWgFzl&&qAfI9l9EOZs!rucNESLsOGv zL?!x_mu4{L!?Xq-Q8al{kffxXpLCEnYfFd_cnJ+>hb~=mPboJ7FxC%z$&}%1no8te zyTNNU?Q<8<(^2mAA>|cDdMYBYKGvi@_!2Z6)+(|H57n&;yd_A9E@hyX(j2}ZvBpMV z!>+?`y{Scf$78t9bIG(*cN_b7@o-Em8d&D6!2NowEUr55WGBiVLCz?JsSAf5$;PL) zm)nn3y*9m{#8Ix;Y(PiG=v8Z|cUy!I+$4=RaU?7-iHj^zXVstVKFw3UXU{#Wu5zn? z8hiyj2zB_W`JRI&KFeJ2o2E7s^b%ODj4~#_8OtY++y`{|49*J$?N@7PArzJ4T(u z>!mT=w%8NVMcvm7w^`(XD%qMN&w$M#*0XB@9?rG zg9uDS>?Eu%?*RoE&KQ%IpWmTfyNQHhatgqR`WL$(A}FlERK60K61Cos^KSbiDNSYa zz}@~!Wo2bLysVRRe;rUzEX!!Uwgiuzb$$?N5|jeQI5aKX91s?r%@<$<$vA>S)_ABW zE1v<1{X`!#>EwK%Ptv_KWtpwHG5 zhRzH(b-}Qmq1uTQy-)`lPo2&|QvXXC6kC|F+d!$Gs;Z|5yD7|l94=c?*Gg$Ak0#l4 z?%d+HZ_}jV2rP1!$b4xnPZtfFEX5LZ2OJ)e&@G%dvQ9Uz-wr&{4qyi}#Cid0z?SLV zx#QREv>QP6Z7Cvh3Gj%8o`$cfPE*S$XkRp*mJ5yP4@~fCK09+^6Y}%@*b4CDLWIF) z1Rb)OCNI*mDbZA^Ch+3r%eJNWy(Lz!=8$Bz^x{Utcd3z;$XBC5&$k!TNHVJ1u4m75 z0{Im>2!(=FN^nnZ(gy}66y`J@4mHNeP+gOS=<%Qws6}MSN(m)2FZPl7*ClQECh+9^ zM~41Kt$x#vGmqhQj{jEHv2x`6kYU~|4DbeT1gm|;xPs;wUvz#6M7b1(M4-lom)$&^ zS}JrggJ(2hOJ{i+fwe-42%ZH7NXnF4di_Wrzy zDtb7oip{!;ttH^DTJ?fK+#03+w4oqh;=Z#yXKceQ^Wn7v2j8PP*PA}Qm@pzIqH|}7 zsr8c%Pq@^Mi1UKN_be_Bus_f)8+G5V{sps^b$z-xpK=Z}oM*o zA`-m43ktL*<43~t^GLep94&bE>^K%68g_M8u85nfK5_jkR;z~i&{H@W7LF~w%=`fj z2_+}Zj1-RL3L*8+Y-f2Yf)R8ZzIdx~?p5Yf3EXP-%Mm!y+o}uSG+;pT+3#6sI~X>L z23n*)E(#85N14w5%HR!AiN~dUgqQH=jv6sB+DW(iS~qH|kj$~~>i2P@$BjD%y(a^4gcF5Jsf7)q zjw^sQKmjGxWU3);arJ*r+GD3h&RB$_s4mT&imPEes29E>Kiq(qm!O)mkOK%&bI`KI zD`Lj)04k!NZYk5GA5YdR0zxo~sMX(xdhkkp-FNqpJrGgMaC~wa>_qkz89!B%bckp8 z+esA!Icx;tWOC&AM+6 z0M>C42jQqFo%^#$IU#phIvJ7?Gu85+j4!?hlml=L?AG@eC}iZRC=eo@z@Zc?>=@wZ z<2qMwHvKYwRmqW^;Qv4c$$lCRBE#e$atyMmGyY@52cw?2Oa8`s&$Xexm2qs&Z+g4= zsW7?skXlX!35m0Gadu{?MifzQ`G+nbzJqpP3xX^V4 z^XGRX&QNoY9BA>Y(4nmb0tMn<1vCDw8foEDq}jyaN79T%f#^lgJs8sjouw%1I4!Qp zHnz4MNv3voZ+gy2=_eh-xmn8Izez^`ox+cix(+C#vxmVKl|wTlFUk#I=7WXcQ09WY z;ZBfOvMWFWU!P{&e#tpH8UeMKwF4J~Uv6IIe}i;^Z0Rh{XqNoGp_t%L$9(15=e!~ zzq*XZj}Q-u(M7;3dbuHF?4Pp(bwF#W^PVFMvH@dy`}Fcb=HH@wmG$>ZL682D@l%<~ zrBFe4==8YP5Ev^EeQ~d(p}D&G`^euoi^(}T-hezEyL6fBwCx_GyRUBwx5TZs`%CUF zmuEYG86&-g&%ba9@W7M_CfI(VchxsUwA0nql`*I_Yx?)=C-V9x@ey1O+zb&fZla(& zpg*H?mo9{-UeI7m9vQEe=75BLrJq-$n4Ccr8sY20Ohf6oJ1}p{TJzbzq#};mG_TTE zLP?V3K}yiRERVXs=Jbmx+KIP`Pg1AQz>_XzIT8ccYjxE}HsGxZKLj3U(n!XEj9VT; z>17K;weIaYEDzdZE~3p3jkClCSn@XBef>NYao@U4fNebwTIOolE#gCYK2%J|Bg7-NK!6a7B>L5Npi?DQzgsyQ$mF ze0DII2g1R+MgI*Gv*{M4R@#;em$;yUR}lkWiQE=xd#j#fusRmM2W?Iqd$L9hnp8da zm*SXN>TO{BVQl-lli%*(&mcWX#JQgPyTl#FhTt!jU9B*a0X zs>(@6gajm0P!bt zoh(UO$==EUkICQr5do;EDK+>%8QQd+dZY^>cNdV?gsOzG zSA++Fc!J+9-<-~SMTP~J7%f(D)UINbHA|HX@c|ak*EHzStbv_KPh3Oes(Fkd z0Z}0qNk~dMSGK(&lZ`w@9u>L-w^y{Va08sgPfnV9nu)k;$iOjU{A5Qx2oL5kGT=td zbNS1`W%9z?nGpk3>wZ?bxloV=be`3F^C#n8n?GUIuw>@YBmKN&*_-6&!fJpb;Iu=C z8|C5zD4W-j85sd+CKe8Y79y1~e^jdl--Hy1CFxr9*T`fv*Lx5dfrSC95{X*WjggGd z6U!<#hjE}me}=)Fi3yc8LL6x^$Xm0Fjh8%5ItE)l?$g7`H&|PbhUYlH4SpmtD(YMI zJjw-vFhn+En`$6(K(Le0Mo=f~s3dit9F&boFBXd}IKw*Q7eQRZ9?B4vIEunADfRs4 zF)gY%;80rbV*q4o6{=DZmJ`^SOZ2Dc^y;vTHWv?%oqQw?<#akFx7r&(EAUU@#yNwy zU^ggk&>Lus@`#-RkPD&QK%iuL60GEO0o7?tUfocFe*>>2$9x5HJRclP5!w_`h|isQ zW{YM4Qx}Qb1kI(_r6OVA;6yhyn>`B~s`oxe-_kTLFT9cW#?paQ=T(2z^81Xw4g3I+ zV->ZfYw{6F1+oNw|9UOoaQ$HA4@$#N>v`!()fSo|(aQs#vs#IgZ`Ssc5i^3s7o0#w z0LkFu9kB0O1<{IP0r$Tbl(o#-boYL%YFerN6FH|4tiBBVK~xIaws~X>kUsB-K4U)x zJSTnzE|SDho9SQP)O>4_4%@p^KTx$SCS<(-MzS3XpU+OMaWNU#Ni;k(daIDRlT5oG z8$uu>D8Cn*LFfRqFV0tc@YWVA=poINaq_;_-BfoZ_u3dXHEx0rlbxAmt95ElaWu7u z9sxagW3$JgfxT!FI7<&@8TVBh8Rj0uL-F|W&fcN&6d_oKh(Zdz0!$rWzG4_=G0#5S z-qv?UkeKY?K7N9@>gAd^&r?wk5&#AQP+c;wP!bp7_g`gXRTR;l|Nc91!-mm3A*DI{ z)Vpx>R^{_Nz`mJ433s7QOaCBV-0B~b;A+O)1i%KdIFK#6|_2W2WJoLBny)Y zFxCq%|M>JUIr8>wqw&@zrT;=cFd*SrU3;{lJ6EKdl+y_BE{!)bDK-PNE1EjQz$AE{ zd=65*QonwG0&EBt#DeUh6IwNtPe*Z2KFN%^LQXcI)?NYPUcb(5bttAyi=Eq0$k7F- z-TZBZlamoP<&-3^X%U>(6n&-apceouV@7&1_asy=WS+Ts_RY;3MIkF>2V+dcYsaV- ze^QO`8y~HZ$&k7qK=X>q+nP)WRHAlCle8%bNI zYnYMILGwu`%Rk_2A!oh3ugcNUcUrKzTAW1&nALsYc2paEhY$akN}$?9Yxi6^Zab1j z)0`7E4-pLrUzYHohEbE_W1QEnJ$K{AG1@Bn{v|%6`|HW#h;d(@ZwE^Cq>qldW~C4K zx(oQ3X?_}gn8NhWV|>jWHAMME7h{c+&X5IH{sqvpbaE;xsbX@Joo>VJ9`<3HYX+6{ zMLu`9>1@ipz8wZ5J`>f$UxQ7DFUvYxpQm;%Fe*0o9HknKKL5@P$+O)bcW>1MLEGq6 zFLxO0=8YaTYB=Wpu)I$~EJDxOI5&ao?Ay|H_5)VB&5*j8nb2iBcaN+A^Q(8 zk3GP0UYmmnJvgeUP|q^%08!~oye3B{eQu0LuheyjW^N|r+Esur!e%JY)z#Fgpu?I% z+_Ad%@5t)fneu4-SO_Z6HdX6vW8+EGlb{6`zo^(wV)EbsExim^iRmW2268Cz0goJO z(r|`!fTqS_KQ!EaIjzwKWF{hv>8P9YjcyQaK10J;W*;4Q@E0a0$|wx6&P-5SU9CB>Uho8~*U6DWLS*z73eL_>zXzSeO>P9t=rXn%-^6OpvhxiNzLFu32h zG&CTn@i!om7DgA)GktC4If5+I^)P}xS-{K3$L6!cy;5h4ZtfAJ>9k|=UOQDHx?^Zi zPtMox) z49P$Oib${H$Df`3YcRc>+$vBrwdGHS?>Bj?{uhi1ucvw2wn4}mp$YwKV%{=8hUpL+ zS8|uT#A?8zAX~pt*yyyP9++q`up5eXzd>UfitL|sDAZ1UDa>eGsT&`NbzzE?Pn${) z#SY5pQzCLfP=4$tUa+e`k0u@Qp{4)NLn`u2wLc0Rh_G2BM54hcL_1=O0Ps-Z4C%%8 zvlI*m3}&Yjbr4%$!_QfjBW3JB2V8 zX=jXIZ*K|)3Tdv;U6Rl}h$m1=Ln_zigbf{$nuM6rAP;>g4H5}@Q%7a;yhM<7S zWE!b=$l&)%KbZR8@Kij1!QL8nQUW=L3etfkJv-+QRv~dPnN6Fqn>heVVW3#4(Q|HY zabwM-_{h-S6x`V0#YNSr`GNtF2qWmO{6^f5O+gy~9hMdR>J#)DMIjY*ep=iBdEbVZ zGrB{x!PlP0GM}*yV&3c?0n2_TuCzi@D-KpTi$QP8KG=)&i>vOml*jULAia1oV3X|h zbb?tIIks530SBaaT9|so-#@*e-TnWx0I63a8m*rbfS<* zqWgx4JRp`fz%8^;V8CP;cAcDBG zC}K@E{oO_Ke}WYxBbbUH*_X^Ji#%eYqL$Kml6&8Kgq`@(kHgNaFr4U8taRKj1dHI7 ze@-8sIPUk@m9!juu79XyB4N8lk?QK|8le1p-I4q$&*5vn3K9VT^)zi;{USXyzC080 zM5GWL`Lza2fF4T}2Bat+2~>^anPiq4S^+1bmV;n53^6?)7FNRHDgcmX;OOz3Db4H6 z5eX8_j1K6Bh2+>XJYPnOpf;sJ9q70n{t{pu*y#Y}4jvBF_;9gzxJt%crM--$0&d*{ z&|rE+%*G_ocj?mQ|L{%FpJXIVxE-3tSyDdFXRq3LNV;A3%wpj_2p!^|B2G*dhC1EE zOpT<*X?bST<;R*aJ?YQochhQq1T}$&oGQX+joC*U6iG58!LSF?6vl0QuF$av)T;@7Xm7!~Ax#rw!Dd|8SP=i;Q+ zAlq2l`A-Y^(U@wM_8nR5`E|?bX}HETik7l zDKS?qOfIdAgi(Adkn8=u!nvVmHei}e1|C3A|259}OSC4CypC%li%?0---LfNUOr>F z>)Ffq{zfH>%mIHISvxeuCAJf&0XkrIFSnGzO&NiL{?G^3@#;ToODF{dedh&>IDMLR zKCj`H^jD@977xJu@4`492pQ#|%xMMlmKi5x{IcYVPbpIZX#MTIn$b4#y~d3jhnvjg zz*!pWJ@PZYFmDYYb(+q$Z}azB(>%r2L{>}DhJJY(2|dXV#5qNuJLEq|`&X8NG8365 zmzBNgA_t*DsAiq+YP)r<22XGL@bPBUPJGLbz%+z69z*hd{Tpu^0`gJTZ~6jDK;*kC zXmPQ|ZmAx|0ES#a5!h~gaJ26)*(*6WKW$wcxQZwzkeT8(%9`A>^F0U3)}d)wO;7;9 z8yse!>vDO>-lF^9(MY-aNaqm0RnFuC}$Y@nmL~=ON9tq&S*Q@rw+1wq)_K z3~^*-8JvL7^YZk(&ACpa*%id#GmpdR{ zT(IsG69`dP*8SLkc98;7Y?V&pOaZv+)8@4i6(`Wgg7_`R$@U}IJR%Gl z61u?24#U0m6Dc4eZ=60Y0A8kYQ6*hM3EJ*@liwK@Ow1XnQp$UVW|s+*z;#Y<=iAUp z_CyZDqxzG>tzyPCtYmCZ{+2;+kaz? zt^n!$5TQz#gc~?`a4}L7S($_??sRsUg1W4Td-@b=-d*7&S%+x=JN+x219R*LQE39{ zg6{i{u&nF7v9@PV>zMJIetb93tBTwG@Xtp5+WlL2=$y%2L4gI z?aaWw&U5@a?cBP$(H~v)`!w>L`A4IyjjDP|z6KlWuMFN0QFl1aK&f?xt;*wt72itI zPNet_P_sQ5UAvena*C;`Ps&dvC=}0>0XZ*fuvFpTEq@<-UHPVNk5}qKLw{4meqT} zzws&vLw9#t_T{ehvx2Z@-j z^>Gb;FCjp%Z1%x@#I=5=I{C$Mxk6I11Tcu1U+rr!iDS&bKXPu`GNuFWh;Xp@}=LNy>bI8OE4v180ZGMTxn{KCM1q+tRL-HKy zLwX=oEHypz|1?rGu}?v~B6D}daqcoxgagZOH_WKb?8nVx|GN)Rio%+o6l!I3W82N2 zhZ#~K2uRI}zpX?DUvC2-Oz|cZ?2y4wnT`a6PNLok`I$#{;Lqir+Bg_18s`rsdRujUS_Rcv=T;$YepIcOBsuKf7s68DkCDKk53XL2iAg0_+okM?-Y6Xw?dby z!tpG!H*xe@?E*W>=hYz$(NN;6>$YjuR5YYiZ8+fYOhZ3^gEjFR>8NZU-%yG+r^P1Q zlP$ccy}TIw11tg)uMe(rtC_@86%RhKZli#>LxIlsgs2Gm_P-daGn8%xSoKlxgx`Sc zO5yMlpFX|brf;YleIq6}QmV?413OL6kLlf`M;Ze;qRk>)|9%V98G|JXX!kL3hfbV$ zz&}$k`M82RiSUN@XDPN|KfV{$DZweI*Xm z`vJ%xeis#;9{*67IkcWop`+=2nR^kYdjd47+mE6B8%iGgcQ}nPAs>=o!2zOGQDp%R z>tP>HvZ|?~bQL=Xo&Y_wgWXNW&G&FH%r37mMEP#u z5ik;gnRr8sI+gN9I$JJLP1Z+@X4FvFQz*6&**HHth!;;=?m`9cB`O}N_E1XlaZtRr zUTTcoZ6$v%HbAnVk_o>wg&+ttv?oWfEc%CbuKr|w;hCu|WoVaY5o3vHOLPSA9mY&M z;#HznaVf2ci9#~GD1@k*kjmUaMvkMZD~o#!%NF%qcBt~WGN$na@*>KqSDf`H1NHB}lM)K+Ci2?U?bF`pG^OcW zQE+9FoYJ80kbLN~)3io5Zy36NCAc)06O|Gze;U6|;OOoq%^x>)=T*(*-sU{eqSl8y zL?Ah1`{1!sEH%?ER&y#Ghb_Ru$~Al#Bss%v(vCLW(msM822_PQML}?1sc|}%3wcADnmZnl*iO&#FG6drmb4D z#u|s5A@iel{OS*uKgx*19T^XS`eF6{gdG`BMN!odA+pxir~Vq(0^Ap$8X!;x9`2kS zF@y~fQOmNGgp87?H|BTbB6r{w5)oKoO8BhkL8?B&ZILdZ*Z6K>i)#njn_e&orcr%a z)(!z!z7!v%gyVX|K3OoLYb!2~7o!8@4B2ZFU-xY=;1s_wApf<=Y`8K|jqKp;K}1FY z`p8IqkE9|X4&vPl{Y!7|<+htnh4=w*GMOP(f=(I;dPckR1uWAcizP3~z@aAJWUdMJXqSQr6*2wEXhMgllb%G_$zji|T2 z45)|@j0RS+0EL0L^9S_0Lr4JxuDqE`R38EN35F^Ieo((kHP3?=+|}YiK!YeLE8h=3 zUhOk;gK9B@H7{l2Tnq0P#gmHS8H0#N9RI0Z1BjD4b-MIFG3HD*RdIKps3Cex@=)zX$jV<#P~o(sS4_~?9h zJx{yrbFHCyzus}EB$*x_H2Vw7sE`Nh3_aqn-i1*fniV0>{+_%GRDN;fO$~QFN=B-| zmIQ^`xCflonKN(kzTC^NHh{~w>tDZmCEIejn+&#GTvPFQ%=cD5j1*b0j@)20<*ya! zF5)8@fZ}z&zg5-hFG+@{*8+bK|B@+=LgP%4LF1i@O>tSgO4~=8vhfP5Y|MW`*$Rk{ZlAS{T8M^+Rc4Fz?zaM27AT0V+FYAepTNFCS_XdL*i&LD`C zoZN;(&C$h^>gHpGvqzXY#85^w7_=g3`b#zS z<~kNBKvkmQAks)+sZVRm%jJB?d4nnBkVenw@mHr#4MxRy#W7q!R!};ad35xcG0u2q z1k5z0`Tnj(t0Y7)E8Y5_E^t zD8LMO$(e#94KY^3)6efd)pn>#>7VtLA4hEXU`1;_r|F@bIG|XO2I3}_PQ#Es#vA0e zqb%>hSlh|;jErRA=XjjHW$s2t!~+lnv{HFz6RW>tz=%YpefRFE^kPy$3udUHk#lD3 zPx2|bPu#p^7PQ2BuEh)5_^)@gS7K&I^3k+k;fl)+4KRak)~j1lD8hEPW()$ki0+CN z7gFL~a9tDd20jTL8{p0Sx9fhdH*AAmBATVY;!Q%1Nml@}+YU=EA|Nu@;>YWn(VPQi zgt)FNIEbq|m8}TNOOGt)AW~MP(;bI;8Uv6@N=S#hl)=FGpP#!^(dHY{Ez)LpF@03}Dfkrsie0 zv~^R7gd%3AJ_wDA#me@VHP7GwRs0Z$LJWyD(UBvwNt&ojzfGJwGocqY>C1fN7Clr`qm%1 z(tRKak$XdLRO`0(mA|S-P|yHwROn|j4DuEAP&~-en&@5;o(YTla6W;lKGM_**vNMW zjg6V-bohSaTYio>LgCpaF2cl(?^;@;i8T=y{KJmwcW)2o%CpSpO!(xc46KX~`< zrcki;M-6+dnTpa#>=$Wy#C)CrN%bUL($c8^HOG?pEaLnCvP`Zwv!>c%2s#;5ymxR$ zA3`okaTjB?qIHeFKVK?yAS;`6zp2>K+b=M^$5o|x^gMCGqB4erqwZ8#5S;YVZGei3 zJMD-kw?!;WWUPsJred1kvhMo4aV%Ao+b%mmNo;yxg7u%(0hX82{^}f`!Q@8?tkEfo z7MmkIkm+Is_y?FV|J2gt_H#GVo1pV>-TW5L<72zaCm@>m(3?J_44|XG6+BBv&VrQJ zV%QGV64wbj4gz+&Y0!$X503n-7q#?qVmtYl-uQoL%E+g+YYV z3JsKgXdtNF%8`E$mx47QBKqIpY{HHPHvqejo`Af|+=g+fH3?1Bn!Tvn$oK-$qT6S` z=hDYr38b>iRhZUG%k#4OrYOPu0asGt=*DcOkyI8PBtemRoq*oh2FP;j#}^i+;%ha- z%1TizoCb6Vv9z^KrdgNGRkB-;7Nse5XU@$T94u>~f*hr9+$dI6Sb<1tSg6NdzAPil zw0bVJ?-mAhFmnUP$F#Wwh>{{w#w3Z<^WAKW^`*sJH`gfaEONH#+40>BEu<#q!bD%!;|P>j{|SdheZ0r&3cY8x+1! zFiOW28a4-_dC}&YznGG_>EzbP<;wNz(N0AZxN4zsBN2j7mUYjunh(@;9iKtFte{qHd7A30a@^Z zBERI4q%?1h-yd>5HfDw?t5_}9#)5nATsE7EpHtY0p`ME3fPe)QOWP!;cK+!M)NGe^ zwz+sMQS9X;1(}9&;{`)e8tR=qc}1i^&i6n!G{5TJE@P7Lx3`WKv>7X0WTXq=EW zzl$1HhN_-Di#rkUYcMBrtaC{-WTWoJ`@JB@0C#N~S~z!DTjykpFKG^Gax zl*C2HB+dgG1ov!G_*}=Oz<<;e$zTW$osMAiOxTvT1YbMU2L?B7DPLh_WkMCL*u{$% zo5ps#u6_Cx*AIo})%;w&plsHD-a#?3YURq{fMyL9ZUSx71MZ2;c5!1wbR7KS!h7Am zr)T|1jNl!6vOSh29ruf+Jkgq-zr4%b7w|6O<;2il$2+_md+fPCA=~fS=kkR47yp!j zz4`91OPxo9R?0vrWzu!ibxY=qTzSyLV`RuD6Bf~kX1J&*zPx^RXbw-L16p(O=e+71 zX#CUJpcK0N*}G?V|I-4HUu3BTAYF)YZ(sUaXbh`IRY6fz7n%|dhphCRyfguL6F7s%DN-IdNSnlRo&%4DH?Z#b+cx;O_UE#JNLJj; zfW%8=AYLY><(7tESeGVs`#~->Dnxh|N(%A3UB0BR@h0T+A8TgfM}+ z#Ps_|>TTNPth0qfYArb@ND^p_nR`wRR&{qPDo5u&))J+E$jYB70cP`)w- zCROZ@V6evgl9Tr80aL}S0=n?M`hg+e3WkgvG;bG|@)pNaRyGmcF4<*n1IsCX@#6oZ zbH{0jjYN}v?FWFFID5K(Yqn0bbMDv2;XlrjX*3z^|>ni7~dN%Ivt4{;V32RA$ z@;VvHPy=xuCK+~n538N>QZjbkfBd*}_wL<+h)gRh0&?uHG82P=lUpCJ=?!R&IW+;a z01|tkH2_>o#tlH~_sv%Bj1{#mEQ1LE6KC&?0Y>T1|&hNq7HxE8|DBUWH&osnCK0EP1=d%v(bS&@bMm?t)kW8ll- z;_{#WxN{ZdA9&0{$LKHjKiJYyT(Zx(f2PP5q!AiioJK{=#fm711|&NrcXNLdEUADG zTzgFW0C1S2pVtxrCBqS@O3|hWsXoC`;6Edy0ZK}&A~FQ`{xjzyqvidMq+$Z)X&h%l zUSS-dzW0pU2IzX`_@+&p0vpBG*NtWEDI67@p_y&>O}(t>49`jFDe5;2d$`=#d0(CC zFu8$5dY^F^@*ZKRyRx~A=zxJv2SVsM#b!S3BqmE@MJz=Pvjv8|2;$84ZGb7=fIr|e z=+EO$EAXs%O%o2jZ{lx-B1v#71e*Yp4$cufzk?y4V^WVQZ99mV?3QH!&?a-30bkb| zG%DwF4VF6Sv#2n4a~czS#gCEvzbtzfY0r}?%*@O$MbDd=3LG4+Qp*##`%RcoSTaJn zdxjCTHFJU9jCo(N_}2X@Ln=&d5jnu1*bWA1KyXl5t6%EIRwW8V=)=J{!^z%8x_d#t z2M>;3?|VI-cKzV^&s~}2IGmUM#$Em-^%=n*0-eNTX}S&dxCcZ8>DOz_=3zM_AsBg& zpuC%6g1!S<5{PAn{y%aEbc#E}CPT3`Whfjx(lOFAsNTvw-euW%?9b?RPKBu7;fqdL zIJbcj8uC)AT+9=L9d@_srcJS7Ke}&fb_26|Or{Rde2PtUuYjl*Uuo`e*q=2n9GZ=c^1Xha`KxrPb;=!%{dy&{x)ZBbwj}lwTwH&1?ID0}HW|}8}V*P67 zHQ9bzc?1ot>6%&7*iB~|icJVesu-MbV{va-g7JqO4f+`q|KR9G6lB1wt#*2%Jrb{Pu>geeh{@HRI#q@pV8%>}lP??# zB0^Ck3L->ROLL4*GAPLbv+#55+0yfbLZrRJiFG@_5+s{ZL*}rIAPlgLoT%irSN|^} zmiG2Xv5w{l>ZijZQGW^c55Vwv-8}ab(}It_pjDltv1s9f1tQz)y{Bz#L%Dg1Xw9h< z_a3k_eIh^jHUQu!*UdRv)ORUXpu;FEdE9ea4xs1%oBHed^XFzy9ajwRD*I^M^HYZK zX1F>5gBw$PiI!ig(7e(M6lh|=&LZU&M3ow|cLtt{!oF~Q^b8EbqK|*}CYOLo4j4JI zGv+Z&JF^`1F57m@?UI$OMP%s%gMy~HZTc*cY0szq%`BacuVBlGCx9_ z@;GJbc-gi%4|y7GmQ%Z;w*M*Vd@^$zNpvUz4I#Ie|bQg(}hF5Q03>f%^TfSFn z(ufYkM1=_jBnQlJv7--1l|MkROhbQaoov1}WCP~M#>(DUm4$d7B;?3(Wo-8s0)u>S zJC&>Eo{d|jo5&CuKL=7&3e13%idQrZFw!@u4tJ=dccGc^RP>FT zy@oU=Uv(oJ!CQ47d4MW+WJqIwVmY)|0?Hx^*ppX%zKVOBLhL*x{a_g?=ugB^c_@6@T zcGzo6J2jHtKE;HE`n{96h|Zc0>25~KieYCS3MMJ z(D&;&_I;Gkj*ywV{Lm7a>;E3XUisE$HF)^j+=q_Qn z5_?BekC0aXEjM0Vs6=!$_;jtUcj;C*hZLBdGzu^K!1`&1=S`F?+1eUQerixX|;~vMmxyk!zn(23ea0s9# z(jI2a4Bmx*h{vD@&km8#Ay;JPFY{EFsQ~1u+*RUd@Mkj!FVoP?eO_IPr0^%|hx+p(O4(lmtSK{<)At%7Ec^fWV=S}^>{V^eRXHZS#Gay3{1Qr2Dcb^M+`&R=}ja)@gLKNR2KSxu# z-~9TjJB;drrpA8B(5|A|X1pAgVS3$9&IvMk`F)TU;X4B^-9Wo77!s=Z?-L))pAL3J z&kLr%{!^yzvS-&ckR;s3jm@-|QMjqt4N%xEUhQ^9%S&;uyk|!E_{I-|^(UI5`5E{5 ziKWgnOE^Grp8%RHMP3hNq+b4Yh+YTqFUdKC0L&d_20w9^AtCLwsc8A|D{bSgKa~g~ zQaHf#nx3Wsii@s5p?+&~W&{~`G4ETJJJHw3FakjWL!pTOZVyUTmVCVs1_~NMEGEh7 ztDrOKF;!-T1PP!ezDLyj)SAz!FJxK;T85sGi2Z`RC4Y!a|J|d%UIzlWHC!)~dAXTt z!;dpOO6C+5)&HaEyyJS_+drO>Q6!^~gp5d$5h<%|GD}p1kW@w#LLwtd<}pIbYG_Hy zh)^m!Z6Za7R0u_6^m|^;{rls7-1j**_5FT6?{QtPb%C(Xu(5Ia(hdk;pa?loU;uM% zw+d%SZHK+St;9@=Uk4ZkEl$p)q3&cV9)zLAD*G5zXt&KJ+H#$~H>ziBo!cxjEUcJc z4@AC|zjU;4R=qH%;OP7cai62VFx4?4iV966_wO~+ljY7mX%JZOs0n2l3LGGGBAMpa z*H0X$GlZl8?@Z9Gw`|J2`*M;1_wX0cr@|!J418Q*6>zJNH4|Ucp4N^J!x_5bpJ5yS zOnj5JAE;gwa@0qoD8vBgnqS-&OwICS9VWxon3tsMQFiqk)c)5b&i$T?4Y zBSD!o9$@D&xo3+1R_%fN2S^x=8?_1{K5?jvM1yx(5t^U7z~HLt>TV45 zxqVU>d4yq8hcR}sJS&QZtwIdh=r+jmU;AOb}W+OHk&*G)$Ug4ORkq^c;> zzV{kT8^PRM7XNU8Mr*R%ysY>$wB)mivV$R|y2xKU-hU5(cV=cwPSL-tAajm*QF^t) z2*JFFp3mHTw{?vs)GNh}H8OR;2$u^@lWu;&@mNI~f6m%=&3Euq2$Y8YmUEA|kF4U4 z`qGP)fJI5jF4Y}&@h^P5Dl{&Go<3UN{LuKYcD*Qq{pI|eK;p_55hUV1rSN@+MdnfP$Zl|B+o)9tTmE{ z(DgE90SUcB6vQZcaq$Bp*CR^9G}=<4Bs1QD!gHZQI}93N%UEJU|06QCrQHK4K5|4R zi%Q`}p~7^t91l&FeSo=Du2IseGou&p>dLTeyO+;4c z=0wb))mEX|zhBLp%M`t03Ks_~`4a7Bn{j+1FulkJ(8V7$?CUI`Dn)TCb#<%Krab_s zVc-C)C2E#5j_@h9Q-E>6){vz;C0RXwR(IoOeXpZ&#(~jJFRf1IWIM(CpPt3^5N1F4 zQw~XNNcQ=ez4_Ss7gH>l#K6reoMn_;Es)M-C`jJ<-dipmIcN?fE|w_ycYn5 z=P}>FQvWD>|MZM-I&=O9njkZ(TNGljQiK}Woe9YcaiVwtmRn{p*$HZtAm{~vsPA9i zcph1Fj&@YQYA`?Y=%S|_3m`HV?G%?9y8ja#-TBLltqfrkk!1Z^ZI$no5&v7ET@x9%+r4t1LVDBT~CGZ62V%a_*%o^a`lG#iZ_ zeIx8@l1)X8@PeTHG_*2Q1l=8fE_Vb6m^{E$tEh&xdiRbvzuozU-Mn~(xd17KORB1> z7?siki8su(poS1mef#c(#L01T-#XVAhC`RD2P=q*xtPRN=tn~8YBzyLKuCsYBSzI;h$ zoJF~ot;dSr1AtR(qN1;*zlD8xluySlR97S9QX&3N7nb=^kt{I~7c z0R$%1!ILmbV2JwBhziJQUl{eiU5t4!f-4!YLwiNrVq{`cLL?}ou6Y*g{!1!nV9c8R z*+>qptj3ZXgT$810(AOgke$+n!83_o173<6G%B|+TwJxtG@MntA7Yc?OrDR}fdVSv zx+B3xlycJ40auBs!KP@~vj2)n?m{t|!QZ%2Q?9o?8x^@11<-0PAB=X<=Z|zEq#VyK zAJTB*cs9a;fPe|qW1zQa)AloI5mnnRdb%M)+A}`s^O&{hR#AYpXVe?9w^4CpUN9$4 zns=bm?=(ISbys(1h!&I6Xc(X=BqYogr9_-vR|p1F4v!IL5(_|YN)f8@cl$y~BS=yI z9e96He-ax}z6ttC6#?J1g@?vs)iE+^$9D1S?oT1e=8z>1wkei>N@lQfNzkEaH=gWp zoOzH!>r1Fd*S$lfN_T#7=MRRLzo~zeS5OXdA1~A9i_41+v~{aiGb+zTSXfv*qd6m% zrc1wmnWw!>hz7*BEf)~5&uQIVSs{}<0R2hF8($hkNr>u&icLbB&?Is`UiGL7Nj>Pz z%aAr=DD#`CucuYd5`TobxSOeTMiVVXYXyxP01%M#bIG6j@lp2UfW$GolgS4X z`T~LUKZ16kF5j4H+ee-yQ{&LK=ou%WLX+`${5zSG1aM1bO1&MCtH^YAnW4jT1OhsU zv76IPd=H3x)xCzYo8;c)lH@hSegB>|5n(mW+#8Z&W2Wzlp(qwn*AtZ3HaoxU<*xfK z-8J5~Ktlf|hmlYsq( z?SW<|+yow4^zuL@OJif}CUWdbvmp&SjjMzH9Agqg;6;R>=cW13xZr`1=S3XD(fFM) zc-_J4CAtmPO}+2-ko*cE$|X-2VJYXgwTla9uEd7GS-@NYsQ8k?z@!$-(s>C8fdz0J zG)PRcA79>hAR-d7ZUPS{3^)wO&bN_khaGJIV!_4qNNXx%P{9bq^T2idP$Pwu8i27+ zASJmITK%kK+Cdd1lyn!c_WJ!9m??kr*Sfg$d2`= zUpu_Hl9D}gSF!XE;_l}!qeh25rQ7@Q+OMy;guwEJ*nxmMYwGgSx!Gv5H^ZSP)7VW{ zAScMca1Po;~(O>^qhjPo|{+@mfw zmdI$zbo9jgS*a9&JN^CRXYXyt^=Z83{auKecKsKP5BwG`q}EW614L)?9EJt_zZT$OukZp( zYh6874mBZ&)m;`LsW)fG+^+=71qeX|D6lFiP!U$@t}vz6pz#!m-TU^)u=BCw#Mxk7qA~-`bR`%9TeLZ6J?^Kk9bb0h^P!=d>dT!{I#{UTBZ}JUoG@B$ zED~613Q$e4nGo@VaH8$vo4bkp@H+FKbn-KK6x2752V@LQ!A;yZGk6^3lR_bY; zbb{<|%Q#{PD{4rG)NeFCGLbYBsNm-N60ALU|C>fE*fm3O;vT$kCooY+`ZS$2Z2UVk z6>?yLW*MF=q8gNGf4JG6AgSa)AcbS8>V$u8S_I4q*ITxhT`!IVTs^5%&GP7(#ql{3%BnY}AC0_Y0ao$&_nH_>u$NX8v}5ryI0kao1|N5#gNpj!pxYzp3g(BO!JUBcrFS zUj6A#pGe{N7=5$D8vA6Jeo5!&JX1rGWwWyt+ly$;;<$|AqI{*CYSw5}pw0{)b$fme zzfBAJW2SPJ|AHi|^BW7f{}{5ph%8_ZtK6^^W8R$TIM7j*%q&Hy0z=yUcn zJx%IhnUl?e@9WvLS|;fuQ%)GWkwrsbCGl;(nyqOXV30Dd!4CMZ~9Wn z3M?#^(P_9wB;zM>?F!HTM!YsZ#zk#navanuj@PZ>&spb>^$yWaF~0#l+Lh^jj{Z{P zt3nj~Z~9gnHMLwv(}7&!pmUG_%6=y|v7lt$1Ii6ohMpYsN?Nr50sm%x?f|Epo_;}( zDZP=01_9DKJU+4XoA%nt!tlL)n+BpTql#9pT6O-2k&~R*ynES^C~qZp;oAu!mS}fm zC;&2x$-|>gXP2QQoX_xJaY{uh+F%z1{$YD8qyp_xcb!s!TR@oq_gbnfh3mlEA`qtj z?%?ia5pK!c1{??;>F*D0_*9g&g+C&Lh8RRO^unXazSy>U$6Pn#USO`J`m!d=dm%EC z(GaMnVaAz`95JEh9%ZMfz0q7h9R5mGRrMA)8X(_=F|A*M!ii%|cGp;)LV7!h^!dPA z5>8G<;+Oh#AJDJV8~}MD`W`Xj=GdlTIw#k815$~0T6t_Qx%nN5!r}Ce0mj z^>A#>Pi|x|m~w^5&K+;L;6!}@Asjrd=WHfR(OmrhzMT!=1QI0N6Zry*zS&322=4~P zE-(z4xQzMO%LUWmAej(-dR}&Uc7Q${3;ni<=giK{2)NPCim(ZaJTZC~6%}c}u?2kJ z#Y_?y6$itShr3DdN)LL6Wax(lyXw|*a)72u$pM~afFV)FtFKv;FeYvAcIbER{MV?Q z{zX6UfGOR5#_-T+c-LctS3HKq5bjkblVjqTF~dG@9R@X;Xiba)OxD_M*BR=ZMn@bf ze556L_Gi#2pHLZzYu>k`zzMx{NkW6|zI(kd zTsz-#@wdUBDsK!pxHO=8N~^31UHuhKwLaD)ORbGtORH(OE-Kmgy|DA?gw%Ec&b@Qx7EYz);p|Pw0!y7;iVpr zuhwlc{y4fxmu}UjXZmOr=Ra-mRrOWwKr|MDECWArwGMr+0TLYs# zTaO%R3!dx8=B*ErHu$T@u2g$eU!6%U#kv?49sO}lgcisIbw1GH$a6Ee46iu%unc{y zSVN(r$is2ns}wUd1L<)aVlQq}+qwe6raX8MF;DHhm)~r?G)_dy#fA)D33gsHX6kcY zcXdBcPtQyix^t)-yq7*Vnxz(pk?V;Uv#hnp!dFhs)1 zq5_0%*{p zgEiA{r=}|Mi1}+H`5+`06`ToBr7nh-7;RzE8Z0Bg!R*%z95MOtw}4mFIED_$sKPIt z%Fwo5xMXiXf1dcf@^jJdv0deX0Uyht&F|zf$kfr69Gww>SD3bAkk(i;ow;@8%HI;lx>d;|DUu_&Xz}9ZlkHx}v z4AV_uQZCwt=3FK{KVGkz0y}P$^Hu3r=`k_JBIu&|CcAIfjvYI+ZUoKgGmh2@B1sWN z&)c_ek00w>J!$NjmSm{iefV%RR~o%0tGj`hS6xwIFWvp)3C!9~XaH3L9rM?)TStO| z$TgosLDPBApl@DE8{ZBbG)M;Ju`3%NJ9g~aSDWJ6KF_!(7GVC8cyu;%rgLbAp9ki> zTteoND%S^~x7P3DdHMM=7L;;C<;TydO}g9}3iOkcpI?GG7f!MK)KqzcO$8v}~?a2O-n-NR~@qz2!mkZHHh)-uF6i(MZeI769 zR6S(RR+t&C<9+}9(-4O}cvtju2r=N?8YA(^3@_^Yb)$i_X8LfSr zWbw^h@NMXtD!-Y%@P}j)3v)X6%xC_)gk!?d#pQZg&4+Nrh7xCjdtQcbZ+KG|8}r&o zg~o$rc?-GADFhcNQ$K8flb2^Div!g5GQ4!1-pP;8;u^zQCnMBb?>4voE#%^#3Y=r4 zW2HcNm$~8B;dy^dDD_JCIm4Xp1>@F7@b1dBE?cPZ||CrE$Cs>uRz%3}O<#&TQ54)!B?BoP6xg8)0_~-ZAjKs_e zR2f^D26ukk&4^W3HDQ5Uk+I+l@`@nArzq#C$HhLqdI3N+-8a6QXhJW)9HrWj1*JWB za9aXbiK8pe5ADT~;npeLRn94r1`wku6Us(1ZdZnu=Y>Dh*A4sSjRkdHUF|GFja0Sw zHxWvQ!clXLtB`QVgfjMQ_N-Vv@L^X6q2+?mv9E(V>ZNJ}K+m@>0J;SE7o# zp4GYhav`30@<}8O20?x!oTf$ovm$cW5w;)`peaIX98C@Ipwc}UK}-?S^553aVCK)F5NN$SrbHf)TzLCVo>bw1(~DF)C1DDp*kJxs8XCI&$B+BfYtZOcdV1-O&oJe3JM%qU zk@Q@;bjj`K5^Qi?IrA{rY(qSX4auwK+1ziDr2a`EDacz_515h zPCobudpSvg@2SGB8MX*p{p~5`wW_+h7{ztZ%Uf0BxR6X!6b?_E;?V~4xO_*QY_s@w z)4b)z%hD;1!H9MyBn(0b_!^q?4xepVpn8{Ws`j&ZPg3;?T4bQ%UugHP`qQUda=ScV zcGqX18jOWj@c)8p3HB8GXig|AYPZNypQRb|+`dGmGLg|T31T6IIId?V*vZH0u4 zk<}0C?#!GuYa#lkr&yWXjOSjCp0#VVH?3$VnW~=h@axs~-konb4t&igSVs~tHk{{C z`D;~@im)*VT~hawJATu-ix*n~J)=gDWyJW2?L5b)#`=k)bu2f%qU%i^@#k|3o)4g( z7*}%o?vYg>H<_IM95YUrZP$-S}4?f?|tXQG#yAcRLWBvHe%fW3LX}Q&LZoo{D*<+{*M+ z+)jbYWjspZ$^9v=nrCP9!oP5BP2zL=S%H*uESP>oYr|D2PM$ouFzIAshoT`mZ;=qD zgE--^HqVb}ubIB3)Po&kPa}Z75{LW8JWm*7tkQN**EbVrHDYk20(qBxB~|d z9(5+O+Oa{hKWm%khDxu5$$2K|C>0M)R3s~vL+W?=vC8XH6R~o00u`S8++fa%2WycQ z4m31m{%iRxo$B(6iqGI=@=iYFRT`(e!nxhyAN(naumlE1&ukQ!?}CDw@CQHGUMdIo zibdh9S=eO*I5iSvGH;r6*|x6_qCz8Pv7$6)h^hf!nyVwT$hSkV_x-x1PEN_>$@@@c z%XvUQkIN_4-G;@ovyjH=JAmN@Hp}uBW4|(yh%W9kDhKV(oo|`7|2B0-cpLgSykGQ$ zin#O=zt-Y0!s^-8&`=Gx2jrQ&D}h&P*40!~Lc8YAUHb}d%Hd@8mq`?GqW$EC_YuJs z&BQ1|(M!@lD>tNZl>%|MwV9lLFfvZ?C&oc=pY zjD#|cPW+gR(cA}p$MNC6c8%7SBNvE}!r=~Q!up(Rev0X?oXqJ=T{1wM@AM|S0mwr; zY<5O_MD%)X<~m>$iu2^n^%{^0RXFnr`QjZ+aK-9PvR?!EQr?PblvN4Ai76Obo<|*C%1w$2 zER7b)4|NAxfA`*PR|Uc-fziPbq|Vd(e!#K&SI6F$}uvI_p|CIQ=PD-B?z0} z*`?JkR#j$BPR<95**C|iHq6P(6N`sz8XH^N%z^?X&T7(Vqg$Kvs&-5XMb752w~>tC zSiqkX2?5Q6Y*+UR&vhr$(WFT>aQTCm%6IJhQC}++*DlEpd>wBSHI`z5_XbC}BD{^X zY5kP8*9YhwNhZ=PX;Ls$VLJH{+mVkmv1ywy^7aUh1*Kw##pWkM*PUOnmX-d3-L>rP6zA+m#MmXc{Qdm?Vkq3iznnHTE*o;P6w!#x_hDzt3%+cFlqof*(X{fOrm^7{(VHTq7O zA}>q3uwY0>$~^8@an~>y>|AP@oi=^3rsi&bF*&o^oUZvVpR-itcWHV2+cI%pFe8kU z5t;2faiZD5d)r6@TOL25b_I`E!W^~M71z^vTlj!S2iFS)&uDvJS%LWyDMTy*QpVax z%NuiPkmDtg02RCep&gelUp@n3l3$PcYIDT0%; zUPcuL;kiW}u|@S;{=x|LNLEqhykKvo%@8NASmc~?C{R+EDm$hvTU6D%BE>NXDh*-r zSzF~k$f@O4B)95GZhBy~3a<-632T~iyqLo0Mnd9`o35HZboAFb;Es}Nmt9=^INLyE zBQiTm`X>-t$7Rbt#G5H)RMB|e0=)eMy)02B<0nq^=1}7drwK|}9zU=H`Z+0ipD$00 zay~k^Y*^s-7>K~rq;MmIx>{CK@#`V3lSPB|lO9qa;SA*Aj=}cJk7x{v_MryGQ{E6Q zlnO}hH9P&yB}QmE=-O2vmDu|Bn?7(qiWR~<&{%Coc=g~CdLkLP1$e}8A}xww6Q;X@ zLB5EnsixdVSBAPkS>$_I<^2(LqSR;!VY6f6xnw{_z1p>l$fp%aCOQqhF9S3?0xpj4 zMv$N>9}Ng(=e29bA^B_E++_AG)fDOxju7?7hbcX7Fi6pi&KO#K2fqyIhAJEE?9G-p zi$5tILOK2#?sSZ&=P;UtSkIqpxV4@c>zjdZ^bu6+JF(D-xr3G>N_a|cESmE9`6g*U z`*RUZ>nV+)ARqt=>OTZMGTS_2}r*I0g!%hDgN&I?^xk`-J5uc?w(uu88be&avYvZ&wXPA@iB8 z#2yk0I`_tjb8nCg0yQAA)TF<8XZ5^0EDDs>0w6!jUvUO|O5_dj$$*y0Tt89f4(dt; z4}92;ffLU%D8xQR(-?p-mEz z_$y@~CjzmU-`A%E=0~79nj53uL*1{XdQoV-LI1A>P~U-P0SagL)%g*BA(hRnY4(ea z(Ig)Ax5wzgC?2SVIUQxH=%4TDBeEu>&0G1-+n1_`CS2wiw(}p0(R3l%ZV6NTxV~bC zn5s(L%tAKV!$d2SsRIN7Bpfbed+Xk;kap;qzo@o_#g)rgbR4sfO;f$#B)g`mq}p8{q5I)V^-t4EZqB<2-F>^G%nhwEo?S zUH#yVh*e2+--(i?aAiG4b6rYE&<2!{5*eOGwkSYrwatTedrCSVyeEJN=GkKS&^!27 zcGLJ3u3YjDm8sMu$SV5PHRGU?m%g^peOAoB=1*5@Hs%Qm!3LPeq4m)3GC~_U)hMTa zR=IY`LtN4C=I~FXxu)2%diZ$ zY=?|{`OV*J@Mokr4m69%#US`~;_U|CGn)AmIMbAB4_<=K!O_X-TKLbaw2z1hL|Kg5 zsHUtaKS>v+foo7geZe=+pI1VF0g$?Nw07*u9a41%Sn7_UKt@v$oa;2**4B@7Jyb3Q zngJ>5mSEwig|-6^)MqpS6$qM*w(lNjargMFMdbofrVcRpFmb`cg$qB+HGvr_$2PZ7 zw^mJMvKjA_6JqU#*r?TMsYtv&QI$)mNS#HS)(z_cE6Bq7MA!A2==Br^T5UlT_U+2f z)n|s%7SmYuLzgOZ+ohTVpxYGp=4hs)kdB|(VgpKvnHH~r%wn&eHoq%CE2sEvK%;3h zXQsNvP@TxIZYi-yz}v2;&#!902}id zrkv~;t!-*=uTA{^-c8Y<=lpN{qgxR1T)`z7Us)cN?0avK8IO-NPX)G;sp`?XPAj?% zAFd_%+=oT+ryg6RbnMvC2=|4>Pa{eb%3Gwhjqtcz-8~@pNx4fr5(a-{vFy&~yqZy# zmj6(!DXZ8{1F5~ucXg%zR=6cJ1=Ky z-Z8x;Rx}xoQ&mCTL+vZ4i#*CE&71$uZPeOS6;bI9nS3Qqo`mIvzCc_1J&vqd`y~kA z@#B>e6{57-_^IpLA1hqNs6`NAAV4SEZ{EDAIH2p>m6|^2Q|J?A;$rww zS}V*+_T75)cN{9$BRADo0+Xk-71Pe5C8BS!g|Oid$cwl!ki6k2YXTDXur0(0fP zG_&hCyD=f8S68u(Sa7Dpet&3~Q6=9$E^YunAl0%>1@-&n$;}B9NA zdXks7CcDyWfbnz340J$KA_|%U=|K)_tc4>C#G}kI`no}9o9gQ))ViM;f%J-9 zXYS`YG(+YC%qDF*{#0!1p&2PfMV+Y1QK&8Hvq@Md3KC*b078sbzisxC;CV?pinyFK z_DtEKEq4Pw8Z~S<|F*ZHpq0|r0eK|j6uzo>8>$@{H0Xo zzIv#f!-!64xbZ)3&~HI;z?MMFFBuN)n7YhvfmYn3yHY$f2TA=GV+zJV0NP-a!;Q-r$_?Bs_#pB`RIj#YKa$6 z3JusQxu?K>3jQlP9e{uZue|x|P2Yzmb38Y0lu7|3Nv2s)$CkTB%eO{LE@Gz~rLj>~ z5HNJm#e@S00L`P`LM;piZD)Iw4+tqEWThaYz_4o{b$|Eq$QLxWGK$v>pv__vdg*mo zbq(O7j~%yPBGh*bcBx5Bgsi8 zv2FdEHY#Ov1CO@@oR!Gtki*e|q4k)ks&aMC^6h%`PEWg@EWPcjx#|0>#z@JUcyC7E zW3=&zj!$nLJ|`&yXhOV8j9y^d88{6ZX=e)a#|4*89hk0gWq7w55bku4ILA{NkEsA~ ze&O_(51(!x(@(=+uy8<+tzN$?<~c53?w~RMff*GspBh?DfGX*Xg^QW1vvmEc->mHU zsFFn%Yte6vp8CR^u<1vKtab>Ry>ab8%0_bQv1L9CEu^QGMUMpE#whXSXGDUnM-c2| zp_lF|dy2f)CICX$(hIumDG@SDax*;+@1+94YPI3R%k^hyo=%`)*eM(gmOKe#FRrX? z0VV49@+WOMZl7AazUup5cIAyArg=MA5tN2M`ShB5MDA1*&cfKfyz+5)HX54BFcAub zH=n#ZXhsKT0qpP;2tg*2UsOPz=VvNVDr7yU;+KYr!nt4Sq;oTbZWLYlN{4?Ps2QK>A3L@6f*Jh-GxyAJm2kSB}4@L^OErj1w(R^^H-O0ibQBDhAkH6WD` zVo?SzJUPz3H^uGu=S6?gHrmYRNWH=_{!Yuel%)vX|pa_g4QwU_zDP#m`+nim_Yc8Ah!#C^)X# zrq_t7>yQ83e`T}j5TAuWUXtF%IXUTy>@LMk@Rdt&qv8|boMZd*ctnm>6+Oq^1k);H zj1f{Ci;9?+K>Tv+39l~{3>HIRjTg@OlW04|a`KBF(!6deRoy!Hpq442Z;kAt*o zugEiEtmLt0>nIH7&D$$<$*F0xyNtR;FU1ve<;`JR;m%oJsMElI-nm^nzJA4?5&^pe z`6nP!N!N2TL?3uHdi8)o-Dw^Wib*Wr!|kKELx1mO2Bui!sKMC|l@T-Nu>#r4VeVe;x2fKsDxD8E3y9m{BET*)QN1wtKK;_LLnc-8z)S8)I-y$`&pz$LPRz+C9b3a zcu(<#PDA-?^%dyWZ_%P2wI8G1k^|fa@W;leY!q8X>SXAdLhZ`R*RQ=rU$x@;=SI>R z@%H9(;HbB^kFbjP3{z^*d`qL~78CxIbgFw=;i39~dx9@>2RY(VKUXp1$lQci53gk~ z-;PF4M9>zt{r8XG2L9C*F|X3I{S1QLWxy=Hx2L^rqSB~+HUpLRUQ~0FvYrPeXFWFb zzwZ`cDsfodXih!8<541emQ8!VkklV7q)#Ckb5t9WfTRVM;ZSgQWRosu>(B#gDU6KB zMHkmvz3{@4O3m}ZUjSWBaVescqV^_cEY^J@`*Y{y-*5VQnR2aLyysf(Cm-lXqdS{O zh-k;wD$gx^0&gw7h0F@V2%yD1Itu667{6tdncquC)ZJ@CeCGvbP`vF@dS??fi@+3= zPfM;j4=U`3p;JkryRh-cDnhW7mrT%uZBr8J!@`B)jo1Re`}g_x)c$u) zB3XHr@O*g#1qzg6Vx3h?PP|;8qzm{WEptQD&2Ti3ZvZ zZHNj;`t@Z}Na}DD-}2?bM}t$7hWnO!$f}?{Hc!1qOF=I9uBCS`8p61iuvIM&3pSLp_HiL1S`?Yg=|E9=ZZ5rTQ7e2VqjK?c8>*7zwlk_w9Xq{^r?wV{zyq zD|7iz@-P6|F_Mr)JWRh ziYesa4gvo3R)9ozIAk4TWA?75SwK>9+pUs<2SO{AwmWiPfCoSo8uGptksS7n?pXF} z_fA6^kcEh6&0~?88Ic!LW!`hr`RM30K%juB3d0#&v2 zm1A$BzeVCD!z0Zbn_3z5pjKP(`$%y8%iK*%Z zN}NQ;1y0LUrcaa5c5oT!WYGqKdfSGIcJ`_HfBLLbxlWJLxOHT{kVn0fPX}`j6Qv}S zV=p_{1s$FAWb1$$a29B-$1W#;h=eo7;ba_`H5C)Cu%t_L-@$WmFr>Uy&fy#p05iaT z>(;FzkqWnT;#tJgG%P?kWnM!hm^K+5$I7Y$&vBE>In3){>^qNhbmPX2dMt5uJ_Mf> zP|P4T2v{IDH&^|!F9-54<>t*(!DDy`bbhX+G~0$Qa{v8jLR?5lBM}OXJp&E$Jv-;en(fj+#Dw|1%>#CXi-Vyv|CSfA8ecFacQt z&j(q>ien9-x>iyf~>8TE*i<-Hfl@oa}m zeF69BT%A?IK_oBg|IDa&MR`rp3onLz3P^(Fl1@r0Dwn`kd_nsG=&G>nn<0X=FnuGn zS!ie|%OX$v&_vM4W}GWh%TFhPt!Not2>L&!D3GD*793wnx3YqLC+)DWZ%#Du-I_=+WH2u`qv zX&jc4V_|i-+>1$6e3-_pYlnqQdls?u`ja0+X(fo$z1N1S2M_a#SG#3b#R*>o%0Q1v zi2?6>*?po_Zj7=n`MAkAsDkq=1ay45aPKqY?n3K?h!yNb2{A&Q7TYw__T2kl4}LqR zQ9NL-^smRRWGMe9em!209*#RXIl3KQDqV|3%R2TT_L;V*_Tf9tyL%;_frd_>q zrL(?%a}Eu8vmJnbKsB+@JxWvZ-VF8j>})*VgjA`Dr$nl>@81xqx7*$ip#X`JNEPzK z2p$6W_XRU6=~50s+98umOnR`1j|saM?`oBoy+T=+g(&UgrawQHDCBSGn|)f9*EKGW zHV*CqnmW@Za(uUBmTcrcwb(%;hS zhN0YT{_SHaHwt^je$W)vh8yWat>(SwUe(BcuYR&rph3ILOUW ze{{HJ6DI7MX`4m+b(-*u@Z6(jr_cv@t6kJi_?O<2Rove*v@hteg~dU&i?w@q?{3Dy z8RrU1$SHSjLA8oNFEoATv0gu)7eyA>Oy@Xc`wu z(_*+d3j7@_uqrBsmw#03X$%||(z7vf2l0r@_TAA7^}|5EQBxk6qHUtUsa#Rwq` z;*oF-7Vo9y!=t0T#BDB*ovY|sQHztMuFUH0AD`336G3-7L#H;`=KT@b(&hGE+TkZlV{vzcJcTNbjz-yHra23t5w0m#mO!BhMhc9(`&As7xdWXo zsO~5r1=cNBYr>RWLg)6{di&PE;AbdBSVVAv9Hvhj2v?`0bKKu~#fovOSI5n4)LcX$ zxMa&lGdD}~!-+MW*#|T!=88>OR`e3R7bzlkIR%mLa)RR!xPFq3LdTsxK8-mgEZ(!7 zB3JEQwqiv(D=EO9u>1xc@MJZtmP9?ELv;?(ruD z1x^*0^v)NlSrS=+39lizorZ?*ojapBIc!7!Qa#*^p-0#MY^`9KFVXuYkMU!FTbnfVBgF>R>(KV;`pJ9-0VyWjj>I zegqMGNFW{#Kd9ubfDu5>rJ-wMC3WET1#N<4=kOkGU=uV;+pfP=v_FvCyeCqXl zR9^7Xugc4v1|`6FKx3*0oykH6$;*y&#T~nue7e-(jn6Q=-L_}P5u08lKU1J6gNs~H zd*dik@1wQ%r>@riwwOx}%Aj9|{2?RmXHhvN=h!^N$HXbCp5gN}2pDZZs+zhwi#|E| znJnqGocf@zJPKgtG?rfN*Oj%KW=>-wbsEhGh&Hl8$q4!1D>yOs%mSw|C3NC&0$IP> zG)8cYVgz<5wM|h@&Z5k3T7k-BQsue0fFGWn5uUoL%eM)-hmx7-6>fl6Wpi5ESiiRx zLZ_Zqx-$IuW+N>iz>r5uR2bZt@#}_z4Vx>f1(>I~UEEPUg4=9iL8L@DMx2<#VQ60j z`v|l}Z&6Qyt8vug#pnFvE}q~sOCr{jmoHUlhiTE?zP!)l9`6-m6%nxK`FanJE?9`y z{50vzhJ9N(Svm;)uuJjr67+AL_!}@V-19(#R(~lBd%Iw8oCL?=ybAL%&VcdgZ2jJv zy>I*AYe8n_g3m){QtHr{I#iYbF*DSyhjQaL6&1>uY2#dR!7d%!2|e5dE*KUjdU6a6@ycz>v~SqhWTr!#_4U|z{f>-EPIo@`G65W zC8qdW3Wox7*7{hufCK7(8xjV6`_?%jGV_#c* z;&SO-_<0_BNc~`>hDh{=S(x+$96?_f=L(e!_oco<5y9S_KO)jeOG^fzG>CwSGG{#mgM%s4-FZ(%j z?%YS06#A(9?I+VE)T(0}s@7)B26h;ysK#>&WEF6_awj*Xk_U3<>ZC4c`TKM*CRCy2 zPP3B~#Na><*`qXT0d2m$LJ4K=3QRTeTo&tpLpOClo-H>$gvo5Zw)oE72EKsbYm{YT z0Qh!f{ufx|d_(#|VPim#$5ittXRmQ`MV&7<-Q56;wGtSEDaFj*4yJu2x){`fj zIknE9s~wtA5}U4dX2D)I``x;wKw||hQ8XbZ8};F!=240qpsxUX>$dwgBs&g-H5_7M zlD&3#W9pncmr9BbD6097P5JecLWw6ezNq-ss|AD790%IC>4b9B87q!YZIjMXUF8zb zm8BcT!zg2{+|Dkec1TzvFHW=q<~5f9VgFY;bie^%?m8p< zpW2@$Mg&t_dfIq)Lh$Kar+}oDz1t`mPk&R)Jw%i7FwOeQdiME};jv>zl{I}ZEN@Z& zeriM4pTBV_c-H)843WNZ_7nBmji%=ivBNef zY_?r~b^DLK!`Z2?n@~gstp5pH_BOleS+5!4mJdG+qcTkWg4W0Wn#1D$?eEyfrhe)C zjbWMoWg1V)+{_1bT`%l*OYnj*0=;NQ?up;TVHB2 z9x%O9vWY1HfMcNOHZh3NHZ&)q*3I->LV`M{^;R|!y@?jtBkM2Fewc0A;@)z)p85d& z>V1DE=^pA|IX+>LiAG-P(*5J_sYt#+~iZ|q}ALX z?l?Ik7o2}Uymu}Fnr`MKh3TRSU=JegUT{-43ABohH%FRw@6Mgk&hE)<&BLqP z{WI2UZD z==^sztR3}tDO}x;lv&mRr93HmKrR>EC*BCj*fgmeIRzIn$`7tk=}stU|5tvgXqzM^D%~|s(NeA`?|kWRI_MuYfU*cdWiS9 zsj*3e)gmV>nVzai+nMQ%{$zYn8$diThI$IejvtrY-VRH0Hq^eikRD2)Y^o5MVMQK9 z&Uv19lOKHxpS_vrr?bbu#OST_tpmzBZXH`$Mf$Ca^z$BOs=Vi{$?T~EtiKGuTQxNM zr|p-2nw50`La~@MN=HYhpcumBU$6f1+h&N zLpN;mf6qC-@wI!4F20-7%)XBDsYJCAM$byee71VhC>fpfiF@b86EI_FP0?o4vz8$CNSG2ntNNMu zeKJxq^YR*nTt;5SSe6I`+ny40TH~c$zAR zVF?T}tgtN`ZB+wVLiRxmmNH6;UtLSD)i zsAh`(i|#gqqo%6MEE-Y6E1>WgGh@a9{{ep;Fb6Gl7Z>b0pI?#r_^L-Mbse1CDpRox^R*Z8(-cXGp)E=j=pf*dM) z^OCF);kiz4Ehc`OHVx;>sX^{4d)#{tbH05>M-p#uhfqq(rH1rB?b1m7LlgDaD?Ld~ z-5x%FR0n;{<8)>b5et3krMAQQ{P&D>`9#PNL03>VbRIAuE@Q>O^3{rmAO^(0{hv!o z^639p3{aCYn#iz2{WMB!U^!_i=S4`iBvp<;L~YB$*qQ_^Iw`)mX$4y z9m=QUEGpx@c`|L>cQtA! z_-DPt%pmGy;nNr&K6W5JtG$FMWIvftO(w#UN8zmQtPwmw@ir-J#?l9;n>6+E?{bU3 zAPVezgDZbbA<>R69o$ZCzq_Ds$!+pqzMP_*qjI0ynXMH+RjEab%Z^@N;g%V+6mE5AB?roRk5L|~+% zfM#VBla>CrTRSaJh6Znj>Ft8-K+?cx;GI4G%K5McYgF?)Z6 z$f7=Byu`Tt);t`!(P*a<^Sl1iU!{+iSjSIF{@SmEhEP_saJn|jJM^O z`D%0iQJXbSS^KbBn_0({8a1&uoj$V6cjVboSvGS?h4JYG|p^kfqm^Qi4sluKRlaz{GRayFEuQc5wKj+rW9@!ZVpk zPI7vY+WWk*aw(OPq!e@@#nvv|S<~xGZJK_da_3c-1k5nDB5@#v;VD zGCsRvDPc5oi-6+;@<*RIZ$5c)OHIv(iTBoy8|RZ|-=%g!pCe}|5$Ht<_ZSWul()`| z0&V-+)}LSgO5Gn89T(RcnNi`M*1JZxn7F|409{~f&S@CJW8z?Vh6bjuI-;b zsyc%#scRim44NSbi$5SNY}R0m(&{L7=C^Bv9p?JP)8%LE_D|c7ZgSTy0e=)EWa+F% zpwui=DK&s}KCIDva8aU()9&p(8l4um@qXsffPmW&-VPu&|Mbz-qF4YZ zzC5Anjs^3VE&CmuaHYqy=g(8Jv*Vt-B5ELq(DGYFOSA8iV*RT@K2+nIyFe|}1r=hdh4%d4q12M&4EGW8lOM&CQ)DY(Qa7~4Ob#ua1QA+UqIhU;_=Fq~I z*&@qshI6t>!}{XO8a~`Eze}&lm90e-OwGA&+DB(N7S2kkCT8pAi?tr4#JZR;VQjZU|u zeE#=l`*!VaG121hOU;j&7dlsW?>@w1XHbAWckR)mhk>DC?!-4pNvrAk6E{nGA z?B}C9H~rT*tH;F3qdoMGMPurC96+C!SI@Pxi{2i#QzFrjQ&fHY`fp`r%&VP$B)5H5 zQ4m<_iyIr-@?33p`o6Ov@+c-_Gf0QPk=Q@gPs<&gFS{7BR6$Zd?25*H-Stw(QdEP~ zqB|CdYPVp9ctOK%aa>u1PI+V4{v;t9#0S}3p13XSEf9U#nr11)fUfKubN0kFT9r>p zFYzIaUVKxlp5BAgG_st(9GM0Nx6q4SN{E}=vyDA)y+OZzWoul}>k!8|A>-*dQI0~! ztQ!`jr?20SFd6;PUxO+>>qi|ue0T>453ACRmIr5J!>FjJ!aebqE{!G>-b&qCmiY!* zRvR{K_^(RD#8qM3?c6(evvX(8G~jp&i;Ubht>>MhKi>uun)J?CkGFC*zolO)=Cq+P z2QbyRM>S_V?)JXJA*P}e3AX~<$JIJG*A$RkN(dte&m#x*1BSnLG(jg z%I3f+Jn^>$FGy95fW-N@2n+YnS{gB7E%&=u!)-o3X9zrd?y9b?&Zx@~F}XG6gxM=n zQ^*CV(Wzs{s8>68Mo;M0ihJjiMu&Fo!oF^wO%yee_~mk3^T9)t+IY@^k;ADi7UK_3 zqf@sQkh?m1wvEjilW2eeC@l)cJTuGDvyd)5;Sql@+A>msmYIOesa2-3@#8`eTNnRX z5+Z|ly3hE!#ZJc(6wPKXN05$Uv#6Mvary;&RAVL+;_1xr=bkW&Hs*A`q-?iM(zXp_fG~M?b1dmvEy-K zxj^;pX71VgX%@D0VzNhR?{_oF4Zb_%FR_AoK0`dI4N^~a}8 z@7YFN!}w3{Zn!$|* z3rPRhgGJaU#9*%W8cji=aW3AuTBukk0B94h|$?c1hl zAI;h_FQMP6f5+P`EGa4BwhH~{IlH)-Cq6;%Y-f{v(Wt=HOSHIM_uT^*zmhpab3rbM)w6R10Mrp9$YxPDpVH0A~i_R!xX z7uXu{=owZ;;(Q|WH_UqBlJwadyO+Op^0aDzVqlNq{=>YHfDcU1?D6yK!+~wnsnb3h zJ)?bTLu2Lzvkpp;OH_ZObIYs4mduip$H^7h7E|DN%^S=f>?N~@X>$YJmm75C2u0u2 zy{2-AL@i-GI{M$W6Q`cBd*9sHX%HO*l(&#cW3mw~AX1;;mLx{?n2AINEkA6elzjyp(yL zQU03LwEg-uY^vDvL)n=Ej7$kjW_?ESq21dON$BS5)#HA!kc?Y+=jWt#F z^>&;**#(xZ5x=v?Y$5GShtex`p0aIxqg~&owh*5(z--{RYbHCzVa9zS2{i=KFD%LzPhR=$DTpv4~ysjQ%}TvD1QsD=PqF83%!yH zMkk$mR&+zQp`!CJ1Se_ z)kRWKrmUOhq(sN-FJAnPw@+Eh-JRKvPk}N${c7m$yz#&-=uh4uvz6)V%hmLV+QM z8ge}RD46%P?lA+p>*mTXdu40O6@CHRz1H=Kto%EJExSJ7QCh`|Jv#Qq08AH3Ph(vD z0L1}TDi?OHI}n6BPb=BK5Wh97dxnj(1a7C}Y^(&wYfz7Qf6=75^{X&Y{`)Q9}0NMlZ2uD`QuwAx3G%=+Gr(gqtXyoELOs%jWJ)$q+$7%8=fs zOl2}Fsg9ouVb<=r+d?t<#&9yu{9!DMrV!ExD`^i$?Lg59Td#l;`-fUQGZe#ZZTWUG zBpPiSV!d_idn__$QSOFS6wl(SA@bhHOt@vccAVo!kD39=uogJOZiC8`8GVoRMh3>Z z^Y)Aw?&XC0lOxdI%`Wf4yaM__xl*7nV>Gl?!$LxuQ@wrinnU(ti26ROG1l2alD2VW zS+53Si`_H&5D2ui4qj5PnCnpHwiJt3iWTf{0o|j2JRb5tC@5970W+%pz3Y>!D&k|s zAIe!heg8MjKwVif6sS@WOE`Sy^)@~~z@eoTq~2%2gSYoVu#ppOGh-Uj9z1*Y zkRc!OU?@7liC>QOYgbn$U^T|<>nFsgppT;IT4Uhbp)gp;wSdV*T zJMq|x&Mc;r0Zyb>hWjz{dlaBWn@BrD-sn|NG)-nkt%5BbymVO7*Omz{+8;iZ-EnI{ zboQH3SBrlm`w&aI;u-RZw8ae zJ#=YeT+o-2Fmog=g&2YX+NJj-lHrdb#iaOEGF&CYfEau=L0yv-p2<$vrlOk0e{lU; zuQN0s;!TA>Bz(_Ea46ZEM_*z;)KtEy!+nN75ck&GfkKA(nm^uu>Hx@(JPo6!_21Oi zv%|%NIELqkz;6#2v9azU4wosPK}V=kMa~zktd7tXqI@TM;gn7rCSwk^hpMz2UKQDH zt2;ND;n${BT<~h$!+GP8_4Q^HoNFmA(9~Gm^5te`7d98y<9?C^q#|IFBs>1`RTW$d zM^MYk91{@Imj-tXbg)h!8>8AY+7tU=pRnHWP{hH< zvzK9{{I8Z*X7_kfqD#7BaU_Vn4=`ug9Dc50J+X}xV@?hI%Ft6((7<^AA@raj zZ@w8dvmpEqT7^vd>LAk+l|R5kv>U^EzZuxU@FMWWc%GmfLcrK}I5Z1XYhe+V@nkbQ zv?N=P7@-q3wb#P4gvD)tJ|5q{fB)NvWqL|&WzIv4uP^;*(2PJnvkM24&xo{RHnz+} z)bICO4$uGJ1C*3qoa;^%gCFI4tbUT~^8TZKPzViFp1dbTMw@w!#XoZN=sHiE#3_^6 zB6t~tZE>v0{BWI$oi|^C7iBkwJH*mZ=H_@KIi9b#flvxi%X6o6zDK#y>!`yRRn-qp zJ%P`VqG3WTrf;uz|C6u@5%~^^MO27KBReL$Q96S`?X?Z>MZGGETOoeGba3@>J$#tQ zvxlJZLu(_WGf0vJT*W;k=Kb1jM`-|}*;K^#kPk5}Kd|URJg^+1^MXSc7LixPL5+&M zA2$K?X0n>q0^k%ZA6Dc<+Y7L_Ugbk9DA8L|so*k_o_geAn}#DuEAZQ{Zgs|`ij;~> zZ}?%A1w*~`#s;}+);%(M<rmmY{|EcX0P)8=)D>-p!Yl&R%mAsC)ek)uVc*|Nu3 z`?heU73m$}9xfY=#laQr8+ciI&gJx{Po=93{Okn9%hIBq*nTFPwwz3ec>n&rto|@| z&5vT|;&~W$u>)!eLKzd;rOzntUh8f5KpEhjP}Vm z)uhd`rwkl~xj5I%PU{ecGbku8(Qx?i89kY`ktGpgLXYm)PPmco-Me$yt4wNfrxKqv zo^>7`ZF2cWU}tsW#EEIW+mzaQ?8zI?*eIBzY@oA404;D3AGRAQGy9lQLB-SG?C1Sy z9Ag4nLH~-G%+>z^T+QTl%rR z8Uj`9X!p$Q>sPs0@v_Px^4$vNm!jKtp^QmOYcJEn2&=sA^h7yoZZ3}hCDi20L1v{H z1c~kKrR7-FonnQ*kd)L0y`T6`)2cgKKL=EimqIUK{i3jQ!X^Prio#>vh{ndWTrLz6 zEAfXrI*&u@Z$nRx7Czr))*^JQYHs=ON=^4^(QwFk1LU^2Mq*Z`A0E7Co^(oMkZ$5% ztAWE=xYtd72b9rntvH03-LW>7RjRst0<5~@he%g}$V--@er*%X+&s6+d~ ze^Xdfa1&Y0w1Y4@VJ$-gY?Wsd;Q>(?A6&6vLsim&9(z~FAYJbEN(Csq=u6^xL{Vw> zJFF>3Lv;J%M3XtJA0*A%wfkx-V{64^;(8mu3UGay>=w0OamqvpL7W8e{9F~DbtE;D zm&}ExLN|VE)B=r^3_LEqzV3)_^ShVIGl2i|#5A5&SJIkAC=cwscP9h`Bi~|*#0uJ` zl+RjUP3IwUky z-NIrh#)*9A*_s`Cpv;TI<6FR=l40sU9Wgf{AW{ON=BP|j3hekxkjbxf%r6ZlP zdRUCUaIv4C_aGPy7ef-AfxBn;?eOwS@AYjs5tGyUo;$(`%(JOs=LN+s|0w0$5jUC~ z@imZLHt-SlJ!l$bPD`S8OyueRXmjiJ#=9OYFxpLX&YT@{l>C*;)X)Vn{k{VW{X;|{ z;2CDs2>DGoz0qzmx5ROng@m%x#8sq zqkUy2)@O9&8A`834O8zfE;2C8^CDhSkhJMRg|+kc?FkIQv8LmB(FqjZO*K2PMX#do zrPZQR#7{zYc2!#a8o`wiF9E7CLJn)OYmzo`N1>w-E+#O}`u6?%1_*@71QExS!O+D; zm>Y4#!($gKC_oHbwmekp?YqUshOM>?nKvlj-T;zD96;GR*njbL@F8*@Zh-%Q-Oc2t z7Ozxj)ryL-KKkgF5R{a_E=SDfbBw_IdEj@=*UmqF_;4#K8gjm_?yN(6cgBsy7=}VM zC+Y_yc;cC_k6DEpFLgB0y zMZY2YHYhJ4L3LXmY5R8jsE@=uX6h%}9dA=H1Xh&!85SnEaJVrAqE76k2C{XZMZ%1# zOQ$V+VulPELfse;7&yzqb0?K90pphaPi5Icf#>qu?LS^TdX#@}G8^y?($g7dejMN0 zwm4@NB^Hv6^}7t`(w5K|h)*E@KG1EoK}TwDUN3#~NDN&vi}dd-S-f}!5 z+7%8DdbgeY2>{MFMcaSn>|bqgE-1*fC?ia^4f+p86 z4y`pt3zG4XF)Yqn{d+A%iL`>^?8+jgyFxgK7h}i0a9S^thgP;i}3Z&I|rqdB6$h(}NB10upv& zB>)*(dcD{72FGR*KB@j?m;tpLJ!4gY9ds3MN4zp2Z^U#$>;&Z!MroyCx8sLL7Rz=8 zsYGehr%kh@aFeP0O<3KADCNO3-rG!J%zyz%N$jF%cGPbPq9<0%eI`y^7MO=9Pl#2T zQ_3W2_4d%NW^TIGyi?NLagz~&tQZ-Ji#IkbWU+{Eb4HFH9VcFKG@zzn_;z2eB#5I7 z_j23scl&6IY-M;3cUxOBM4~{qQ4|a7*8}Yei?_nqZ&&hF_DOz2}Ir zW8W&uYEU|EsD~GTl`8Kj+Xwl`SrULir z=+08-7hT!>Q40aez_M}Th=88;-Ip&_`)Z%i`%x|)B;Y~U2arVwF=k(nn6lzcb}-QC zEWNd{57@t)M6$iipvnX=N7cT(_>T$qWgi}Sx)YzG*7>JhyM{>VT6GyUGqA`b7PN4W z^b%t0-#cH2aW3xX6>y5GsGIAnRF3w znNk;!G-LjJBzE?3S0h=J7U%Y2+WCF8pX2BSM>-)2$0xB=j8;8Pom zGKO}avJFH1W^@a}nNMy$7>Jln(5kAcbf^D)Gmzg&UxV=Ao-BnxEfnFi3~d%ajZh`x zbZVB;Z^ao%00|j+;15fRUgR(|%6FXh*Gg+}%#B1|@jl1~Ni>2Hd-gDj38eV_xx8`z zI-k&6EGm_KHQX936PikAH~(UFO(ft5flZ8-#3~fJq#-AR)LA-1GisIH9|>}B zVR2}QyK|LG$GeikCc?8Z!Lyfv656()c_;nHt@gI@);aRzqd2@U5jldcNoCoM!4@;}i?4jiG#qJg1z;M4(D~s-W{CW`^1ys1%f;FN{hLkqxDhxT zGoQK#j6!ROKLv>Fjs^x2>nsw*=gD1^+a8eUCkz`M5xNRlr-ep_x1M%GZ5f~_UV4aN zAlyR^^d~S8%W$?{K`f(L^-sLhlUK;|ls-cW1i%K@f6s$EQ}6O2_F@W8d2VfdBM4C) z7ha;?(Zbcft>^}MhrR%*V0J{0Ajca`F^xe)HE&)kS-Jzx638a{n`pY~mQA2xgi!3u z^uFwq6E{(ELxk55#&`PHlD6h@J29p`Wmv53aAG#&=~s9FY%6Izf2tQhAx zH{``QBoeX2ZGzH?<)303fW!Fo%oX*MHqGcyfII8-t4qDNecu7Q5egP7%{?k__xVAte+8pld?qr!nu9$^zcu+aqj7kNDUTY zHb75`rz7GvA{=v}E`$IO)T7?F*38<-_4pMXB=cnA zLdfA~LXoa=mQh(%Y;BFBKxDk_t}$oolx3r?Uc1IPY9scl`FQGYo5r7JlHUjBgaHtNqvCWT8L{<#I zsqNjUK?C(~AM^6+gDE*O&pOH4QkNsYwEt2yL{ll=jt=WE8Zb2)!+3!L32L%f9Cnb( z&r7)i1ecv33SP-AmDGRvfvk`}q$&R|s&SvqCj8p(K@zqmz zdwLLdQ6P!+jGT0bDkOQxF`?Oq__SZdH9)h%&Kxe7ySsaa<9n&8K+f+%yy+Eoh#PTO z%kv45^Oj@zFbV*2+`L0+M+qrFG*_&0r^u2~t>SZ=k+I-FS)bz|Y_M>eyp_Ggq6pvT`&57o&`al(Zl-eko;qugeZ)X1ELg^7~jC+4cjcP~I7x zeDT>Ops7XRce`q_}r@tOi?EB*(;l4PB0ZxlA1kc_2A7N=`*nzXeK}6tAMQwE{ZRR#?er0$qSD3Y;3QcS3Q1Qft$O*EbX>JhT=hxptq>R+>dRh03?N9C#3-R-{xO=Fee0emR0o zNKMH?8o4vz7+zbq0E+d+5u8%_A!=tS)!=z?w+IQF?Dq+sYp;|l zlN}&!6Ij&XMv?F{C%MU+v-u*%r@R(WoDC$c$WK}cI*S&$&<*j!#EBiUMeD4(0T~?i ze!To`P@#n(XQNso=;O?Z2|t~VcX5$V-gr@K64&{|a7R3ffFAnU%yQh?^11a^+-%7N z1JgZQ+=_KcrRU*NtbK8&jv30zx{%Qs;cHL5E%JhKq}&gTF!lOQJ3^qTsVUR#7k)T3 zt4E0#FKqYbkB?)wRgY-Z5cQalLewni?4rZL_JB(ENfaV20M!P~Ts{uK9n#^lW4UD& z+q#iTE-7R?rMkF=iZ>stclY{J{me+44T1`E2O7kC#q;d6@wVZq1~URN8Nvs@{*$W$ zaq5Q|26_#j$e(Yv&}Yw{#(P`$I7kUiuQYhf?OZAd@MBgbOVJ55toka`m4x#pE23rY zwx0^LA4jK5fx;q86u1PX$F4OqJ4l}lW)pyq4(3x@1Iz(Kj^JL#6-Fp?FD@?6&vRS$ ziq1_47)*#flxcY^|GA$5kN|*DX688;FVe^JTSXL(VgmZsKSkBqj}IY372XvtA zRJ6fw1Kg+Fm+d?>(1PhwVge;=4agJ>h8hY3|G0bi>Vp(zzWf;k8AP>s9}-3I8Lw|k z@bHPP{%R!!1!1x|q9AcOxO$b@buGdOkgdSIINXB(q;C1OfRa294;p+xhX`Qe=GHp! z#k~=&D2YK2xfT8yJq8iNWg}?DC8I;KEkO9^O`HCtuH66zEG!EwF#&Ua;Mv(K9Yw7d zkBe%Zj?%Ec+4AM}_+=dP_YgT+{f`o_@I#VjnMcSOD$=&Fc1lG}ZQ@+rL3TZ^T6HcZ zY61uS%Eosy*wQvX;Kk23{w@Ar3m}e@GkrSm6$uj8s5gKTU{%agRK>d=LjaYKI`7k$ z%AN%lYvpVEa1aU_!{JGgB4Ppf4j!{JEqxmL|BeESOAA!bu^Dv<0_1IY_p+nXQ)x%a=Fg-?0Uny?-Ja|Alq_=FIKCz3U_tdE-fkmTQHMFv_ z!dbfuCeykF-D81lq)7~Xa=tnTDEu-jFp=R;PC2Upl|wqeObZ<7sAcm{vqmSdA#UAs z(wvX_WZqIWl_ye;i}^cVBN7%AS=NU-S}plXx~>cfun z-_VGs^KB0vJh+izU1}yG?fs;rk|Y0CtR8{rnD;OKmChohNMS z$~p;otYlKMnpSucYXxCxr3Ropq=>qxYp;fEHBjIPob3zE8tt0B#^3udhmQ#=W!G34D2^zf zuy7BTi3RI0T(Z4XQW&_*yXu}VsbwUZ&ON5GFmj}QCs<`Lgyw_{nJHPUmJs)R0<)MB z0zUfe5x+&Sm8Hk_&}MQ%d!GEP@>jJ*gCuece(>DD7fbF|`#1|n4)NQR@^j2=nJ8G- zGj4?JVvuT()FDQywBpB(9g~yL+zY7;m!Tb)v}ko@f!N^k>HM|Q85$ZIsI_;1XHwBp zj2%7m#*(R6g1R6vD^}F!SI~G*ZRaz}AOB_=S}cPVA2J^6_{d2iEc!&56;Hflg6VhV41Vys11YEi`Fuwztsei09} znDOFIGB?+h=|+(C*{1j1R~rC7@lP9?Z2R6=dRz*0udS_^R^d**by1vh7h$J;^*4r+ zB;iAtT(GvnnG$qaC>qowIPdQZ2^mx@up#jCKX?G)q&+Y@uHG$Y#qy#|#acGl$X<_I zES_*Y%pVnL3TTMTh7I-_>|}(C3fw6jYvi=*g!l!pyTvcB_nEW-g-xtfX!lfQtQQ% zy(`|rmmW8EXwE+iyxmbkv@yMjykIY_Iue!=`26>LCBGjcJ|=U~$BKvwz%!yp0|^gl z4*-wFIt>m@@cJc7&X+zI%e)!XBoRp@?zFPJ$NLW+oLlg1DTt~R-;}T7av&TIh{xdL zrII^kF(VtcR-iwc?Dhg;g~^vaJYr-f3}XB0`m0Qs&;{%YlzIoAm|4nJQEi8azLRMZ zNYxdvgb*zZd9Po6|7hNL^yhupxxzf-#Bz3U^l0YUH?6-rll)hpAx@wz!;}JFjC6L|$(k za}X@!9iF>`WAx!{gm{*nEMS8dbpu;)NufF$z@q;9??v5Fv;B00%>sA1Wn0{n!_U^1 zhKm-ZPVrg_CJ00WKM*gUkeC1Ooo!u^8=T*C64(`S1R>%c*qS@LYwF8mXT+|UnFZ_K zs12n}$0BKQ)_PeCjVGrhEHO_GIikA}s){0%ojmov6@Nj8v8ZAaA)68z-On^$I_iVv zt5!9t!$9v(x$@+K`HESP9-_q(P0Hj*lRY!~XdLdmQ$W-73yYn;Rqq$USOVdia#t1@ za3uxGV9Ld3d+Q_zMK5M1CzYiwy0yJpjigD{xfdGFY;+?I+U|8bkOzvO7J7oFp*;Uz z9=0rK0Epg)u;5;D@|6YiPS-1UUcd`+>$N%9I;FE`V6P~x1pc&aSDT#uqp=g%bS0wNC)t!SZ%4@$-ri1t~+ka+f2H5+Q; zK~^QJ2l)C<3p78;QQ{H7IwzYP`&~F6>j1KUosxRw$SbqUZ{dxI(nbUb*u{3@Jr<>V zh8s=P#lvzp_Kqma8ZxsQ*}5e)q)6_mT-b<|WMLmQwcn9B0vxb(s}=cp@%q_k&^)s~ zaL}aMs-GCoWj?Mn1LP4=J}dub2DY`2T}$MBhh83vKz-s>~YW%a)e6S z%Qko`swEa4C>uMKEv60*3HzYTCHFUvt@_bY7R*7RJoO&a5|&%dsLi>u-H*`$$q0dn zaDeuZ_0ne~uW2T|T(U3GS8S|lm{z;LSZ!`zxx9fHWIXktuKMoCWJ(>R-C}VF+6XjO z^nG_NU$g|7>k1T{T`Q+0UR5EcNHHP4@rcv4&N8fk%1HDQFQe_RX$-KJ-VPxhw2EjG zinPDbh>V0Rk-esrO*5Eo3_qP#sKtnglH`8|y(ia9Mk&=xGBX!G;Km0NbegzK9RM=> z_hZU+5Uvs*MG{0OHxt4CpML zzmyBLf>UwJ?t5PtK(9NBUG`3g(-ygxC}u@WT-bLH!C90JB8EYZ@33tO1vxXGkQ0rB z{iK;%&W!fnIb#+;y9^rC94<~cFFMM_6{l*3gT|?t-03b$2P?{pbJuqClUlo;)HVWt z39ahtDh;-E)(PXH=3cV5RfrM%-~_%w{rf9q=qGvAw@q|E3p2n>6b0JBo<5bh0ILn%`(GdLuRBO#uo z#h`n4h-o+tlUI6fk&I9vEY#NzI@Z>V!3z$WXo0Zd4gXcSm_H=aAwZ4AmTj$&HsVtw z+FEfVh#NuIcuyK-a0CR)gPmTq+%rQ4Ibn3;pqkSnCmvdD0ATZ0+Vd+bXS;7zu;D@p z|3V8Tm9RMMP?0*EYI89(G!CVbp#1Du@&{L-DRek8#{kz(+`3)qX70av6FocE78pas zn5$N=h7b+0?ge|_U0wr8D&UIIu53~UH{&<0k0|22w02YvN0CPfDI}0AFu|*jupDli z*nysvnPv`hA5uB4984MLEGr()nUOAJT&L>^Z*%Uy_um&pPIFZ=P}WjJ&WC^Zm*htb)J#Q zKhW4EC}Z;AVDz4RI~?ml1VM^bhj>i2imd4f*!J@J`gYP7(bis82~8=!PfIVF^RXLV z)&o`zbpOoq2}EM=&em29AWWriHQu`dbc2mchj12MNgXXs4Y}WXYwlLAg%mrGB4MTeW5U`0=F!d)gdH zT!lDP9LIJ*c}Gk(@4UA@5023@*)MLDGl_eFa8A4Ezy{XnftaEvB%d(W@?*OF0-O1< za13%M=w~wQw;1!zW~NT5E?vaRMkFu|&pOvkkec7;p?~^rExZhb9zV?(0I?m+xir4c z>17idB#6g{ebxR6q`h>jvT`5$PmjDl5h zCWDyffN{HDdp4%BwN+$R!>Khj%Ii~OmZ=r2iqJWB`0Du%?N>Dm?(N%qfAGc*vtka~ z`S==lST%4_n?_9ss_U%kIB>4k++_m;52sAd_wT3eSyfY#S@WUh=(#?cO+S}SaynD_ zs9?f?#Pyb&r+nTvC2H%YpP#g^HI65+cY(YI3XTU{BZ&x0K*-I?>KdqPP`qqQL~U)j zZV2X`u#f36vBr_s2V`g%O8;8+!RuG9h@s@T96J}5A_XsO^tti$HjVDR;mF4$+r~e) zw~ESP`v0*@Glm>$qPM;B>$p$PeV*V2LERvtHC$!pDhzM7t9P>*4U^ZY0y!N=1apwe z#(QtuAO&SjzW+mI?n|T&U=lL^by1OW|0ZQi~a^8IOGC0sdy09XSht zla$NnC6zp-E{LaA4B?Q3>7T0Fbnk4pG{ynm;x|7kaj(xH%nL8$@4~i(hV1K_2aFL@ z2_%2G`veae3TC9v@cOM1Fef?GxPKEoPa)Fs%=W*a2rWxa<=-hYY1(tL12Qr( zo1&Y)Xbk9a3-3(A{}BtPuC76rF5wq0wD8i}!(#9-{mig*z|6M2dM#M7!f)ZAi>;g{ zg&9WpQwK(~a9v@u-39iwlU1%UyC!b%S2EM%!jz?V$-Ax77njl%J={N~JXJsgHQ3=dQNr`2o@B3OiQ zqVTm;y{Yr|#h9L5yJ|5@10A8Hrk1rTcYWxE3*$GvZ$!7cmcm6N%!p?X&yWC>HHUh= zTiKc@!>~0VZ2-ms<6d*?ui2KUPXEEA_PWeVJ!q%`SuAR2Z=Zcb-`pzdZf(ob^h-u~ z0c!=m=SM;7dmcUdfN)wzdtAPJxy#ds{`I{G{G$k+6fUwip3U@^(~{(G^j2*k&V4Kq0hSESvJRuA zZ&mh6oGTV|HM)?7bcXfYin7rJz;0bylS@jP*DYQj14Wh*{@7vW3mXbvS#ekPT*KRk%$zk1#a4xqaxf7cbm%VjO?6RVgXT)(Uce=#-{J zl)&CqLw&Kx#Ng4UzE_s3XFNker-*7m58WIF-%KvB#sK3d zJ4vokG9b`AtkwZbu|(LV6O$dsG6l5eM1c=>Fe2Qala~FDRq$J{k`}E$3OHJTe+8Qb`~f2&$i|f(ZN$^{yC)hp90HCKKoJT&L{-~u zRnLwsgBie(*|w`&KF>$yAcO=}-?7dtmzdsWw?^>w>qmiDC42(U&45mJNt?J%ODY`H zH7QA{zn5`8D5}15Ahw{^2{4{ZL~tno_Kdkb=6LN~K0FA!c<}?jkAhhGFt|*Wt@mR? zJd_SFt?I*D8|Qu0+Ig|Qemqt3bN=8T#>(e;Ou2Alog*WSc8uyBIDB}+QFo(2U6Rrx zI(LI;yG<@>t;{Zv%48R07XT&H1=lycN;$W){qNBw5zr){=5whg77n^Y*MZ~%*W?^O zhNHo@ysh0nZKYV?Si4f#&|(L`=u5Lf`NQr_kSm{86reHs1+rEA{Y_sZ^)8M8~#)4 zsQr+NS+<#VO;^}qNEARcb{76fPWN|?VtSNfgrPP%9jbi@)gSC_TUOQZDk78~YSzBg z-wecgu+W3i!beaZ4_v*R@%k3yf4Y{1O*$Yku;-_*dwpZ56o(ArM-{zZi`5@E(@(0c z_r=Az>xw#)lOwl&)nbw&AaYaY2|Q6sV30&PVR&Q1`Wxl1L0Iop6b_NIj2&(A&O2-a zbmM2FUR^!6-HW6u1W^X8IWn+xAF~*$m^t8s2|XPTLk)v9B(KXgkyCdsg?^)`wL2`n z=ZO<@*w6d$b03piT;eT?{>kfP?oq(a(DYHjZ;12PCEpMD8_4HlCE0PP;RyU~P=|_7<@*i&7=x4v5^Q_jty4s(@h{bgy@jdeJ_8#0|h;tqh#JV`ghbO9G za1+;SnL^?t&d_hC)l(m*A`q9 znYZ`QX?9FN8asX+!+8E2_U9}dR{^3eEA3Are?gnH=0xD1z;owhBFCk{U<6l;#sNLP zQBgETwj#XTl&TW-o=&9;WfbY=O{>!4;qsuCYa(BfJsV8v66q+x&vWfNp4~UA!C)Q> zZ00o>IM{!7`*r8VypP){d9s;}*_L#y>_)Q82uii^pqaUi1OUdEi7iS;ti67Vu$$_YI13SM66$M5dNQALoNR#_Th81@M@GT|UO(#D)D z+f}J?=c+$;kW=ESBU?uq5@LKoZ}8%4Z(h1g%?zF4$I44QD$8oB)2Ar%Dl|g$3{4M~ z>0+D?AY*{i6UjzwQMo5}3Do~HmM-l~l2f=bRza2^aYj}pt+YIRZ^RZfe!RkzJ5G+q z_8&XQf;pj-fSq5RY08ztybS^`4`E7K>+y3vcEi^5K4pUhid5CY2-^W>5#9hu!fpe& z1l)8Y=>EY#s0#`Y?kR_F5j$|ob5ixD^h?{`Q7ULsA7jryBz&@ePNqwuq8vS)wEtGf zL>=xIo{{Va|Nir5p5MNnR|y-s>itKL_FSJD^qt>?C$;dT1!*CkxA%3Zi_`}~IS*{& zsKVa{F!>~17tN|d)?15KN}3m*?CIILGZ0xbqe$y_xKtpl4!D#}fgwmNzVhj>&*K^+ zn^Gw}$9_)JR%S6Ak^=cG&u~g)0K^ZJlu56tJG|N3K=49AYL=aAzQ`_ojNaEZTiJL6 z&_1c;ZbRnt?)B~V5?~dA><}o%aT0$zb@K zd@y~HME&4>G;M7=bl9U6=#Py_6=4_@bE$Rfj?IHvk=%=Ay!#1}^x&kTk&rr{dg|9@ z%r!Fub%iSgJJ*;#y*_W`BSFXY>TCYs`UmF-yICs+u zj30Ndr>J$)dpG`lc;V8ekH{4-udZ&%NXN*?v+$uKNcF^Rv-_{Ieb6)!onP<*Hl#dr zn0rL2xw&~!WW9rEngPI8%DC0UiL!ry!a@+URu}G#ghL}Mn(sW>?Gw1>w%Y1)NRNyS z-7a##CspJJ%sV-14~^Z}3(I=q1cl1~u5UL}DFNYj*`aYr>RDXsDU)dl^7vv+0{d@x ziUTWe?7CI%8PK;j9XhN&lBq>)ib#=o_Xw20_1ge?!~tjQcAY=ta3L|eyw($Q7opx= zT;^J2U0=a*C(c!Wjio{o#vim{0Xs{$K2&I1m^Nw>+CxdREkuIwf}cO{gT_YxC+jNc z7@C~)tgHT;0;^f)Cy96!wcb*IIr3#he)p%wM~%;?vXM=La=zqq(|da#y9}-CM^gj! z2HT_a?>u@3_CA$$>TjQkikq8nay)DP;E74$00rMt@h1QQjPydW4y$~EMOUFc72v+G`cHIF;9MCh5;%d_O2kme>@LzcD3k9$+ zMNJwnVg?-n;dQh07P#h#j?^$Lh#rI-Mt?nzH^CjG{_*tkvUzQ>Bj|2M#xbg}pEN{< zDnpHUs(6t|MkMlgN#6(iR-WrTRnR2~=zb$Am)Ko<^7yeSU%h>Y4h0sWIs>JuEB?Jb zTxVc@dT1y5{&RG~gm^-)rj}M;Ixz0K$Ej0unQo+*0;ElwsPNGTIoLaPaxgkXg+`*! z!^jHkV14c#F&^W&jV@_!tgPn~o?AK-Z#I!}3vkX+f>U!(5I z?hRls8LBd*IqY!8mqUy5Enj%en$0{@nO{TP&PaM7j|3^a=Y}(BLB-f?K4b|M+!>&` z7^T4VA^xDZKsS6ZBjbj#6W*7j>`In%p|&P$jVQ2#15pn*j(MuD`YMe(1LS|6e)+m( zwm1JLed1SF(kILUxcUy90gnRL(bcRB>e5ZQUq2V>OhE7q-=DvSFk%Zl!uARder zX{pk{f&1Aj3KB1VC7?W1I8-;qol9CODz2qdp~^3q{MAUD8jE8R3e!WosRX0Wd`^I& zFX)A7!PPm1XStLjK|#&R(OgBVc{8xgycsNntn_nut?4n72#Er)#3DDf4w3zFpP)cD zw}{hIzI~aV-b`X1Is!_4fNOO&=g`wh<}@(S#FW)t-x zE(L|#(UjG<9O6LVT-0K-qk{tn09mmjhaG&B0*-082ag}O0Q~_*5d8h| zNKUIx%ZN%TuntZ)L*6Q00Awv?r;B@KVGvN2WNDghZ<~vFA|L_N>9irNSna6N0q%-0 zrr%;~Yu0$ZllgKaPY-=}ME*PMGXzFF6=v`i>NgS&c`3W&w#;>^Hs<r|H2bM2fYYhUaG!#JWNS>}%`=LNbf%_moag9`{H-h$AWXt~!TTA1k(Lpg5wH80HA6>FDbHtde z#0TGgt2FRX0tH@~G^h$xcof^FsY5aSH~X*Nx%ub&0b%i6 zl0l2E1)6Bhne+Bu(_ZJWqYt(j=$R-R=k1v?YTmM?`PO~^Smi_~^2%Eoo+4Kx?@0Kt zg#~6d_1Dy0S?`_@L2w7aIIrY3S6b0^fg)sNYlOtyHvKkXK8339>tU=IKw}8?X_YbIHfSw|YP&#U=4#Hz((I$mW%!mn! zEPw{VCuZCgbMxLY%xW-?BuW|@NmRHh6!WS?&N2sARz$GSiEcx*oU$&tTZa=PkKv$> zFamvpdU4iKR@Z!ac?2!RN$b`TWlLnv8rzjFXeA{kgZgQtFQ||iETBSuzTMY|%vM_0 zxSa+pai&XDKB+#G1`?i1wEmPweq@oHqRTh#BvW7}GF!V&mejTk;#mpuuxZnkoEt3u z;Wt9lSnfR8ye_q;(H++l6F)T0D&F(;?}&%sr|!!WJp_qj%cv}8AriIETp^tpk$NZf zBC?sJQ-;k2+^6rre>!>9R1@%GnQ4c_zrF3x)rHgl;p4FgP+YWVn#cnuVm4mW3Y2+J zI5}ObWq@1KUXmMK;L8cAoa(&{@L8)F89AsevQP!)1UOElFBGzqG6E(rEimZzqL`x- zNzR{Py(laSom^>#=={MMvh%-}hA8xY#%@Lc)UIV!tfxYkAbN0~M%341dto4A9Lnxv z$&B!35pycV!_8=INIZCEHfJv=?)hJwLm4Y(75f=pVNAHEk53Q&b^tflcJih9=L0TY zJj}lkbr6B@E~WeJO?i8h$L*~-uB6FXeqU5Hmnz(zdhidzyZn^EmPkXX9t*!>=Z>B) zD=B2r0MCohvTSal5a8{E-+Z2wOXj329F5T(l}qXdbGM-L=SOpYT{6^Z)J48ZChU0P zWF6|Dt<9SkWeO1tY&)42D{6k6#lUM#B{++wi5d=J-2qUflUvw2%&Xh2tR12Uw837- z@EmP{MA^IokYJuN;3Seiy5K(CGFq{K7URuTyCUp*jHw2IEC|ay=$ZY3pSFZSxaD;h)aG`D^GXt`oQn}oKy5RvA^$+?Wo>CJgW_XF% z!k83~ks^UI4M~ne>M<5(fP)phx^~`R{t0xkmjO|UfO7Nx~S>( zWe$VSWS=?cEJV4i$`qggd~;->RVF_G8sQo*7tz>?U&}YD(;vvFB#3#81qBwFcnx!7 zeTN>edz;QrpsHY|j!`vI0_SH(-F(;tUMGIsjJexgsQ#K88Q4mX0iB>*-9aA@D+agIXTX32rI5(Cwb|VPOGK|MPznd` zeSZEN>bk=8C9q!%LyQczoX40u2Ty2~mm#%blnP==ORIEy^T&e=*XI~sUw03sV*+lF z7jJHip5fP9RaK4*>gPH0=BW<+?^i6dd=o&qP$xU;`nWo1%FuPxt>!J-nWm5LlSkvkL9v*O2?Pg_lGAix0Uh938EKle$dH-^;K zRk6*U?P1Lr(-`P7{w>z7$KjM8a(XegIdE<#;O<1C?%@k2=k!AlU}OOrhf=+5n>Nd@Dy(E>8pVXr!e~%a zUQg-Wdxz-on>O9&;O^z&aUTs;A|%E$v0+0h-Ky)gDUc`v#Swc~7N&(rbOENX$t%}{ zc!zNPVH(Di`MZm1K>(og$$|8Ma{_{=WeIuWC)v@O_(oEk6X`A9y zA>zd?3jL+9*_E^b0~x{stsQOw%j&KooQ?LhX*(LPS-Tx{0W9Dkg@g_rBm8ucPlJm= zL3_DBo2gyt!MNC?3=FULpLpSxkPEYh}kK287nWdFuw z+9n+~k3Fgpz&z(6dX6m&01A)FPh+UW+0irT7(A+ZrW<5?VN9TZY60d(L7ZP(rwZU3 z;pn77lD`sQS&XveI}~C`mU(#cO{?73mg74==6ezXli>!Sh8au=vF#OMKAJgGk~UDl zVecokgH=>kkv)*Yb#1?!N_Prng6gf>tQ{GQ^*zVoG@kb@_FMF28rjc(PXv>JFlI#f z0fAhKY_K&zZ0+LXD~V?KbaF5eB`+>sio6L0W-|D*%jfg@p|5~KTXs}=iyxUrww~@_ zFZ7M4fnHO>O=2DUx~OwWq~$?=YPC$--1(>H6z9Y|{Mx=Q?R^^vMhsWQO66O)i{xiT zgw84qCb(W*m)w_VLnX16Ayht2Wx(d*MFiy^8HRAE3=a;L zZ4&eoU5!$M&YjymE_a(JLhHj|7Y|ofqi4K_GTeCF96k_8$a~rb2dnb+5r#B2Cnwooo$l1B zeR~;ILOt9zpoon$FH7ERdGWobvbfu}Ar~hsy|zXHH<9E@Z*G;tuP=#=ldj3=y7Ygo zKLsql9TdxMoP7du{f14Jo~!YG^}`Av0x$C=<&A^Dm_K#Zl7gp^-z$nLK0;GciObkL zY|2rU`Zr#)W&%x;mDLMI5)x%-4UglParbT1dJvGS=;8#sMb43*ofhQ@_4mrRqK}7C zGM5lu!fwg=i=gIE{j!4=0$He)7>6<7xeuArJUMS`=J{LvC>j8obfm~H7#JX7CwVHGA&fw04$UYvDjA4}r= zn5d|zpOC}Xcy?UE!kDpSc0RJSAq=x^<~BMsJ!H06Pfw~RSoqQ#UP=dK#=**}*m*+$ z7Xa%YHl%!}>-zv!gALEH(_ zDL?3aL4iT>rf)Mt^hRN0v;EJW^aE$K1>t#a=O8b$-3 z;W(xC+}LR_7jtRv#lUL<78Z!x&n3p^BX1zC%?i;gv{(k^FY=;UvmWNwID#Te4wL~a zWDpwJZkw@BSa5cVIHIADK4%=8+kG32KCICwiC^dQ$(Tr>EJZ20EPO`-37vv6VXEbwj0<6-e{e2Oe0_YIx{%8a^q;~B zi*()QrG-k(D^YhO$_5l*oLa{@+S;=Mk^vk=iUftlZ|`QkasUAo%_n@^x0mw+k_E>{ zTl6Hd+o&=p6@mu?gfcFW<6P?$vodF>rU%jwKLQ4QHJQLwtp|H%MYn-V76OR2+;Epv zBPWi7%pnzT!8_dk!;#t2gcM~25rWvK1`BuD{^y#G!;PPE1CWV@BA zQOmR@LaQ*yp&Zid=aPu&r$DQVj81td^*R0oH3ool{tf4-%^zDJdihB6j=ybOu#LR( zGuwV><~S6Etyz?JVG4;@Hj_+X-Z$s-0uLogq=ej|suSzdoVS{$2XcT0v>?+%(^LG^ zn?hFUhabHXKVt5*j{pkNe~6a}Yb-~u+#7thZ{6El-iVBe#PTtU(y|+2O!Tp03~}Dl zbDd4pp~nZX`II;WAqgrQQXcZ176p5yClt(dh68YKEgtGi_rWh%o21Fw>w8?B`KUTx zrBu6~(|rFjh7UxI=^J>gk=k8G{%?CO(k|H@MdB@BIS|6(E~gPs#$k4)X}r zV;zkaUemi5MF1b{)xu}~KE!@dJ*o*K{?|{OA-xMo00x%6>}X7M^l6$++Ry3WNh+%9 zPqx4?bG?M#z@?%Df3nP|OD;TOsu_An9~kR1&NcR6^EEfZ=AX~wA5+>DIw`z;p zUW)&iw&1h$6C%(fs(E^N%%CrznkLlWUo}oaN^<-Sx!+QH(hGgqe0%!zFgmD_P8FrG zF&)k&ult=J;4WYeQc8`$-aRC)MQT55C5A+$$u`(fvCv=s(>2UsCXmGID zafAJi#%Y9{yFKCkcM+})7%t#j3ADmAqSDE-o^vw-d)bwCnDl^CnD8q23XlleFH;PeAVU3K zHMv;^(Aa z4?fl1l1MJ*rH;fpiV6nN&z@JQ!>W9Mu;i+2!cQ^Ag8e&x2y~QgqE(yV8bmab*x+Nf2XV zg$H$R@n;l#GS|V|(&n=vzPR%>7kBDJ{)$ynkj+=M1#{-GqbkAowSHMLxy0C^pufnr zS->$L%?m;^g^n*54{R?iKUb~LX*-Y+v7+zDk;(ab_Mm|)nEscUTF%9n>!n!|8gdQ8|Spa>+0TDops4jgY1vOG8g7nbH11EiaofJOrnM?I|U(&=qcrG*BJnf(CTboEv|@}?xDopgVwMvNZI2)rD8wh|02F-3U-&P zt9HQ4?(X~d`z{XEclb= z6=TT{)7Lo=Bzb@EtO2P72qHuOB&e1tcoCO4VN+#AfRg5WhL+L)ryo`STco{V)#=IU zgY*Dd>oc!)q)IgfTF$1%YgZkJ0dEqQe zg@5%q;R7Rs3W9*kAuGu86WS@s{PHK zrJFWy7Sk+73E(#^O0yVqR3gj=+B8yO)Iko8OU$4ph!fYkm zcb=i_i9gDHMiw{xC>x5~W_kHqyq}q~icM~;+wGu!=xRhY+o;=`H1?w)N~9)nWAu8@ znt}2(W^4h{f5wTSubvgCD^?ZP+y)fP+h+Zpf{F%rA4nrge9ZC9{yTm9e+gC_P#vF^ zw~$>;B64q7bOY~*9~`cfNH!4muPZcmsTv_qHNl?4$Ne{$7EYQAQ?@BW!j(`&J@hMLW^MnGtqxg z7Dp-HOf3HJVJ20c)Q2$gFvC<^(~*0qFZeo^q#?gf9M(ZXlpWVSdGR9L(gHVujKGo$ z?woTuI2$8}uLSEvPsd*s>Ilf`7($P>9Xqbc*rYAXbJNX=2j8k#0x2gVOjgHufgF#! z9c#PgHGn+@UwYKo{+j;IwKa?~>aV(97tG#W;?sz^C{rYJKu2YqG&eVw2cqgLQcC1# zFX1;~D8-f&X?DEc|38ydo(XDO`Zj?3(3{nup*;CVlTRMh@K6%vW^zDNk}_%D^XyrZ z;!~aWUJut^_LG`u>?_kWkQy2eHJiejJXc_2_YZg4|Woq8`$!?oITq9y#Gr`L99 z7d3WHGLx1xI}DjS1VndWW>8Yb3m%5p$tq4NsRy*HeMtizIRTv!t;&C1UaPIAdMIJ; zfJiy|K8GFB%QB@X2_b0*VK89|9A2|Pz66~f;q|QJsQkaALje~OL^wh4iWC#~?h{gY zB&DevG43TR+6-{!18TpDsUtM*PaY1i&%>r)^tElsI>f^iXQ{OEEuUTbPRq82h6=Xp z8tgYX4BDA>H>|fq0LJjij8^GYh1ZF78BigzsH37L<2(h^la&0<)snu4m};^ zez)v>GyHt%x#i{?1Ld5uS!X5^XV{e{5ek$OAbVth|F8Alw3OLiC@*Sk2n0kFI)lB| zba`^F`~#zZjB+%*i>?Ghe$m#yPj2H2if@1VZ|a0DX*E&BcS0+-Z4K8Y`4(lkGA}7K zA0m`_SUd;?dfF;fZu3RmNQFPg*m@SlgZWhOx+hLdyYiu2(zM1&3fvi@(o&S zkcU-FO-KKJe@H=1hAV4+o~l1{C%$ZAar}p)pl)r906e;0$)b=VnkTj;pR>Y)caKsR`%M`ry zYeb-D!`A&DQ|AHKbK8b}Bbk|5*((_-G>9^bBq~XXl#vvbO(e=JiHuYdMM=p>c9M`} z6-ktak-ZY3@qW+T&-=d5$8&$4=eGX;-|xE4ah%6-oX!)XCxvw%Ja~%RFyla{?BlJe z9ZU_Zd)K6lmzlKl2g1VOhSKM)SaB}*)}Y+pqyG(2!K=py-e81=g_QQxU;h%u_3Ei> zj^{sm^ytvNk8t-u=ad@Xjr&HuCu%va!(b!=P=UT2A2DlI!J6Zahe)a{1H)tD>vOkc z(Q`iWTul|MsuYjo!FD0(;^@k1G7|vrzI*S?t<=?_`5}~xj1}_vT^%8_AeQNg2 zMxq}Szo^jAP@7w4&%$!WO!yj}T;)Uw|M+UidcoKjlSYTrSgRhKR~lgvBN)R)5d)lK z0)#xNRf`r5|FH$!Pjb-dqR{EVD3QqT*db%C;X7L54~?>*c03Mqt$~n6HJ_-#e20X; zd*8mOm8oV&ExH-EBwaN(+*7Rq91Si)%wV!8ez=i;&m<=H!k~fen`_?u2D1E5t{}5C z^lpG&s?FG0(^qPKvJs3EY7G=xDY&OmG4P+v@S3QTxu@Htt(q4WI8CJSc zs44P5ze@t5@^oy~A1MH+w~bx05j zRX0JvRgrLy{@11#*wL5P1~z3n9~jVuUUXaR{4~#wi=hdMRLkoYrQ3 z*?e{&a40<-wU5v#kwxZxyc!EU51=c}FVbQF-5>FP<6>fpz&$|#WeUR$U40xXJ%6xb zbhZd$h`QRPaW&=Wg|?g6M6)}cN*23Kf38}{(OZ|(uYTIQZ{HGNm|C37&w8H!E`_)I ze4^A#&bQ$5EAwtYdADo^B3S?)@zN-m(xK`P?{pyiCkXF0ShvyR#{62emwt<4_@1!y z5hx)^b^5NY)`ZNT0vKpb&}IQb%u3BW?T{YOZ9-?k4}>6Yuk?Xlo{Y2Q36q&sNG&%DxdD>6D^*>62lf7$D01L}YC0X> z4>v8qamt)qdpLib8Am`9#iM`yAh$6yciQ6>Uh}rKJb_vycR{tljbjWvYMOK1-$PV? z_oQgSd-lRWlPLtTC^BpTA4 z6evp}aO`&bs-vjunrF}2QK4x=3DS8xhXc&AwVgacHiU$WL#>GWh2_-w)$iUEv=UO~ z8Ze2Y=}Lv^!b3d$bZK<9b00M|dju{RR`@fYQmr+r| z%b*b!`vle$PTuvHm=A&j10{bK=dCm`Crh0v{Y#%;i~+y6~}>Wp!VsU?F|)`S@)w0P0ZDRH{gGINqIb?6T)4{*nsm2@@ zCbd^pX_s2`PuBpu?^%2`tm#5Vl~?CJe-0Tug`rcK;skuaD4V004n=5wt=*6$3dlwTb5z z6AeK0#nfH`Jrf!JH3iqe+&_$md5}v9b|NbgS2i8D7ZZWeBVVk~`4_I~aEe*oLkR`j z{BU&Hd9Wj9ziWTy&Ib|UmIZqJa=_La?`7HPD6>NBYawQRC-T3m%txM0u z0QvxsCMld*DZ7^|Qe0B9QuoohtpHy1CO5%bWf=J0bEaKjPr*xo0r{?i)p}x;8wbx) zi4qe=;O--7p!+h*K(E6Em8mZoO0Zkj_n{~D?;ALiIWGr*^bfaK_Q#-*>G0~@xJ6x$ zU+r^+#|UHG9+I7mpb6l7micCV`m$ z;S)L-n(n^^SHG|)yFJTb3PBE+caBwS1eK^O;7FUY>3s+cltW@8Mhiv}p&q;>5@HW_ z>Rai@mvF2T2CFL@rU1$cYC+XbAO$LnJa<&hO*++ks)ZE-)JP?GYj0*GbtSj-{2P$Cd zce9c;(=05!jUr{B>vg<;!e()Gz`0(E`UxBIK zLpt!-9d3Kq-x2BqojmhT2T0G{DH{i8v8HQ&-IAmYM^lW}2%>JQ<1(En12-X3s{WLb z!?5HVt=>^4&o*H!`;gUZ_hC0W4 zofSgT#EGxSXK?2ZfQM(DT`&a@q{{uJF4GwiXhLELfaKo9L#G$p}z{x5vsHw)L zrrPi3!z&&t-5*5$9?*jzDkhwi89HOlq0~r(nY`sWGxtp_=)2vh2Nm{g9PgyK;NAM& z61b6!3d{mWvAUoFH;-GKUNYF@-xnL|_8UC>`|TcHe;?eV_YK*j4jV2QM_Ll;~HVOR}^A=#A{WBfYowOv` z@EX%IGI|Ue)Dm5jNtD}E@OiNzp~kbeEN<)?pDL|VL3LFSSkKG1ZyV(0JvCTYalzRC zhM%9`H|&f#c3O*`?ZH0b&(BX8%;grlyR&oq-Vuv2QG`F4C1L`Ki-IxL15qE)qqgqf z`5z0C!}&{2VOt>WJy&sJqwB$`G$X=SLid}6&Y9SpCLFoplg*W@D!+K~^~Qk}2yRAM z0);vxNk>VsE=8Dt)OmR`K+7J#?NCHmTbO@ouV^hq++}04V8xq&2sPn}@yCHXmDv8w zSiEf65oBllg6yHL+(@2ap69Q8$9p9wg}h0TbC9#87l3ooTtF8TGdkDr$|dRsK2|1l zaJWZ|gy3CVo|+NR_m;<-qq8n9*+gop^N_iLRs0NNWGGWr+1J2tx|@LdQ}%+18fiG3 z)P0PNNdg@l99JF$d!(`YtEU^*+OS*Co*Pk1KZJYtta?`Tqi+-?!c9ZKP^*96-&zRw z`72h~emM-h1O{IvPGRtrt8<+HSjs4d+O_)gKoqgFiF&F@MjWRS>hN;YHgxZN7-m^gdVHFoVev$2@CGuBt$a>kk3_f8Vu%62!EwadK%-#0= zdHA6W)k2_P%tAwIQ*Vm1N;)*y5T>#fMT-F{&!?C9k%;e*K}8Gx&ii_&D(2({4>d|=ys zD39dD=_D1vRSXP^xQ!0@smaE2g7+KU4}IyX=%|CW9I>Aa(Es_gOVt|UF&Ks;yacH9 z`#UWgq~Z@xN|VPakgEHqXWFqR@5yYA+K@mCPsh*juc8~!w!5`PF8|y;_!2L^<5I=mxc2)XaA22aP{v1Xn|BQRl2r(ewGWS~9PUGV&|{`w zcVD#AnTlPV=!?XYtWT@r9A*S)!K5}74--R+2)@b^PHc57FPab49CkfZsUA$PMAZJT78@R{hQ>K*1_$H z!(#iKf`V}A@o~8NeCfjgzY@aF9Y#bjLcw*W6;_>nzp z*{PHG=8*7ULuY@CDx?^qK%qZ1i_J!TZC&PxoJ8^|zrPeNscl|f67&Gkt+H{BwbJvx zucnBDgC=nzyS*l8?R9(2hm_X4?doDi7NYAm3CO|;A*6Vy;dgn$>ThV4gOce{iy{cl zd`4Nk%bS_aHK3))|L&JZ^|lI0lc~onQE^~KXZojV9?S?tHIRZ3qc7%aBxLNLI&B&b zHMhy?1KTx$B4g9>>!WweFvH!+#}&L4SJk_n$B;F6gc1R1{yxm~cm{bEt16*bF1*04 zRzsJ^OvcNvvn91FoupU{=UmhwUov?nn&RL6Wc*-d2~p)oDL=W7bSSk!)&N=`I_rOZ z-`dQ0;>5XV?!=dr+lco0+xg$!2gqev4AalD#^lJLiBaS(rj(4Ys@nwL;{Pz4r>tta zOfO$OU}}sd#j%*r76Pkfl~cB2AizZdQzZ+fe7vg0$DL|vQfhKf+(gHgwUs&8&Iyakez4E@A{ZZ2O{oZ`)liy zO@GRw@ot}o^FX9xBNxLc&7eP1AMl{UrR@FTB~b65g}U>lcPBg5EIrz~dFqr~8GBSS zXc7VG?jH9)|HV@DOL#)@pORaL=-81jB&yYYPW8xvNm%>)`?Jkk-)O4%1O9#I6A#9X z2kg-0XS)$WKqbhH?h+AFIDqONCqqdke05P2Z`-<6v(Lz{Yh<8q;Cab7R|)2))GZNL zRsK_M;A4Oi?5$D85qLq;$_pns&Svm#lg6~LrNUTUwh+M(Y=9edpm7&tEc-Ga6enpx zjet!Y!)En>5FrJaSH;UN+=Pd(O34D~G3KGRq`9(DF8u!E$6VTe*7_uvqUa>{13Z z5iYVou7K+NFe!j=;q!|x;}UZ+Y6(M!%3NI~bq0fUu`{6>J_C<-cfv@6zaM$Jvy@Pr zU;cb4quA7i(@Uhj!IKvS2PLMHmQ3Q2Z|w&I1!Outc!f*qclU&zb$CP7UAuNY zv|)ZtRkPRy?S5i`E^Q!Z(5msVr;kfs0WKZN`EWWhQT#@%f_K(D+*3PPy#(Phg{iXJ z>H}2XSWPgw9t_tl;mi)2S`t8#-K@Xo?M_A$a+B-=GM(b|6=7T-$x{N4$fU3ZAVDykB%>&nRKH zl@N{Yop5_i!}c4gg#?}ctQJ>m1W+qOC?QtRY$c?X_Yl=Beq*#BkK4PmvTr_{?T}2q z+xOu*&zKT|^vVQA{#rW!;IiqqKABEqqaO*vCAtsbynEbc(Jgb*$vD-j&CT#N1QM_< z2^wx_jN7 zk_V_as8|`4(Hp`^%lX-kDI?y8Iab^GOeZT};s6mA)`>icLVDq%MU+jWusrR!T@Tv^ zI{rZm>dHhKVav1P99aX>{Q7jzzXea?+M`V*k<-CywrgUQ?s{&>p@^IhRO;94HBq)s zW=i%!zkN*w;DAcU^d(peONL(UOKaamQB=c1!6W^yTbXbVJSgV_;9gG#FF;HPxNz7& zk}(Cl4RB{dAfygT3k+EgQD-p1m0=OAxcmw>AKYLd{xbkDn(1Pq7j+d$2`8<({zg9F zvgO;BMP}Zn_eIKn#5nCToDLWh)0dqncv)B|Ym^0_6ulf@-7#nwPB(?f69AJpiIpp8 zQN?G~cINNIk#uC|shOw5%fSkfZm2fZiTLaf!b}7x!U!6^E9PR_SV% z#tGtGfC50lDq_SbgbM%8sPTls#eQ>Q$>Cye_1?yoZ6S7|BOJ3NBNa#fXETFaQQw5ye*o1S@Wm%rjYL z0hg=~&(QIKskt&u^DUy!1HNN{Q>7liPPB&8<_|qdPf8a&iBU*)SrU#BW+AG{TobO?0^1_0$7Ov zc#-z*exU_mG_LElng3K8diepJE~OcU-E)oh+6bDL&%N_kX`^p(@}Pt{;J+nA8LEA} zqwe4VG*KlL{ERAm`iaAiQZO0$t8BunjX!BV7tT>PZcAvdGQNHqRS{MBJpLu2emB=A zA{o**!>z0j^zo0ZAnUK-auWn!QSgfq$^r?f#zu=*d25l~BRdtaw?8e=o<5R!|M~|+=-6nO-VpeRrg>Vav~1;-?eeF`ri_u|rM zW1Get)ZsK;PyU#%>p@-3EGnFu@GCP@M!rrfbi}e<++d(rJRW+(3MIVoA4#AO1}N4MmkIxPcJQFP5cM1bEIIHUhOf+ z;{9xrSl_<0>30Rk1B^#!xyWMQ4m{)dJxG5aANPOi70-!5^WU;#M>cV|;2^HMhP9|o z#3z7Wh5vv4t>?F|UuA{4w6`F5A)Z&Yg-gh+{E1D}U3<+_Y*3c?OU<*c#as2heY>N~ z5>hpiP4Fqgid-HR!#+Rf$Sz0m@FDFcw)dfs7XCF?fxmtt2o@^!oyNI+YEcrMo3L$c z%`0<>iCI-kw~H$?xJ$3=YDS$IatOWBtmj$-H8oGYXw{O*0uQK$Dw2I;#HG!nGScUzWPDl8gAo}eAq@_|B$8o~0rMHI0 zgO9&Vj#>y+oDsquY;m2FS81IEC46*c^->%;?MmL9fmkbk^uK?LIE5ICc}m3;1&ej} z>@_hw;z;5A`0Pkw5YPquyh9WkN_x5k7#ULW0c3?W5$ljm%EgeYeU|TSU!kvk^o`UJ ztdL*^kl^uh^^`nqT{X*zT>fQYx60?~ZJtN&$ zF6xuZ>;WKlXaTQ7PlpHU5?S$4o8-Ql2`MD|F|pY%zRPB90^#NeHE1LSr$0REsNLaN z6fW_znW6Z%w3l_;6z*W}r}-nrD-}kRkKGh=WdTB%7LBHbb^BYhsf5~Y4*y;5_>20) z07?T1UOe@XfkqR>bXvWB0D54CnH%CZn_Of3Qz8HmmG%v-sgNBSQl0~A!v9H3QaWKi z;Yq}>gS-jG&Mx7W@2TDX--DcRv^y3f)NsMeu4Fn@Oj%^rp@|}R0Q*+vKzo-|Lzh=okozEHz89XOF=y=E1QOjie43ttC2N zDudj&9p3merJ1eSj+DSA)jgCaL11hLR~0wht)rNqpWhzw=c0Gbj`3}oh)|aw2KG^^ zGN9$;eAv*w)0qIPs-8b_HV_3H?3aDf&p(LuFD4}_NjHMIm_qW!JW+_VRKBtPC#+&6 zX5#oG+c@!1e}1m1SHPAnThePE49VK)b*tsF8X7w3Z9sCeM6e4zs1}M!O6p&uxQrVV zWw=tGL>T9J=Oj4Tl2X}z+hFk)2xF@1>i)Q9i6@`U<6{*Mn3it`hR_R`qP$5YKRGj3 z=08!&$MZ*&DO^~1zmt9P=7XkYiU{O{Z5nz=#=kcgwLU>Zg17P8XMb)L|Dx&itJk=V z$Q^`cZuKDSkA?CkxVzt|O1@vK+w37v!6Sfuos$7NWScvU;`>gm$HyE7WzC5XQ)uEU z&hSK5SbUY|?{<_4+l?^wo;?+S|B0ah1Z~QG|JC-ps^3dh^@*ZoT;^@Vn)hWLlw#ji zUq6idecB~w09d_?x$&{&#>idycwnxDi^8@MOn|JSH|jFS{IF zbA4;)T`7r6*NLb4=NkOrPqdp8;#o2sxieLQi`yY4LLani|Eox5B6$&?OMcZBVIx^t zt+*V$EDaOqLtfQYR_gODyRbcG;(;N%@PR9pF)RgZw#$_e13i>5YDAgTw6wGdgA*rW zj3~>5VeQG1WSX3OPAa@ee!JF!EGn}4AY-zTmCW+!o%5P={1QyqJf4SN(*@@F$J`Y0 z6O9yA#~g}c`RpkPYFI}uO|2k>q^5sH0 zB|9-ZM)C}Lb8$u3^?QY@=_mksX)yn(UW=$@g;aLu3JAAQG{vEl8Ec+bbtM{~qbVo* z$%!{_OWQ?9=^J6Mr7{!%>ScXPAY+%m(X|i>MA@~f2@K7jm=o$L`>@sR!3|!pr)7VV zxR%?C11P>^>o1IrPmbaEDW0&3tXU47XUV&)USOXcmM1-d zFyTNH7kMja*h5rcVD_ni$&|#W-zNg0Fw9Yxj+5k*FhOV6KM;mzi_$s`+PNqsBc-*lM1w4jo!I5#!=~GetLS2+k zNGHfyAOLiLU?u;iC?ZYb)-Pt;gSd=$eck0zR#rJ9gK`yK0BuCv=R9WC?7nrKkmRBT=7N5!t06bt#sMt?svY9|N=)MRg%fyicc z3@8}=GJ(Fq$F{Y7K1;#OxvC-r07xnRam5J?TKe@9UoqxNe5^^%&V9+gy`eMEZN^p& z*KVR%mxg2>7l<-Og>kIn#T^$(oYu_4$a=;}1tvZz*T6zozur4-Kaz8z`-%LWi=226 z($~qB7)qF(!NJB%{CpJtGRgU`qD3zcO`~CxCO7WgQ-TyA?v%0Fi5sqtm>!;7Qj#)~ zlgF|9v@((#LCpuI{tC}frlDs>=@xqFpM+&mBeX{xh!R-V{ZjjfPxT06PLn_k6M7|~ z_}I{WZ^)w9)23c_ejCvYU*l5hqhd5P*PUGRurdszzRj)n8Aoc1^&pL@der zu)E;$DrKcLskb->HZP~=XheiJ`+q$GqTAiOvh)&*=VUM3u$7;Cg2F;%Y|*S)fX8In z4c2_LHN%{PvR(xM17h!@Y=37;K8iFM?4Vy!qpNP?Ha_&YW0iKwz7Qp-Q}L%D0?3RO z@}g7rM@2((+(u8nr9~t}!eWlisNeJxrG z@pNP0Z@Vb+8N_?3^I`2XU7_mETa^1WPV^Ci{7BbH-^$$w36C3ej`1+e1*w_*uhu^H z=$&j15zlc#;(~`Rrr`!*yjVr@f2==Xq9Gn(LdGM))3aJH`l#X?QTXxWL`pzDs{^N+ zQq{Ur?}>$--F<3tYw#w4h(?SEr~Na!e3hguNw1my53@x>V=n1@Df1A3ZeqAW(x?}y zwt{SA9WlPkO0q6p!i^egwevT^)iRg7APfU!lqY`eXH5X1o472jXc>nC5?SqElzP0O zw;c}KfINh?6N5fOJ40#Mg1X4%Y~e1+G-Lh23&a?T%8;%h6$xAM>AOvji9}de=N$FGJEElSbL2OyRKuG&N_+V-RW1gOIE?H|=zX$Ncr@PuH)CIZwcX zU`iLl=#oGMw?v38Gxv=@VI_JdUdvcqej^vw0?;|b(i8C|quqI>r3o1Ub#hxp4k>H$9nH*`(r>j1FTTA>N#2iSljPybI1 z!{9|JFtOByH}vY2xMHlvq60gdUYeR;R}S6-k|*H+BGg%@!AYw9WZM9vC>!Osma*AV z5(zs6g|?QH*?HPX@`G&l<3hxG)W6K%DSr|^7(|sUV5w){XL_{(Zi|TME;40aJ!4}< zrUPXIJfHBG_?ISQ$KD9M<@5yik|L=eA@zy&}Po!-@(EM~)xAHG6P^5M5Ro9s1$xJEdap&Tg2f3ls^Y9>PJ z!}K+eQChRzV|CLw1W@=>BJP6b;qmLOK$JDAf&=20CTjZrD~fgKume)lWmC zUJmuriADn@~zNX9L7djO5-vihkgxvyr`W z;-@FjIqjT$56Z=alT+HF)ZpCUWTpw~hG}6(D$L{`Q7+h1bG!vvku>VR@8}V=M);C} zH=x^rGUZsm4Mb>!PwfXg3dS*d%owk4Uuf<{hfjYkWu2e5D>E`6cpq?u#T4&6ojJ_a zr;$Jcdzmm$)nFQM&WU{srckHAVPynE_p4>y=6M*?lPy$AXFy#=r0BOM4smrR1TevD zmo57->(4LSnp(Snz$(0b=%@mXG10kSyyf-XM#td5?B%8imYjuWip++_j@|fw-wSY^ zY#T);a=rLZ6`??szWjQYD`kvWuH$BVOZC?$m#D!SA>Hw9P6O&qZh zVUF^OrvG?lFp}O{3NadJ+D686D0*Kq*l^&ev{`hgpYLdfm$KyoOTt>NKc|RVOl)n$ zd7b=!Vp_~aTcjFqPN#K#2|FO}UV}fE;~s_FdW#y3X_2-VZ~14lHx!*$efz;L~$7$W9oHZR*FP5`auF2zW>rHkQ}r zgAo*H90lRkBF=e0;#Y6f06nH`*PyF31ngF^kE%Jyx|IK!5N~Lz-XSq(MdPXRby;!i zCjf)8Tc!})L$p9V9oAd9Wo{Dcez&pt;$sKC&vLAU3pb{5hkqxtla%t=IdoX{Or4mb zH*dnhV1drNtSjFj%gDggL-cnF!rEDlaGf%1p*d{nv+_03JjZ`1itv3#;~hPc1-AJDj|n{vNd0eTkB0ufo%Bx%GG}|14+^h zYeHtWq>2$Wu9!Y!d$0iJk#pi7x66}?-sk}}(-SsV|X_TCHXK_6stHsMfcnL!#O&rU-_MCi6eqO*P$NHMhjd3e6^f z0C9le(#p|o(op_B#@v#`8EJNHcCEsf`rb!TiLs5{z9 z$=GG4lAHQJYe&l9b7@i;az65ugpWa?>0-4lqt zIu2d3k*f=(WVXev-8I$dP`1UV6Ja?j)aYRw8k1kj9*Fjz;^S>zZPW;pCqCE z`W>FM*eSqJk?r7)i+<$%NERNO`10byylYLOEk*~2pt{Mj6VxGABkED!k%@8n>!qis zqM?EKc>u@_h>DOo`2-6xhjadz*K1PH^abnEb%`{O%#^izaF=A2uC8uQ#87Kn+BJ+v zVME{DwcOd8TZ%S&46g~!t~+zIhda!82IuR z!)4e`!2mra*~WxoLHzUpwu3uOl(UJ~q60%(xPs}a8<)!yAb%jxuvLzOKqQ;PC~v3* zdfo0Tg=FjmVgao_%#>E_EhCh;WRB^`sicHm&2~ksXRb3QU=B8Z%)e=HzhSr=1E%ZY z->K`;V*S~P?-3&kUghKy91b3wL`TdBt!7pq z%0;94f~OTOYw6If`Au+4bjtL`(P^W2q!2_yJPq;|R?zv#;uhvt=RL<5P?8ES1kF?v zFjJdoRag*_AUU;AeB^&@Qp@EMT@b~nti$3x0@nI+_P{nB{c(Dq4CE)=8Lp_XS|bW} z^IK6ZVv9FS7(Yo7{Bh!Ml8f* z0Vn8**8rK-*sKPUv%=N?4mYZ{NMHy$+JCEB-)(a2O4$=zK2{56#|#_qy4F#X_t34% z8r+3Qm7q3w9{r0D#Hhq%$$9P(9dpxUUySK+ZUUH6M0KJ%BHfP206a&#C*D}BFs3@^ zxk%Rv>Txe(T^|}|G4&CKG;5w4(7&6kyE1Eg3Em^v-4lbp#z#R8a-N!o5&C&!TYT-Xzjz!mOs+Ob1r^|2&ofo>>94PG`tpv002#`y0ZW3^e ze$@8y`5RmWCK&%SGQn0McTNSKU^0c3ONbZi?p?bw-?o=MjhLYBmtu~z@-D#sa7ZnC z=HJXiWXuoF|6H#(cp>yKaxstd49%zPePE+IA@9gNcSG~9U%ws#x&lY{2H4!+sXzRG zSrx$Onc1@RI#d4NhBWKJwkRHB;Gz=~R zXeKRd!xS_) z%u@$3Ci0l?4%8&<7;(!XG7$M3N5r@(`9_?=EJmC)J?1~#T76P=*l}Vqe@NcvcaJSZ zd**`;7`sL!(m77m5lzgnl{LOf0D;zfjHgafop3TIbnVp$H5uhX((q%rKf!8aYm8gv zS<}9%{imq?VuI% zE4Ti^3(_9wjZyoxID22dCUvGGV}>QO91XQ6Pxa#DFn-F6Gra=Y2Txb^Mp0CtbghD` zkpxa(SZGV}L60MxHeolQU4m(dq0J@r6lLCw>?Gk+t4sYsLnE(6N5sR3&7;eFc zq@bc8!>lita5$_}qdi6Pq5ZD5$RNLX9kzwg|gO{BzO|)KusSy5U#!Y10L0 zMNf7ny@VOjHw-1j)EUu+iu-1E5O2n&G+uT zhVm%ERZ%GN7NH2{eOHTxgq z7~2T47_94dkRWw^Ewce6%5;$|;OQ!*z*6Xf+prtf(z5hUkSh0-HH{2C6yy$fCh<}^ zFhIMjl6qvlZ;HJ=cbr5kauEGrd1J7FI$BzTg_J)xF*OzNkJ|9YtKKPLVPUd*mu3~e z!Nd)CX&Ta%ZlLePwrMQKNH6Su-#OBa()Qb}Dyk<8b1V0|NZ@cPyjot|n6G_1J}wb zG#0Fj5k0XGeL){4q%tlYKK#nLU+E|7VTlS-M#RJ!BN_=~-=$&*%8sC`bECAnL%oqP z=*pEPtlv%Cka!7#4U{**HkimL4L6ZER55k$o;|`)s{0U30-LNwKUcc!uG5#1C=I8m zda>BVBSp1q*J}~Rjca~OKG#mjIAWffFu|CIx^y@j7_y#TZjrrbG=5t%f#t>3N=wDxrbDTFX<3NQA{DWk2H~&@ z3%a09UCVYyR4OyBtjdfFlvP{QEU5Gv>3@R+#WhV9)^a zP*}YJ4WMSkIsJF&oS8FbFl4XG?1iFQ>Jwtn8~(Z&y&gEQ@S9QmmM!(cWbBCy zs=6&t#>c;*7_g_|zVhqE8nL^<{?=A|CmD7DbtLC?F2<6u-y2cR5?~ykJkY}!oZaX|)S|`eckjJ4SpAHJz0w0n3gyu7+DwO0PKYind?ArmLw$6+HN8^0WE)^*ft)9c!i# zr*>xif}`G+CZBF@dUCEf@%f@p`c;!$Y}cIj`{m^J(k`h7Jy1JO6t_g+ZlP!XK3MGj16Y z5<){BXVA>@!!kWi^&DcJY@pCt__S7XL9@_%o9#7+^jzN0w~o0o)aebB6cXc)#m34$ zPR8$#!~0<21N4^1!)&fldrPw}oh>iWgnQ4bd_PT0PrW8h8Q)xidaJ+983kOD$Flg^ zBA~HCodybZF1!hG`SWqE)Wj-V`)3SUT&zH6+t4RvJxs&)B9VB!wCC~(X_U_0G6oT_ z@G+^AWanjE4^y@lrgP8qf5{sf%V;>O{*AWk(>GTCIay6&QE66nbbr?d`-#d`h#IfY zKHcQ~X(D_lnW#`#*HZL3T(CT_XUe-}#Z2$g7#d0fC<0>Loc3~*mP)6%LrT!;1*sxpIo_!YAV%Uvq^fj`8WHUMeb5^ zT<0TweK*-lg*^DxBWdS6n@=j2Kg3^FTplqCsiq)I0_^20MXvAK;FNX$Ri7`G1RCsw zQcqR6>HG^1m)qBe^H@WMfIY-te52C9yH-%fa^p3ny~_H2XS7iJVgBrUN`=4#b zZ?=r6=!OnD?8hH6Me#|mN|&rP!&)mV7h+)~x$xWW@Ct=#cB^~w+6TRIxXCd%&6!|) zrKoYWyt_(=4zjjgvR{KuqmA{qWINx)5os&^+u~=})d;>{gOV%enU!XQuYS`Wy2g@r zu{@H9Z{u0~dFm8K%w3x|xb|*YQ;&@cEqWxc`{p;RkZCZIha2kW^Soo@FTJ;LQI&_d z6OG4L#Kwn@9_ z+PcZ2MT>^8vI2dG@2sltL1N%{#qP__dVOl`+_g(QUL7EP%SMH7pWM7U5MADt9$GS_ z3lwaMF%>w7XC(Dy3vOp?);S4J!4SEruD^`!=7>rb^i_UuicHj zI9#rm-l+-^Z1^bmJ&fXIix)F#zwtc--90tijpfX6Q|gCJ(yi0FC3_NAWj=f6tNUVA zU7ifX&or*zh-1I<8qQk1HR9O)NjfV2YimycC)66xI1qmLEegND>6DrB=JQrOUvz5v ziPRaLW;P;7xOslCb#ijLCVS2_Yw<{AJS>yOJoi*3Cs$XIY?zsw*O;Ee`;4j8!v^IN zug@B$0Oi>x0r`FV#jnp@*!k2g`U=^KW!y;tBP~&aLK@x*VY6GT=dl~9{;RHKmg;q$ zbVDOTt-FfbX;I{p@%lR67E3E|xY(TSJT-h+ z@aIVQ4Qq=U&$`CFl3jfy@wOmLMvE4yd#4ocRM-@u77-Pth$o%#2uG|9%87OcZ+}14 zIzt~6z}UA)!|S(+MYSVu=G*;YUkYbcy`E)sNKXQ8v*O-$aR=KPu{A16RiRF82$wx8 zJ2tG_`uuZ$_aRLV4Kr&$vBLo3Y>V2+mr@YAg*|ps8P!}`M#E zavT=pQ=}8BBsgZ=euW+X;{u=r4?MmAJ)USDHNC1T9NL#HcPJS*{Mgp|y$r&e4G3z? z57+Y@$SB0fud9ah&jwpklk|oc=Xdg)`Rik&ZCm<$>w0v4^H$B~c&rF$GOziHKJ+ux ziz;h>T-i~u!z(=f89LCa%7W@njtMrNop+~iWTh;Rf_ZFxD(R#FP^g^0&ejP%jc<#j zu=9CK8l#SoWnm5o-HZcTb?EzT!0`^Q7dG^GXEbnBbJ$?EE?~#lCs+ zpX`%V9EvMqSQcuYMGCp=IJnM+S|OpKEgC2&mX&WjsRyF-XS45yMm+J%!m*L&($N7M zPkMjN1@P@^#cPeFBYX$KqMZZmZ4C{R-<-XBr{bXf0}Xw;HK;?B^yYPE2qg|#xgX=o zUX_EHcp6lE9Rps_HKy(tTcVGnAB5`^MinKT7tFqo~Zh0>stLw7;4BO%nL7f40EUFzc3?y zW55C~GH{G!((NNRNd)L@eZmTU<@F+Wg0!l(>)Ggy8+=oX*7wh#&`{mI?cbB?3S+o| z6nne%o;IyTg`38xGF@}tb}03!z!;*nfjZK!$ivWl^YDq{#CEkb>`URT4sJJq6deWy zD^`{+C69=o%Bkm{j8B9ksg++s`kyf&z1E=>9=r?+7}9i)9zE&;?1^nUv2934qahuw zewn!Ig}D#u$d3k!KJJ(E`5!%2xUcKJyJy40X2%L9T|PKs>9^a2oB2(%3nxRjjK% zRAADxi6w-Q#>Rn|9ttOI`3l*`-9qW^mtQYQ%9B05D3dS3tA0e+{k(Kkq+iztsEls4 zz52BtNpR4+k;O}{9wcM8Yhr!MzBYwJ=Y@F}S}6Jy1%@M!fHU1>4YtS5k6F!GPD)yn zTVF$4#sArBOdwaJ_jc{$o8?jw#Cy2sIA;F*Xpbks8Lzz`z1zr-=btvK`Mw{2`e0Cb zX=Y(r#nKNS9%!~coI}AQhRtPP&Yyg^#V8yaWgZM0*)yb~qS7*c<&cgwuuzxkZ(SN82bb?ShpMuR$BdWuzvTzL!^%J0rM7~HeScFme$v^|QbC?Eep zYPXcdaSpS-BX(}F=F`5R;)(q>go;C z+&7NyMtA*^$b5s!W8AUP5}0HAw`mLqhjo3;8*M85wrYUhZ^y0;>+b#Y$76h;0&~)l zo2c5uv-B8_Tba-Dhrx~VVp1AgPzga1yzK74A=^c5n=(M#vl-P(PM`Vh8 z9aaFRX7j6ytqs{AUzdql(BnUZFp`zSa?VGL=)$1v-O8EdZ*1TES!VM% zJNs~CWZek0<8$s5&$&HgK-)`~E>UZY`+E7%*zUU;9Av$a!HA&HP(MgMbCB}y$6EPc z!QL#%t{M3nc^5DmzLJfhUL45US;r`{g{b98PMLXm2iz+OL;(0Z`2A>nntE-JC=eBV z&(XSnoAR{=ax%H!lmBQJtpBo+XU$BW1vlufF#XuxtHaTRxZPlfE1$3!e`PKE2`7rh-icred1AL`eCV|$5nD_YpzPoo}6u+|PuL3UU z{HUndNtf$_H&bm4JH}owI7*U(!f+in`*xt(7RPt;Rd4l;%si&pmyXM*f13^=BX7Q5 zl2TF{qpq=bHvq!eJ^TA-JVnMsL&foCf)P`H(SnazRHkH8u_3?im@qSIDZBwOrv-Et z4`KS%?EoSU!^S|~Yz5bLl0`}Zl(y6GiW^=|3$Tja#EXW?X(cHg3X-L?lWhf0g&Kuif%)WUWQyuuh+Z@udDYL)2 zZ=34AoUci31Q&?q?2YN=Z)apoxg5rQ-3i{n(WEa;U8u8k+0%I}EiR{(*oNn;76x41)?Azk`17YYC)TO8qsxdLV5~p>9;jV+?~WZ!`3r01YxKm4TqD7fUl{RC zqm5q?#01M(p>vx)k^^L~rF|H~zSqSLww)SO*@|zm#1|CaeLL=|%e8IY5u1RH* zjb?v;m7Z#FNeq9fHX7zM^j;6&A`;$5{cV4_S@t@i4mzP4?+bU$Yk$~m{3pAH3U%IZ z_S{mgaZoyrG5#4QGPzE$`B4OKRqarQec&l~?t5OlYsVyI~tY z@=U!8EG8O=87_i&Nj+Avdq-t-1!EJ1qtNUQxSz;(O+!j4xEeBo9V3^^ow2$(EMUXu z%)>rIGZ$PNd6WUlv_pZrb}eo{j}p9vX_E~jYeA+rb^a7>P}Ya&5in=Yt%jqTyK`?| zg6U2EW4N039y)qNXNB$IeYEqg*lAS#@~YO2@%crAlES`>-|GrnG9V^J^Mhw(m^5qO zJalOtDUUlg?LmdSZ{CF&1H|K3#Oad`45@9dJjGgHY3#mviT&PPkJsXUfn&BM22e&& zPf!!kP2M!s&EJRvJm}BD+iB(gkTn&FZ5jvH{aL_{)pgerX&fN!T!U0_3at6RyAVNa zDI2S1uH2&0roeR{*MG@dq!aq5j=|u;t=jm#9(0F9+C8M*)xY^)RI|fopSG4-jPdGH zh2s&s1lH39RZcgz(q`1D-uP+77k_*BgQ_du{nKol_y$5k!M)Q&Q z)JBn~r%*}w3#t=W14b3&Q{)`VivRPd}@$6Z~ z;&sbkYj`z`%-o7#ozoo&$RG_hMZOs;(W-1)DICuEwC(on(}gCp{nio9Q6Sb6O-PSaBO%!+YbvO7vdT03{&i2ZxZ}awymm@HchcBEr;}c;cybR*6 ze4oILaENCQhgB?jt{*e;rr{5C3#S{JW2wA@jc8Q7^EdYWxbD$ceBxCTS5SCcUtRlq zWA65KT9~cB@7xLSKb7KYoBNRM`}Vcb($YFa?}5HTD&66on~gr){CbflnV_ffgyp~Y ztXK1W`}XZfVgXCszW#jf#!8f~!-jQWOea8@RH*&pFVvw91it`2z`TZe8jVp>ouF?E zVJ(PpZmZ8niL+mEP%EwOFUiqtxLFGY2dBENgEEdP_6`5@IC{Xz338_!%5%k{yI~F@ z&KYYyB~qky+Hl;dCpQ$Lva}ql$b&88N6?HPm{hV=v9GDADS+NA3m2p&0Tcj}w)&il zoVnKL2UBAR*t4+?tF_*JNZjUrN=iyjixy4Qpb((7Ic>c?zyBQSP$~TM!f1yrznr)3 zkAh_k_&e+tp(V2fhhe0-07=H3&K>~f#%PVv$k`Uhwi``niXqVn zz`RG1^$9{QQvX&mOgsF3J=3!z-XmyhAd0iTZ`a{s<^=(%L%>q^XCevj>`U@_l5L+%k;wR z#Ocx@QE_!>IL=wIPHpM?ghg0ijgV8;@9NEMYQADr=X&w=z9XG;+zv_pT&4%gfV&5l z{)6V;l;Gq)j!G-Frs*FBHRi~J^@mT7i_ElV!pZYZCDgTwml@}`6KZIl!b3`kCc z-*5cD8i8%YzFgT|(~^|o3)Pt7kH?ubX}a-|f{`~}&w~%ag(d&*zxSqFpFK6D%JI0k zi5`RhU<%q*L&J?wWGUSVoPy2Zthdh$FMM|Ck{%`B39DfrmuKhXM8?Mta4_}mdg#K1 zcGG4q&pwqiHg#Nc1yVT4a}En@FT6h zK7W6XhIh7ez4eD1S}xQHeb&fTOC{}wpIp-jOUzWp_cdcSc(ZMC`OOwXS51mx6~<;j zHDLl9jT@J?-lcNg2(dq54!!Q_hiB9(A6Kloo(ZDf6ym|Fzw1X?DEEr_9FG1h#G%>? zcYGR6eo#Z=CZhm6JbLNU!FHZy*$$P@w9d>v-Hsph)C+Yw5OKJ6_Je{S?^XqK-Y!57 zYdyxXf0ONrO%rm5_q}Y5y{LR+p2XIOA%)Y!A8e5>?1`;gr^7YhFK$~vMV<9Tx{ad` z9|@W8$8#k7sJ3K245O0`f&9Gzwk&(GWbbpuqCzaOkydO z6%8iERnL~A)RZlLh3x6su*kh#U{9soUs2i4G_F*>*bv(%PS5Uo!%1s&Z1(kk-G;qp zSBeGdh&FzPNzf88+w4x210_cK8sOtNtA2Duc!>UurT? zbjN>jjrEFVlBEilT-4+;ZwxRwKBgDctNCVf)s@76%KhSuh7bO(60t<`^dH%}Qjp>$|UKLb)E zs}5=a6~wk&LSTGQgYBz&({o<{T08~UR*;vXkp1~f73>C7 zD-KGQjK>~6e!R!MTDg`r+Znh45t+w4I&B;K`1!Yhm**oh)yA4{OnbQ@wP+-z$neeq z&yA!dr;Y92g31`!^+nre#!josnw%L>FLlqhZY{Tgx6lRDp}QnCbKwzBH^fTS z7j?TRwrEnUbeDJf{B`un9Gr36a?(=l-LEAsU%uSQ%`FXn#Fj+C%~e8+H_%L*DffD} zd;cFL%dzH`56p^<_DBU&IYqf1J+QIAIo)3>8x8gAOwDwnd6yOhaJhFA%egiJ;A*

AgzQ}pXE02+;Q^9BlhEBU|t6#u*Qce}04{ihK3 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

#^TbX|aYzUM(ZTydQXKJE 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 h{im;5(K0#Z&uh10k=T3 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 G=fQz>dHCc@A$t= z7tc{Pna)>HQ=uR@s-N_a`?P7=&ee3kFp9Fj?PFtO(`>&d_o9y5eCUuJU{of$zSPuI z%Knn}=~QOE{Tz6CC{DbHA#gnn>h$?muh8Lb)kN0xZ*W=eoFQX=nR$6DRe6W=5CxHR zc%iQPhcsbuAY9rZW-_2jl$76*O;-Oo^vDjk_~ST zlN|U=x7`U3?%hKl=Rq+hwnn%$_Q{Jq*%sek9!J{@a4XuYkdP2D!$7qo`gS@d+N0Ag5J^;QVVdiJT+;#2<^C6^I-YH<3k>A zAW$o#M}1y-WzW?AJXK!XDEnuNvq|RleDu-Zle0dp2woL+G2qN&@A$_HdUuBQypnf) zAd110S~{gd|KU|n68GmN4ox{%ZxT@U!L@FELxG)1!g9|JeOpi6oZhk#JylQkoNlc( zZfbR3#*({t`bVC+r8A3ss8<7}%|G}{q3b8{W9pll&fA`#>SS9po~W$GX-tRlBtLLw jf{6MZRctv%;+%{$1^?;?F!UA5H$O;DrAJD1ipL diff --git a/man/figures/logo.svg b/man/figures/logo.svg deleted file mode 100644 index dad62cce..00000000 --- a/man/figures/logo.svg +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/man/hash_input.lazy_tensor.Rd b/man/hash_input.lazy_tensor.Rd deleted file mode 100644 index 2af04c6f..00000000 --- a/man/hash_input.lazy_tensor.Rd +++ /dev/null @@ -1,15 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/lazy_tensor.R -\name{hash_input.lazy_tensor} -\alias{hash_input.lazy_tensor} -\title{Hash Input for Lazy Tensor} -\usage{ -\method{hash_input}{lazy_tensor}(x) -} -\arguments{ -\item{x}{(any)\cr -Object for which to retrieve hash input.} -} -\description{ -Returns the a list containing the IDs and the data descriprot's hash. -} diff --git a/man/is_lazy_tensor.Rd b/man/is_lazy_tensor.Rd deleted file mode 100644 index 02e5e216..00000000 --- a/man/is_lazy_tensor.Rd +++ /dev/null @@ -1,15 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/lazy_tensor.R -\name{is_lazy_tensor} -\alias{is_lazy_tensor} -\title{Check for lazy tensor} -\usage{ -is_lazy_tensor(x) -} -\arguments{ -\item{x}{(any)\cr -Object to check.} -} -\description{ -Checks whether an object is a lazy tensor. -} diff --git a/man/lazy_tensor.Rd b/man/lazy_tensor.Rd deleted file mode 100644 index 556439ae..00000000 --- a/man/lazy_tensor.Rd +++ /dev/null @@ -1,18 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/lazy_tensor.R -\name{lazy_tensor} -\alias{lazy_tensor} -\title{Create a lazy tesornsor} -\usage{ -lazy_tensor(data_descriptor = NULL, ids = NULL) -} -\arguments{ -\item{data_descriptor}{(\code{\link{DataDescriptor}} or \code{NULL})\cr -The data descriptor or \code{NULL} for a lazy tensor of length 0.} - -\item{ids}{(\code{integer()})\cr -The elements of the \code{data_descriptor} to be included in the lazy tensor.} -} -\description{ -Create a lazy tensor. -} diff --git a/man/materialize.Rd b/man/materialize.Rd deleted file mode 100644 index 6a0324ae..00000000 --- a/man/materialize.Rd +++ /dev/null @@ -1,67 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/materialize.R -\name{materialize} -\alias{materialize} -\alias{materialize.list} -\title{Materialize Lazy Tensor Columns} -\usage{ -materialize(x, device = "cpu", rbind = FALSE, ...) - -\method{materialize}{list}(x, device = "cpu", rbind = FALSE, cache = "auto", ...) -} -\arguments{ -\item{x}{(any)\cr -The object to materialize. -Either a \code{\link{lazy_tensor}} or a \code{list()} / \code{data.frame()} containing \code{\link{lazy_tensor}} columns.} - -\item{device}{(\code{character(1)})\cr -The torch device.} - -\item{rbind}{(\code{logical(1)})\cr -Whether to rbind the lazy tensor columns (\code{TRUE}) or return them as a list of tensors (\code{FALSE}). -In the second case, there is no batch dimension.} - -\item{...}{(any)\cr -Additional arguments.} - -\item{cache}{(\code{character(1)} or \code{environment()} or \code{NULL})\cr -Optional cache for (intermediate) materialization results. -Per default, caching will be enabled when the same dataset or data descriptor (with different output pointer) -is used for more than one lazy tensor columns.} -} -\value{ -(\code{list()} of \code{\link{lazy_tensor}}s or a \code{\link{lazy_tensor}}) -} -\description{ -This will materialize a \code{\link[=lazy_tensor]{lazy_tensor()}} or a \code{data.frame()} / \code{list()} containing -- among other things -- -\code{\link[=lazy_tensor]{lazy_tensor()}} columns. -I.e. the data described in the underlying \code{\link{DataDescriptor}}s is loaded for the indices in the \code{\link[=lazy_tensor]{lazy_tensor()}}, -is preprocessed and then put unto the specified device. -Because not all elements in a lazy tensor must have the same shape, a list of tensors is returned by default. -If all elements have the same shape, these tensors can also be rbinded into a single tensor (parameter \code{rbind}). -} -\details{ -Materializing a lazy tensor consists of: -\enumerate{ -\item Loading the data from the internal dataset of the \code{\link{DataDescriptor}}. -\item Processing these batches in the preprocessing \code{\link{Graph}}s. -\item Returning the result of the \code{\link{PipeOp}} pointed to by the \code{\link{DataDescriptor}} (\code{pointer}). -} - -With multiple \code{\link{lazy_tensor}} columns we can benefit from caching because: -a) Output(s) from the dataset might be input to multiple graphs. -b) Different lazy tensors might be outputs from the same graph. - -For this reason it is possible to provide a cache environment. -The hash key for a) is the hash of the indices and the dataset. -The hash key for b) is the hash of the indices, dataset and preprocessing graph. -} -\examples{ -lt1 = as_lazy_tensor(torch_randn(10, 3)) -materialize(lt1, rbind = TRUE) -materialize(lt1, rbind = FALSE) -lt2 = as_lazy_tensor(torch_randn(10, 4)) -d = data.table::data.table(lt1 = lt1, lt2 = lt2) -materialize(d, rbind = TRUE) -materialize(d, rbind = FALSE) -} diff --git a/man/materialize_internal.Rd b/man/materialize_internal.Rd deleted file mode 100644 index 65390e21..00000000 --- a/man/materialize_internal.Rd +++ /dev/null @@ -1,46 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/materialize.R -\name{materialize_internal} -\alias{materialize_internal} -\title{Materialize a Lazy Tensor} -\usage{ -materialize_internal(x, device = "cpu", cache = NULL, rbind) -} -\arguments{ -\item{x}{(\code{\link[=lazy_tensor]{lazy_tensor()}})\cr -The lazy tensor to materialize.} - -\item{device}{(\code{character(1L)})\cr -The device to put the materialized tensor on (after running the preprocessing graph).} - -\item{cache}{(\code{NULL} or \code{environment()})\cr -Whether to cache the (intermediate) results of the materialization. -This can make data loading faster when multiple \code{lazy_tensor}s reference the same dataset or graph.} - -\item{rbind}{(\code{logical(1)})\cr -Whtether to rbind the resulting tensors (\code{TRUE}) or return them as a list of tensors (\code{FALSE}).} -} -\value{ -\code{\link[=lazy_tensor]{lazy_tensor()}} -} -\description{ -Convert a \code{\link{lazy_tensor}} to a \code{\link{torch_tensor}}. -} -\details{ -Materializing a lazy tensor consists of: -\enumerate{ -\item Loading the data from the internal dataset of the \code{\link{DataDescriptor}}. -\item Processing these batches in the preprocessing \code{\link{Graph}}s. -\item Returning the result of the \code{\link{PipeOp}} pointed to by the \code{\link{DataDescriptor}} (\code{pointer}). -} - -When materializing multiple \code{\link{lazy_tensor}} columns, caching can be useful because: -a) Output(s) from the dataset might be input to multiple graphs. -(in task_dataset this is shoudl rarely be the case because because we try to merge them). -b) Different lazy tensors might be outputs from the same graph. - -For this reason it is possible to provide a cache environment. -The hash key for a) is the hash of the indices and the dataset. -The hash key for b) is the hash of the indices dataset and preprocessing graph. -} -\keyword{internal} diff --git a/man/mlr3torch-package.Rd b/man/mlr3torch-package.Rd deleted file mode 100644 index 460e1562..00000000 --- a/man/mlr3torch-package.Rd +++ /dev/null @@ -1,37 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/zzz.R -\docType{package} -\name{mlr3torch-package} -\alias{mlr3torch} -\alias{mlr3torch-package} -\title{mlr3torch: Deep Learning for 'mlr3'} -\description{ -\if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} - -Deep Learning library that extends the mlr3 framework by building upon the 'torch' package. It allows to conveniently build, train, and evaluate deep learning models without having to worry about low level details. Custom architectures can be created using the graph language defined in 'mlr3pipelines'. -} -\section{Options}{ - -\itemize{ -\item \code{mlr3torch.cache}: -Whether to cache the downloaded data (\code{TRUE}) or not (\code{FALSE}, default). -This can also be set to a specific folder on the file system to be used as the cache directory. -} -} - -\author{ -\strong{Maintainer}: Sebastian Fischer \email{sebf.fischer@gmail.com} (\href{https://orcid.org/0000-0002-9609-3197}{ORCID}) - -Authors: -\itemize{ - \item Martin Binder \email{mlr.developer@mb706.com} -} - -Other contributors: -\itemize{ - \item Bernd Bischl \email{bernd_bischl@gmx.net} (\href{https://orcid.org/0000-0001-6002-6980}{ORCID}) [contributor] - \item Lukas Burk \email{github@quantenbrot.de} (\href{https://orcid.org/0000-0001-7528-3795}{ORCID}) [contributor] - \item Florian Pfisterer \email{pfistererf@googlemail.com} (\href{https://orcid.org/0000-0001-8867-762X}{ORCID}) [contributor] -} - -} diff --git a/man/mlr3torch_callbacks.Rd b/man/mlr3torch_callbacks.Rd deleted file mode 100644 index e12cd877..00000000 --- a/man/mlr3torch_callbacks.Rd +++ /dev/null @@ -1,45 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TorchCallback.R -\docType{data} -\name{mlr3torch_callbacks} -\alias{mlr3torch_callbacks} -\title{Dictionary of Torch Callbacks} -\format{ -An object of class \code{DictionaryMlr3torchCallbacks} (inherits from \code{Dictionary}, \code{R6}) of length 13. -} -\usage{ -mlr3torch_callbacks -} -\description{ -A \code{\link[mlr3misc:Dictionary]{mlr3misc::Dictionary}} of torch callbacks. -Use \code{\link[=t_clbk]{t_clbk()}} to conveniently retrieve callbacks. -Can be converted to a \code{\link{data.table}} using \code{as.data.table}. -} -\examples{ -mlr3torch_callbacks$get("checkpoint") -# is the same as -t_clbk("checkpoint") -# convert to a data.table -as.data.table(mlr3torch_callbacks) -} -\seealso{ -Other Callback: -\code{\link{TorchCallback}}, -\code{\link{as_torch_callback}()}, -\code{\link{as_torch_callbacks}()}, -\code{\link{callback_set}()}, -\code{\link{mlr_callback_set}}, -\code{\link{mlr_callback_set.checkpoint}}, -\code{\link{mlr_callback_set.progress}}, -\code{\link{mlr_context_torch}}, -\code{\link{t_clbk}()}, -\code{\link{torch_callback}()} - -Other Dictionary: -\code{\link{mlr3torch_losses}}, -\code{\link{mlr3torch_optimizers}}, -\code{\link{t_opt}()} -} -\concept{Callback} -\concept{Dictionary} -\keyword{datasets} diff --git a/man/mlr3torch_losses.Rd b/man/mlr3torch_losses.Rd deleted file mode 100644 index 8fd0d0b0..00000000 --- a/man/mlr3torch_losses.Rd +++ /dev/null @@ -1,51 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TorchLoss.R -\docType{data} -\name{mlr3torch_losses} -\alias{mlr3torch_losses} -\title{Loss Functions} -\format{ -An object of class \code{DictionaryMlr3torchLosses} (inherits from \code{Dictionary}, \code{R6}) of length 13. -} -\usage{ -mlr3torch_losses -} -\description{ -Dictionary of torch loss descriptors. -See \code{\link[=t_loss]{t_loss()}} for conveniently retrieving a loss function. -Can be converted to a \code{\link{data.table}} using \code{\link[=as.data.table]{as.data.table()}}. -} -\section{Available Loss Functions}{ - -cross_entropy, l1, mse -} - -\examples{ -mlr3torch_losses$get("mse") -# is equivalent to -t_loss("mse") -# convert to a data.table -as.data.table(mlr3torch_losses) -} -\seealso{ -Other Torch Descriptor: -\code{\link{TorchCallback}}, -\code{\link{TorchDescriptor}}, -\code{\link{TorchLoss}}, -\code{\link{TorchOptimizer}}, -\code{\link{as_torch_callbacks}()}, -\code{\link{as_torch_loss}()}, -\code{\link{as_torch_optimizer}()}, -\code{\link{mlr3torch_optimizers}}, -\code{\link{t_clbk}()}, -\code{\link{t_loss}()}, -\code{\link{t_opt}()} - -Other Dictionary: -\code{\link{mlr3torch_callbacks}}, -\code{\link{mlr3torch_optimizers}}, -\code{\link{t_opt}()} -} -\concept{Dictionary} -\concept{Torch Descriptor} -\keyword{datasets} diff --git a/man/mlr3torch_optimizers.Rd b/man/mlr3torch_optimizers.Rd deleted file mode 100644 index eff88966..00000000 --- a/man/mlr3torch_optimizers.Rd +++ /dev/null @@ -1,51 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TorchOptimizer.R -\docType{data} -\name{mlr3torch_optimizers} -\alias{mlr3torch_optimizers} -\title{Optimizers} -\format{ -An object of class \code{DictionaryMlr3torchOptimizers} (inherits from \code{Dictionary}, \code{R6}) of length 13. -} -\usage{ -mlr3torch_optimizers -} -\description{ -Dictionary of torch optimizers. -Use \code{\link{t_opt}} for conveniently retrieving optimizers. -Can be converted to a \code{\link{data.table}} using \code{as.data.table}. -} -\section{Available Optimizers}{ - -adadelta, adagrad, adam, asgd, rmsprop, rprop, sgd -} - -\examples{ -mlr3torch_optimizers$get("adam") -# is equivalent to -t_opt("adam") -# convert to a data.table -as.data.table(mlr3torch_optimizers) -} -\seealso{ -Other Torch Descriptor: -\code{\link{TorchCallback}}, -\code{\link{TorchDescriptor}}, -\code{\link{TorchLoss}}, -\code{\link{TorchOptimizer}}, -\code{\link{as_torch_callbacks}()}, -\code{\link{as_torch_loss}()}, -\code{\link{as_torch_optimizer}()}, -\code{\link{mlr3torch_losses}}, -\code{\link{t_clbk}()}, -\code{\link{t_loss}()}, -\code{\link{t_opt}()} - -Other Dictionary: -\code{\link{mlr3torch_callbacks}}, -\code{\link{mlr3torch_losses}}, -\code{\link{t_opt}()} -} -\concept{Dictionary} -\concept{Torch Descriptor} -\keyword{datasets} diff --git a/man/mlr_backends_lazy.Rd b/man/mlr_backends_lazy.Rd deleted file mode 100644 index 504a4c37..00000000 --- a/man/mlr_backends_lazy.Rd +++ /dev/null @@ -1,271 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/DataBackendLazy.R -\name{mlr_backends_lazy} -\alias{mlr_backends_lazy} -\alias{DataBackendLazy} -\title{Lazy Data Backend} -\description{ -This lazy data backend wraps a constructor that lazily creates another backend, e.g. by downloading -(and caching) some data from the internet. -This backend should be used, when some metadata of the backend is known in advance and should be accessible -before downloading the actual data. -When the backend is first constructed, it is verified that the provided metadata was correct, otherwise -an informative error message is thrown. -After the construction of the lazily constructed backend, calls like \verb{$data()}, \verb{$missings()}, \verb{$distinct()}, -or \verb{$hash()} are redirected to it. - -Information that is available before the backend is constructed is: -\itemize{ -\item \code{nrow} - The number of rows (set as the length of the \code{rownames}). -\item \code{ncol} - The number of columns (provided via the \code{id} column of \code{col_info}). -\item \code{colnames} - The column names. -\item \code{rownames} - The row names. -\item \code{col_info} - The column information, which can be obtained via \code{\link[mlr3:col_info]{mlr3::col_info()}}. -} - -Beware that accessing the backend's hash also contructs the backend. - -Note that while in most cases the data contains \code{\link{lazy_tensor}} columns, this is not necessary and the naming -of this class has nothing to do with the \code{\link{lazy_tensor}} data type. - -\strong{Important} - -When the constructor generates \code{factor()} variables it is important that the ordering of the levels in data -corresponds to the ordering of the levels in the \code{col_info} argument. -} -\examples{ -# We first define a backend constructor -constructor = function(backend) { - cat("Data is constructed!\n") - DataBackendDataTable$new( - data.table(x = rnorm(10), y = rnorm(10), row_id = 1:10), - primary_key = "row_id" - ) -} - -# to wrap this backend constructor in a lazy backend, we need to provide the correct metadata for it -column_info = data.table( - id = c("x", "y", "row_id"), - type = c("numeric", "numeric", "integer"), - levels = list(NULL, NULL, NULL) -) -backend_lazy = DataBackendLazy$new( - constructor = constructor, - rownames = 1:10, - col_info = column_info, - data_formats = "data.table", - primary_key = "row_id" -) - -# Note that the constructor is not called for the calls below -# as they can be read from the metadata -backend_lazy$nrow -backend_lazy$rownames -backend_lazy$ncol -backend_lazy$colnames -col_info(backend_lazy) - -# Only now the backend is constructed -backend_lazy$data(1, "x") -# Is the same as: -backend_lazy$backend$data(1, "x") -} -\section{Super class}{ -\code{\link[mlr3:DataBackend]{mlr3::DataBackend}} -> \code{DataBackendLazy} -} -\section{Active bindings}{ -\if{html}{\out{

}} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-DataBackendLazy-new}{\code{DataBackendLazy$new()}} -\item \href{#method-DataBackendLazy-data}{\code{DataBackendLazy$data()}} -\item \href{#method-DataBackendLazy-head}{\code{DataBackendLazy$head()}} -\item \href{#method-DataBackendLazy-distinct}{\code{DataBackendLazy$distinct()}} -\item \href{#method-DataBackendLazy-missings}{\code{DataBackendLazy$missings()}} -\item \href{#method-DataBackendLazy-print}{\code{DataBackendLazy$print()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-DataBackendLazy-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{DataBackendLazy$new(constructor, rownames, col_info, primary_key, data_formats)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{constructor}}{(\code{function})\cr -A function with argument \code{backend} (the lazy backend), whose return value must be the actual backend. -This function is called the first time the field \verb{$backend} is accessed.} - -\item{\code{rownames}}{(\code{integer()})\cr -The row names. Must be a permutation of the rownames of the lazily constructed backend.} - -\item{\code{col_info}}{(\code{\link[data.table:data.table]{data.table::data.table()}})\cr -A data.table with columns \code{id}, \code{type} and \code{levels} containing the column id, type and levels. -Note that the levels must be provided in the correct order.} - -\item{\code{primary_key}}{(\code{character(1)})\cr -Name of the primary key column.} - -\item{\code{data_formats}}{(\code{character()})\cr -Set of supported data formats. E.g. \code{"data.table"}. -These must be a subset of the data formats of the lazily constructed backend.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-DataBackendLazy-data}{}}} -\subsection{Method \code{data()}}{ -Returns a slice of the data in the specified format. -The rows must be addressed as vector of primary key values, columns must be referred to via column names. -Queries for rows with no matching row id and queries for columns with no matching column name are silently ignored. -Rows are guaranteed to be returned in the same order as \code{rows}, columns may be returned in an arbitrary order. -Duplicated row ids result in duplicated rows, duplicated column names lead to an exception. - -Accessing the data triggers the construction of the backend. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{DataBackendLazy$data(rows, cols, data_format = "data.table")}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{rows}}{(\code{integer()})\cr -Row indices.} - -\item{\code{cols}}{(\code{character()})\cr -Column names.} - -\item{\code{data_format}}{(\code{character(1)})\cr -Desired data format, e.g. \code{"data.table"} or \code{"Matrix"}.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-DataBackendLazy-head}{}}} -\subsection{Method \code{head()}}{ -Retrieve the first \code{n} rows. -This triggers the construction of the backend. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{DataBackendLazy$head(n = 6L)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{n}}{(\code{integer(1)})\cr -Number of rows.} -} -\if{html}{\out{
}} -} -\subsection{Returns}{ -\code{\link[data.table:data.table]{data.table::data.table()}} of the first \code{n} rows. -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-DataBackendLazy-distinct}{}}} -\subsection{Method \code{distinct()}}{ -Returns a named list of vectors of distinct values for each column -specified. If \code{na_rm} is \code{TRUE}, missing values are removed from the -returned vectors of distinct values. Non-existing rows and columns are -silently ignored. - -This triggers the construction of the backend. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{DataBackendLazy$distinct(rows, cols, na_rm = TRUE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{rows}}{(\code{integer()})\cr -Row indices.} - -\item{\code{cols}}{(\code{character()})\cr -Column names.} - -\item{\code{na_rm}}{(\code{logical(1)})\cr -Whether to remove NAs or not.} -} -\if{html}{\out{
}} -} -\subsection{Returns}{ -Named \code{list()} of distinct values. -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-DataBackendLazy-missings}{}}} -\subsection{Method \code{missings()}}{ -Returns the number of missing values per column in the specified slice -of data. Non-existing rows and columns are silently ignored. - -This triggers the construction of the backend. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{DataBackendLazy$missings(rows, cols)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{rows}}{(\code{integer()})\cr -Row indices.} - -\item{\code{cols}}{(\code{character()})\cr -Column names.} -} -\if{html}{\out{
}} -} -\subsection{Returns}{ -Total of missing values per column (named \code{numeric()}). -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-DataBackendLazy-print}{}}} -\subsection{Method \code{print()}}{ -Printer. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{DataBackendLazy$print()}\if{html}{\out{
}} -} - -} -} diff --git a/man/mlr_context_torch.Rd b/man/mlr_context_torch.Rd deleted file mode 100644 index 01f43ee7..00000000 --- a/man/mlr_context_torch.Rd +++ /dev/null @@ -1,167 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/ContextTorch.R -\name{mlr_context_torch} -\alias{mlr_context_torch} -\alias{ContextTorch} -\title{Context for Torch Learner} -\description{ -Context for training a torch learner. -This is the - mostly read-only - information callbacks have access to through the argument \code{ctx}. -For more information on callbacks, see \code{\link{CallbackSet}}. -} -\seealso{ -Other Callback: -\code{\link{TorchCallback}}, -\code{\link{as_torch_callback}()}, -\code{\link{as_torch_callbacks}()}, -\code{\link{callback_set}()}, -\code{\link{mlr3torch_callbacks}}, -\code{\link{mlr_callback_set}}, -\code{\link{mlr_callback_set.checkpoint}}, -\code{\link{mlr_callback_set.progress}}, -\code{\link{t_clbk}()}, -\code{\link{torch_callback}()} -} -\concept{Callback} -\section{Public fields}{ -\if{html}{\out{
}} -\describe{ -\item{\code{learner}}{(\code{\link{Learner}})\cr -The torch learner.} - -\item{\code{task_train}}{(\code{\link{Task}})\cr -The training task.} - -\item{\code{task_valid}}{(\code{\link{Task}} or \code{NULL})\cr -The validation task.} - -\item{\code{loader_train}}{(\code{\link[torch:dataloader]{torch::dataloader}})\cr -The data loader for training.} - -\item{\code{loader_valid}}{(\code{\link[torch:dataloader]{torch::dataloader}})\cr -The data loader for validation.} - -\item{\code{measures_train}}{(\code{list()} of \code{\link{Measure}}s or \code{NULL})\cr -Measures used for training.} - -\item{\code{measures_valid}}{(\code{list()} of \code{\link{Measure}}s or \code{NULL})\cr -Measures used for validation.} - -\item{\code{network}}{(\code{\link[torch:nn_module]{torch::nn_module}})\cr -The torch network.} - -\item{\code{optimizer}}{(\code{\link[torch:optimizer]{torch::optimizer}})\cr -The optimizer.} - -\item{\code{loss_fn}}{(\code{\link[torch:nn_module]{torch::nn_module}})\cr -The loss function.} - -\item{\code{total_epochs}}{(\code{integer(1)})\cr -The total number of epochs the learner is trained for.} - -\item{\code{last_scores_train}}{(named \code{list()})\cr -The scores from the last training batch. Names are the ids of the training measures.} - -\item{\code{last_scores_valid}}{(\code{list()})\cr -The scores from the last validation batch. Names are the ids of the validation measures.} - -\item{\code{epoch}}{(\code{integer(1)})\cr -The current epoch.} - -\item{\code{batch}}{(\code{integer(1)})\cr -The current iteration of the batch.} - -\item{\code{prediction_encoder}}{(\verb{function()})\cr -The learner's prediction encoder.} -} -\if{html}{\out{
}} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-ContextTorch-new}{\code{ContextTorch$new()}} -\item \href{#method-ContextTorch-clone}{\code{ContextTorch$clone()}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-ContextTorch-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{ContextTorch$new( - learner, - task_train, - task_valid = NULL, - loader_train, - loader_valid = NULL, - measures_train = NULL, - measures_valid = NULL, - network, - optimizer, - loss_fn, - total_epochs, - prediction_encoder -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{learner}}{(\code{\link{Learner}})\cr -The torch learner.} - -\item{\code{task_train}}{(\code{\link{Task}})\cr -The training task.} - -\item{\code{task_valid}}{(\code{\link{Task}} or \code{NULL})\cr -The validation task.} - -\item{\code{loader_train}}{(\code{\link[torch:dataloader]{torch::dataloader}})\cr -The data loader for training.} - -\item{\code{loader_valid}}{(\code{\link[torch:dataloader]{torch::dataloader}} or \code{NULL})\cr -The data loader for validation.} - -\item{\code{measures_train}}{(\code{list()} of \code{\link{Measure}}s or \code{NULL})\cr -Measures used for training. Default is \code{NULL}.} - -\item{\code{measures_valid}}{(\code{list()} of \code{\link{Measure}}s or \code{NULL})\cr -Measures used for validation.} - -\item{\code{network}}{(\code{\link[torch:nn_module]{torch::nn_module}})\cr -The torch network.} - -\item{\code{optimizer}}{(\code{\link[torch:optimizer]{torch::optimizer}})\cr -The optimizer.} - -\item{\code{loss_fn}}{(\code{\link[torch:nn_module]{torch::nn_module}})\cr -The loss function.} - -\item{\code{total_epochs}}{(\code{integer(1)})\cr -The total number of epochs the learner is trained for.} - -\item{\code{prediction_encoder}}{(\verb{function()})\cr -The learner's prediction encoder.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-ContextTorch-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{ContextTorch$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_module.Rd b/man/mlr_pipeops_module.Rd deleted file mode 100644 index 113d5dcd..00000000 --- a/man/mlr_pipeops_module.Rd +++ /dev/null @@ -1,185 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpModule.R -\name{mlr_pipeops_module} -\alias{mlr_pipeops_module} -\alias{PipeOpModule} -\title{Class for Torch Module Wrappers} -\description{ -\code{PipeOpModule} wraps an \code{\link{nn_module}} or \code{function} that is being called during the \code{train} phase of this -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}}. By doing so, this allows to assemble \code{PipeOpModule}s in a computational -\code{\link[mlr3pipelines:Graph]{mlr3pipelines::Graph}} that represents either a neural network or a preprocessing graph of a \code{\link{lazy_tensor}}. -In most cases it is easier to create such a network by creating a graph that generates this graph. - -In most cases it is easier to create such a network by creating a structurally related graph consisting -of nodes of class \code{\link{PipeOpTorchIngress}} and \code{\link{PipeOpTorch}}. This graph will then generate the graph consisting -of \code{PipeOpModule}s as part of the \code{\link{ModelDescriptor}}. -} -\section{Input and Output Channels}{ - -The number and names of the input and output channels can be set during construction. They input and output -\code{"torch_tensor"} during training, and \code{NULL} during prediction as the prediction phase currently serves no -meaningful purpose. -} - -\section{State}{ - -The state is the value calculated by the public method \code{shapes_out()}. -} - -\section{Parameters}{ - -No parameters. -} - -\section{Internals}{ - -During training, the wrapped \code{\link{nn_module}} / \code{function} is called with the provided inputs in the order in which -the channels are defined. Arguments are \strong{not} matched by name. -} - -\examples{ -## creating an PipeOpModule manually - -# one input and output channel -po_module = po("module", - id = "linear", - module = torch::nn_linear(10, 20), - inname = "input", - outname = "output" -) -x = torch::torch_randn(16, 10) -# This calls the forward function of the wrapped module. -y = po_module$train(list(input = x)) -str(y) - -# multiple input and output channels -nn_custom = torch::nn_module("nn_custom", - initialize = function(in_features, out_features) { - self$lin1 = torch::nn_linear(in_features, out_features) - self$lin2 = torch::nn_linear(in_features, out_features) - }, - forward = function(x, z) { - list(out1 = self$lin1(x), out2 = torch::nnf_relu(self$lin2(z))) - } -) - -module = nn_custom(3, 2) -po_module = po("module", - id = "custom", - module = module, - inname = c("x", "z"), - outname = c("out1", "out2") -) -x = torch::torch_randn(1, 3) -z = torch::torch_randn(1, 3) -out = po_module$train(list(x = x, z = z)) -str(out) - -# How such a PipeOpModule is usually generated -graph = po("torch_ingress_num") \%>>\% po("nn_linear", out_features = 10L) -result = graph$train(tsk("iris")) -# The PipeOpTorchLinear generates a PipeOpModule and adds it to a new (module) graph -result[[1]]$graph -linear_module = result[[1L]]$graph$pipeops$nn_linear -linear_module -formalArgs(linear_module$module) -linear_module$input$name - -# Constructing a PipeOpModule using a simple function -po_add1 = po("module", - id = "add_one", - module = function(x) x + 1 -) -input = list(torch_tensor(1)) -po_add1$train(input)$output -} -\seealso{ -Other Graph Network: -\code{\link{ModelDescriptor}()}, -\code{\link{TorchIngressToken}()}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_pipeops_torch}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{model_descriptor_to_learner}()}, -\code{\link{model_descriptor_to_module}()}, -\code{\link{model_descriptor_union}()}, -\code{\link{nn_graph}()} - -Other PipeOp: -\code{\link{mlr_pipeops_torch_callbacks}}, -\code{\link{mlr_pipeops_torch_optimizer}} -} -\concept{Graph Network} -\concept{PipeOp} -\section{Super class}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{PipeOpModule} -} -\section{Public fields}{ -\if{html}{\out{
}} -\describe{ -\item{\code{module}}{(\code{\link{nn_module}})\cr -The torch module that is called during the training phase.} -} -\if{html}{\out{
}} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpModule-new}{\code{PipeOpModule$new()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpModule-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpModule$new( - id = "module", - module = nn_identity(), - inname = "input", - outname = "output", - param_vals = list(), - packages = character(0) -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -The id for of the new object.} - -\item{\code{module}}{(\code{\link{nn_module}} or \verb{function()})\cr -The torch module or function that is being wrapped.} - -\item{\code{inname}}{(\code{character()})\cr -The names of the input channels.} - -\item{\code{outname}}{(\code{character()})\cr -The names of the output channels. If this parameter has length 1, the parameter \link[torch:nn_module]{module} must -return a \link[torch:torch_tensor]{tensor}. Otherwise it must return a \code{list()} of tensors of corresponding length.} - -\item{\code{param_vals}}{(named \code{list()})\cr -Parameter values to be set after construction.} - -\item{\code{packages}}{(\code{character()})\cr -The R packages this object depends on.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_avg_pool1d.Rd b/man/mlr_pipeops_nn_avg_pool1d.Rd deleted file mode 100644 index 1c244e23..00000000 --- a/man/mlr_pipeops_nn_avg_pool1d.Rd +++ /dev/null @@ -1,177 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchAvgPool.R -\name{mlr_pipeops_nn_avg_pool1d} -\alias{mlr_pipeops_nn_avg_pool1d} -\alias{PipeOpTorchAvgPool1D} -\title{1D Average Pooling} -\description{ -Applies a 1D adaptive average pooling over an input signal composed of -several input planes. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{kernel_size} :: (\code{integer()})\cr -The size of the window. Can be a single number or a vector. -\item \code{stride} :: \code{integer()}\cr -The stride of the window. Can be a single number or a vector. Default: \code{kernel_size}. -\item \code{padding} :: \code{integer()}\cr -Implicit zero paddings on both sides of the input. Can be a single number or a vector. Default: 0. -\item \code{ceil_mode} :: \code{integer()}\cr -When \code{TRUE}, will use ceil instead of floor to compute the output shape. Default: \code{FALSE}. -\item \code{count_include_pad} :: \code{logical(1)}\cr -When \code{TRUE}, will include the zero-padding in the averaging calculation. Default: \code{TRUE}. -\item \code{divisor_override} :: \code{logical(1)}\cr -If specified, it will be used as divisor, otherwise size of the pooling region will be used. Default: NULL. -Only available for dimension greater than 1. -} -} - -\section{Internals}{ - -Calls \code{\link[=nn_avg_pool1d]{nn_avg_pool1d()}} during training. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_avg_pool1d") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{mlr3torch::PipeOpTorchAvgPool} -> \code{PipeOpTorchAvgPool1D} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchAvgPool1D-new}{\code{PipeOpTorchAvgPool1D$new()}} -\item \href{#method-PipeOpTorchAvgPool1D-clone}{\code{PipeOpTorchAvgPool1D$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchAvgPool1D-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchAvgPool1D$new(id = "nn_avg_pool1d", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchAvgPool1D-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchAvgPool1D$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_avg_pool2d.Rd b/man/mlr_pipeops_nn_avg_pool2d.Rd deleted file mode 100644 index 3819c435..00000000 --- a/man/mlr_pipeops_nn_avg_pool2d.Rd +++ /dev/null @@ -1,177 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchAvgPool.R -\name{mlr_pipeops_nn_avg_pool2d} -\alias{mlr_pipeops_nn_avg_pool2d} -\alias{PipeOpTorchAvgPool2D} -\title{2D Average Pooling} -\description{ -Applies a 2D adaptive average pooling over an input signal composed of -several input planes. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Internals}{ - -Calls \code{\link[=nn_avg_pool2d]{nn_avg_pool2d()}} during training. -} - -\section{Parameters}{ - -\itemize{ -\item \code{kernel_size} :: (\code{integer()})\cr -The size of the window. Can be a single number or a vector. -\item \code{stride} :: \code{integer()}\cr -The stride of the window. Can be a single number or a vector. Default: \code{kernel_size}. -\item \code{padding} :: \code{integer()}\cr -Implicit zero paddings on both sides of the input. Can be a single number or a vector. Default: 0. -\item \code{ceil_mode} :: \code{integer()}\cr -When \code{TRUE}, will use ceil instead of floor to compute the output shape. Default: \code{FALSE}. -\item \code{count_include_pad} :: \code{logical(1)}\cr -When \code{TRUE}, will include the zero-padding in the averaging calculation. Default: \code{TRUE}. -\item \code{divisor_override} :: \code{logical(1)}\cr -If specified, it will be used as divisor, otherwise size of the pooling region will be used. Default: NULL. -Only available for dimension greater than 1. -} -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_avg_pool2d") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{mlr3torch::PipeOpTorchAvgPool} -> \code{PipeOpTorchAvgPool2D} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchAvgPool2D-new}{\code{PipeOpTorchAvgPool2D$new()}} -\item \href{#method-PipeOpTorchAvgPool2D-clone}{\code{PipeOpTorchAvgPool2D$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchAvgPool2D-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchAvgPool2D$new(id = "nn_avg_pool2d", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchAvgPool2D-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchAvgPool2D$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_avg_pool3d.Rd b/man/mlr_pipeops_nn_avg_pool3d.Rd deleted file mode 100644 index e917a326..00000000 --- a/man/mlr_pipeops_nn_avg_pool3d.Rd +++ /dev/null @@ -1,177 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchAvgPool.R -\name{mlr_pipeops_nn_avg_pool3d} -\alias{mlr_pipeops_nn_avg_pool3d} -\alias{PipeOpTorchAvgPool3D} -\title{3D Average Pooling} -\description{ -Applies a 3D adaptive average pooling over an input signal composed of -several input planes. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Internals}{ - -Calls \code{\link[=nn_avg_pool3d]{nn_avg_pool3d()}} during training. -} - -\section{Parameters}{ - -\itemize{ -\item \code{kernel_size} :: (\code{integer()})\cr -The size of the window. Can be a single number or a vector. -\item \code{stride} :: \code{integer()}\cr -The stride of the window. Can be a single number or a vector. Default: \code{kernel_size}. -\item \code{padding} :: \code{integer()}\cr -Implicit zero paddings on both sides of the input. Can be a single number or a vector. Default: 0. -\item \code{ceil_mode} :: \code{integer()}\cr -When \code{TRUE}, will use ceil instead of floor to compute the output shape. Default: \code{FALSE}. -\item \code{count_include_pad} :: \code{logical(1)}\cr -When \code{TRUE}, will include the zero-padding in the averaging calculation. Default: \code{TRUE}. -\item \code{divisor_override} :: \code{logical(1)}\cr -If specified, it will be used as divisor, otherwise size of the pooling region will be used. Default: NULL. -Only available for dimension greater than 1. -} -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_avg_pool3d") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{mlr3torch::PipeOpTorchAvgPool} -> \code{PipeOpTorchAvgPool3D} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchAvgPool3D-new}{\code{PipeOpTorchAvgPool3D$new()}} -\item \href{#method-PipeOpTorchAvgPool3D-clone}{\code{PipeOpTorchAvgPool3D$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchAvgPool3D-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchAvgPool3D$new(id = "nn_avg_pool3d", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchAvgPool3D-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchAvgPool3D$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_batch_norm1d.Rd b/man/mlr_pipeops_nn_batch_norm1d.Rd deleted file mode 100644 index f4893c5b..00000000 --- a/man/mlr_pipeops_nn_batch_norm1d.Rd +++ /dev/null @@ -1,175 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchBatchNorm.R -\name{mlr_pipeops_nn_batch_norm1d} -\alias{mlr_pipeops_nn_batch_norm1d} -\alias{PipeOpTorchBatchNorm1D} -\title{1D Batch Normalization} -\description{ -Applies Batch Normalization for each channel across a batch of data. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{eps} :: \code{numeric(1)}\cr -A value added to the denominator for numerical stability. Default: \code{1e-5}. -\item \code{momentum} :: \code{numeric(1)}\cr -The value used for the running_mean and running_var computation. Can be set to \code{NULL} for cumulative moving average -(i.e. simple average). Default: 0.1 -\item \code{affine} :: \code{logical(1)}\cr -a boolean value that when set to \code{TRUE}, this module has learnable affine parameters. Default: \code{TRUE} -\item \code{track_running_stats} :: \code{logical(1)}\cr -a boolean value that when set to \code{TRUE}, this module tracks the running mean and variance, and when set to \code{FALSE}, -this module does not track such statistics and always uses batch statistics in both training and eval modes. -Default: \code{TRUE} -} -} - -\section{Internals}{ - -Calls \code{\link[torch:nn_batch_norm1d]{torch::nn_batch_norm1d()}}. -The parameter \code{num_features} is inferred as the second dimension of the input shape. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_batch_norm1d") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{mlr3torch::PipeOpTorchBatchNorm} -> \code{PipeOpTorchBatchNorm1D} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchBatchNorm1D-new}{\code{PipeOpTorchBatchNorm1D$new()}} -\item \href{#method-PipeOpTorchBatchNorm1D-clone}{\code{PipeOpTorchBatchNorm1D$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchBatchNorm1D-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchBatchNorm1D$new(id = "nn_batch_norm1d", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchBatchNorm1D-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchBatchNorm1D$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_batch_norm2d.Rd b/man/mlr_pipeops_nn_batch_norm2d.Rd deleted file mode 100644 index 942aedc6..00000000 --- a/man/mlr_pipeops_nn_batch_norm2d.Rd +++ /dev/null @@ -1,175 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchBatchNorm.R -\name{mlr_pipeops_nn_batch_norm2d} -\alias{mlr_pipeops_nn_batch_norm2d} -\alias{PipeOpTorchBatchNorm2D} -\title{2D Batch Normalization} -\description{ -Applies Batch Normalization for each channel across a batch of data. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Internals}{ - -Calls \code{\link[torch:nn_batch_norm2d]{torch::nn_batch_norm2d()}}. -The parameter \code{num_features} is inferred as the second dimension of the input shape. -} - -\section{Parameters}{ - -\itemize{ -\item \code{eps} :: \code{numeric(1)}\cr -A value added to the denominator for numerical stability. Default: \code{1e-5}. -\item \code{momentum} :: \code{numeric(1)}\cr -The value used for the running_mean and running_var computation. Can be set to \code{NULL} for cumulative moving average -(i.e. simple average). Default: 0.1 -\item \code{affine} :: \code{logical(1)}\cr -a boolean value that when set to \code{TRUE}, this module has learnable affine parameters. Default: \code{TRUE} -\item \code{track_running_stats} :: \code{logical(1)}\cr -a boolean value that when set to \code{TRUE}, this module tracks the running mean and variance, and when set to \code{FALSE}, -this module does not track such statistics and always uses batch statistics in both training and eval modes. -Default: \code{TRUE} -} -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_batch_norm2d") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{mlr3torch::PipeOpTorchBatchNorm} -> \code{PipeOpTorchBatchNorm2D} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchBatchNorm2D-new}{\code{PipeOpTorchBatchNorm2D$new()}} -\item \href{#method-PipeOpTorchBatchNorm2D-clone}{\code{PipeOpTorchBatchNorm2D$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchBatchNorm2D-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchBatchNorm2D$new(id = "nn_batch_norm2d", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchBatchNorm2D-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchBatchNorm2D$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_batch_norm3d.Rd b/man/mlr_pipeops_nn_batch_norm3d.Rd deleted file mode 100644 index 5f858053..00000000 --- a/man/mlr_pipeops_nn_batch_norm3d.Rd +++ /dev/null @@ -1,175 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchBatchNorm.R -\name{mlr_pipeops_nn_batch_norm3d} -\alias{mlr_pipeops_nn_batch_norm3d} -\alias{PipeOpTorchBatchNorm3D} -\title{3D Batch Normalization} -\description{ -Applies Batch Normalization for each channel across a batch of data. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Internals}{ - -Calls \code{\link[torch:nn_batch_norm3d]{torch::nn_batch_norm3d()}}. -The parameter \code{num_features} is inferred as the second dimension of the input shape. -} - -\section{Parameters}{ - -\itemize{ -\item \code{eps} :: \code{numeric(1)}\cr -A value added to the denominator for numerical stability. Default: \code{1e-5}. -\item \code{momentum} :: \code{numeric(1)}\cr -The value used for the running_mean and running_var computation. Can be set to \code{NULL} for cumulative moving average -(i.e. simple average). Default: 0.1 -\item \code{affine} :: \code{logical(1)}\cr -a boolean value that when set to \code{TRUE}, this module has learnable affine parameters. Default: \code{TRUE} -\item \code{track_running_stats} :: \code{logical(1)}\cr -a boolean value that when set to \code{TRUE}, this module tracks the running mean and variance, and when set to \code{FALSE}, -this module does not track such statistics and always uses batch statistics in both training and eval modes. -Default: \code{TRUE} -} -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_batch_norm3d") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{mlr3torch::PipeOpTorchBatchNorm} -> \code{PipeOpTorchBatchNorm3D} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchBatchNorm3D-new}{\code{PipeOpTorchBatchNorm3D$new()}} -\item \href{#method-PipeOpTorchBatchNorm3D-clone}{\code{PipeOpTorchBatchNorm3D$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchBatchNorm3D-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchBatchNorm3D$new(id = "nn_batch_norm3d", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchBatchNorm3D-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchBatchNorm3D$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_celu.Rd b/man/mlr_pipeops_nn_celu.Rd deleted file mode 100644 index 5abb33b3..00000000 --- a/man/mlr_pipeops_nn_celu.Rd +++ /dev/null @@ -1,166 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_celu} -\alias{mlr_pipeops_nn_celu} -\alias{PipeOpTorchCELU} -\title{CELU Activation Function} -\description{ -Applies element-wise, \eqn{CELU(x) = max(0,x) + min(0, \alpha * (exp(x \alpha) - 1))}. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{alpha} :: \code{numeric(1)}\cr -The alpha value for the ELU formulation. Default: 1.0 -\item \code{inplace} :: \code{logical(1)}\cr -Whether to do the operation in-place. Default: \code{FALSE}. -} -} - -\section{Internals}{ - Calls \code{\link[torch:nn_celu]{torch::nn_celu()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_celu") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchCELU} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchCELU-new}{\code{PipeOpTorchCELU$new()}} -\item \href{#method-PipeOpTorchCELU-clone}{\code{PipeOpTorchCELU$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchCELU-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchCELU$new(id = "nn_celu", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchCELU-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchCELU$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_conv1d.Rd b/man/mlr_pipeops_nn_conv1d.Rd deleted file mode 100644 index a45c85da..00000000 --- a/man/mlr_pipeops_nn_conv1d.Rd +++ /dev/null @@ -1,181 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchConv.R -\name{mlr_pipeops_nn_conv1d} -\alias{mlr_pipeops_nn_conv1d} -\alias{PipeOpTorchConv1D} -\title{1D Convolution} -\description{ -Applies a 1D convolution over an input signal composed of several input -planes. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{out_channels} :: \code{integer(1)}\cr -Number of channels produced by the convolution. -\item \code{kernel_size} :: \code{integer()}\cr -Size of the convolving kernel. -\item \code{stride} :: \code{integer()}\cr -Stride of the convolution. The default is 1. -\item \code{padding} :: \code{integer()}\cr -‘dilation * (kernel_size - 1) - padding’ zero-padding will be added to both sides of the input. Default: 0. -\item \code{groups} :: \code{integer()}\cr -Number of blocked connections from input channels to output channels. Default: 1 -\item \code{bias} :: \code{logical(1)}\cr -If ‘TRUE’, adds a learnable bias to the output. Default: ‘TRUE’. -\item \code{dilation} :: \code{integer()}\cr -Spacing between kernel elements. Default: 1. -\item \code{padding_mode} :: \code{character(1)}\cr -The padding mode. One of \code{"zeros"}, \code{"reflect"}, \code{"replicate"}, or \code{"circular"}. Default is \code{"zeros"}. -} -} - -\section{Internals}{ - -Calls \code{\link[torch:nn_conv1d]{torch::nn_conv1d()}} when trained. -The paramter \code{in_channels} is inferred from the second dimension of the input tensor. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_conv1d", kernel_size = 10, out_channels = 1) -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{mlr3torch::PipeOpTorchConv} -> \code{PipeOpTorchConv1D} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchConv1D-new}{\code{PipeOpTorchConv1D$new()}} -\item \href{#method-PipeOpTorchConv1D-clone}{\code{PipeOpTorchConv1D$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchConv1D-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchConv1D$new(id = "nn_conv1d", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchConv1D-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchConv1D$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_conv2d.Rd b/man/mlr_pipeops_nn_conv2d.Rd deleted file mode 100644 index bdf59cc1..00000000 --- a/man/mlr_pipeops_nn_conv2d.Rd +++ /dev/null @@ -1,181 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchConv.R -\name{mlr_pipeops_nn_conv2d} -\alias{mlr_pipeops_nn_conv2d} -\alias{PipeOpTorchConv2D} -\title{2D Convolution} -\description{ -Applies a 2D convolution over an input image composed of several input -planes. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Internals}{ - -Calls \code{\link[torch:nn_conv2d]{torch::nn_conv2d()}} when trained. -The paramter \code{in_channels} is inferred from the second dimension of the input tensor. -} - -\section{Parameters}{ - -\itemize{ -\item \code{out_channels} :: \code{integer(1)}\cr -Number of channels produced by the convolution. -\item \code{kernel_size} :: \code{integer()}\cr -Size of the convolving kernel. -\item \code{stride} :: \code{integer()}\cr -Stride of the convolution. The default is 1. -\item \code{padding} :: \code{integer()}\cr -‘dilation * (kernel_size - 1) - padding’ zero-padding will be added to both sides of the input. Default: 0. -\item \code{groups} :: \code{integer()}\cr -Number of blocked connections from input channels to output channels. Default: 1 -\item \code{bias} :: \code{logical(1)}\cr -If ‘TRUE’, adds a learnable bias to the output. Default: ‘TRUE’. -\item \code{dilation} :: \code{integer()}\cr -Spacing between kernel elements. Default: 1. -\item \code{padding_mode} :: \code{character(1)}\cr -The padding mode. One of \code{"zeros"}, \code{"reflect"}, \code{"replicate"}, or \code{"circular"}. Default is \code{"zeros"}. -} -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_conv2d", kernel_size = 10, out_channels = 1) -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{mlr3torch::PipeOpTorchConv} -> \code{PipeOpTorchConv2D} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchConv2D-new}{\code{PipeOpTorchConv2D$new()}} -\item \href{#method-PipeOpTorchConv2D-clone}{\code{PipeOpTorchConv2D$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchConv2D-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchConv2D$new(id = "nn_conv2d", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchConv2D-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchConv2D$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_conv3d.Rd b/man/mlr_pipeops_nn_conv3d.Rd deleted file mode 100644 index 3a48ff60..00000000 --- a/man/mlr_pipeops_nn_conv3d.Rd +++ /dev/null @@ -1,181 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchConv.R -\name{mlr_pipeops_nn_conv3d} -\alias{mlr_pipeops_nn_conv3d} -\alias{PipeOpTorchConv3D} -\title{3D Convolution} -\description{ -Applies a 3D convolution over an input image composed of several input -planes. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Internals}{ - -Calls \code{\link[torch:nn_conv3d]{torch::nn_conv3d()}} when trained. -The paramter \code{in_channels} is inferred from the second dimension of the input tensor. -} - -\section{Parameters}{ - -\itemize{ -\item \code{out_channels} :: \code{integer(1)}\cr -Number of channels produced by the convolution. -\item \code{kernel_size} :: \code{integer()}\cr -Size of the convolving kernel. -\item \code{stride} :: \code{integer()}\cr -Stride of the convolution. The default is 1. -\item \code{padding} :: \code{integer()}\cr -‘dilation * (kernel_size - 1) - padding’ zero-padding will be added to both sides of the input. Default: 0. -\item \code{groups} :: \code{integer()}\cr -Number of blocked connections from input channels to output channels. Default: 1 -\item \code{bias} :: \code{logical(1)}\cr -If ‘TRUE’, adds a learnable bias to the output. Default: ‘TRUE’. -\item \code{dilation} :: \code{integer()}\cr -Spacing between kernel elements. Default: 1. -\item \code{padding_mode} :: \code{character(1)}\cr -The padding mode. One of \code{"zeros"}, \code{"reflect"}, \code{"replicate"}, or \code{"circular"}. Default is \code{"zeros"}. -} -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_conv3d", kernel_size = 10, out_channels = 1) -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{mlr3torch::PipeOpTorchConv} -> \code{PipeOpTorchConv3D} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchConv3D-new}{\code{PipeOpTorchConv3D$new()}} -\item \href{#method-PipeOpTorchConv3D-clone}{\code{PipeOpTorchConv3D$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchConv3D-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchConv3D$new(id = "nn_conv3d", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchConv3D-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchConv3D$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_conv_transpose1d.Rd b/man/mlr_pipeops_nn_conv_transpose1d.Rd deleted file mode 100644 index 111450c6..00000000 --- a/man/mlr_pipeops_nn_conv_transpose1d.Rd +++ /dev/null @@ -1,184 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchConvTranspose.R -\name{mlr_pipeops_nn_conv_transpose1d} -\alias{mlr_pipeops_nn_conv_transpose1d} -\alias{PipeOpTorchConvTranspose1D} -\title{Transpose 1D Convolution} -\description{ -Transpose 1D Convolution - -Transpose 1D Convolution -} -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{out_channels} :: \code{integer(1)}\cr -Number of output channels produce by the convolution. -\item \code{kernel_size} :: \code{integer()}\cr -Size of the convolving kernel. -\item \code{stride} :: \code{integer()}\cr -Stride of the convolution. Default: 1. -\item \code{padding} :: \verb{ }integer()`\cr -‘dilation * (kernel_size - 1) - padding’ zero-padding will be added to both sides of the input. Default: 0. -\item \code{output_padding} ::\code{integer()}\cr -Additional size added to one side of the output shape. Default: 0. -\item \code{groups} :: \code{integer()}\cr -Number of blocked connections from input channels to output channels. Default: 1 -\item \code{bias} :: \code{logical(1)}\cr -If ‘True’, adds a learnable bias to the output. Default: ‘TRUE’. -\item \code{dilation} :: \code{integer()}\cr -Spacing between kernel elements. Default: 1. -\item \code{padding_mode} :: \code{character(1)}\cr -The padding mode. One of \code{"zeros"}, \code{"reflect"}, \code{"replicate"}, or \code{"circular"}. Default is \code{"zeros"}. -} -} - -\section{Internals}{ - -Calls \code{\link{nn_conv_transpose1d}}. -The parameter \code{in_channels} is inferred as the second dimension of the input tensor. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_conv_transpose1d", kernel_size = 3, out_channels = 2) -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{mlr3torch::PipeOpTorchConvTranspose} -> \code{PipeOpTorchConvTranspose1D} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchConvTranspose1D-new}{\code{PipeOpTorchConvTranspose1D$new()}} -\item \href{#method-PipeOpTorchConvTranspose1D-clone}{\code{PipeOpTorchConvTranspose1D$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchConvTranspose1D-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchConvTranspose1D$new(id = "nn_conv_transpose1d", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchConvTranspose1D-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchConvTranspose1D$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_conv_transpose2d.Rd b/man/mlr_pipeops_nn_conv_transpose2d.Rd deleted file mode 100644 index 78890b78..00000000 --- a/man/mlr_pipeops_nn_conv_transpose2d.Rd +++ /dev/null @@ -1,183 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchConvTranspose.R -\name{mlr_pipeops_nn_conv_transpose2d} -\alias{mlr_pipeops_nn_conv_transpose2d} -\alias{PipeOpTorchConvTranspose2D} -\title{Transpose 2D Convolution} -\description{ -Applies a 2D transposed convolution operator over an input image -composed of several input planes, sometimes also called "deconvolution". -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Internals}{ - -Calls \code{\link{nn_conv_transpose2d}}. -The parameter \code{in_channels} is inferred as the second dimension of the input tensor. -} - -\section{Parameters}{ - -\itemize{ -\item \code{out_channels} :: \code{integer(1)}\cr -Number of output channels produce by the convolution. -\item \code{kernel_size} :: \code{integer()}\cr -Size of the convolving kernel. -\item \code{stride} :: \code{integer()}\cr -Stride of the convolution. Default: 1. -\item \code{padding} :: \verb{ }integer()`\cr -‘dilation * (kernel_size - 1) - padding’ zero-padding will be added to both sides of the input. Default: 0. -\item \code{output_padding} ::\code{integer()}\cr -Additional size added to one side of the output shape. Default: 0. -\item \code{groups} :: \code{integer()}\cr -Number of blocked connections from input channels to output channels. Default: 1 -\item \code{bias} :: \code{logical(1)}\cr -If ‘True’, adds a learnable bias to the output. Default: ‘TRUE’. -\item \code{dilation} :: \code{integer()}\cr -Spacing between kernel elements. Default: 1. -\item \code{padding_mode} :: \code{character(1)}\cr -The padding mode. One of \code{"zeros"}, \code{"reflect"}, \code{"replicate"}, or \code{"circular"}. Default is \code{"zeros"}. -} -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_conv_transpose2d", kernel_size = 3, out_channels = 2) -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{mlr3torch::PipeOpTorchConvTranspose} -> \code{PipeOpTorchConvTranspose2D} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchConvTranspose2D-new}{\code{PipeOpTorchConvTranspose2D$new()}} -\item \href{#method-PipeOpTorchConvTranspose2D-clone}{\code{PipeOpTorchConvTranspose2D$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchConvTranspose2D-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchConvTranspose2D$new(id = "nn_conv_transpose2d", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchConvTranspose2D-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchConvTranspose2D$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_conv_transpose3d.Rd b/man/mlr_pipeops_nn_conv_transpose3d.Rd deleted file mode 100644 index de6ee003..00000000 --- a/man/mlr_pipeops_nn_conv_transpose3d.Rd +++ /dev/null @@ -1,183 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchConvTranspose.R -\name{mlr_pipeops_nn_conv_transpose3d} -\alias{mlr_pipeops_nn_conv_transpose3d} -\alias{PipeOpTorchConvTranspose3D} -\title{Transpose 3D Convolution} -\description{ -Applies a 3D transposed convolution operator over an input image -composed of several input planes, sometimes also called "deconvolution" -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Internals}{ - -Calls \code{\link{nn_conv_transpose3d}}. -The parameter \code{in_channels} is inferred as the second dimension of the input tensor. -} - -\section{Parameters}{ - -\itemize{ -\item \code{out_channels} :: \code{integer(1)}\cr -Number of output channels produce by the convolution. -\item \code{kernel_size} :: \code{integer()}\cr -Size of the convolving kernel. -\item \code{stride} :: \code{integer()}\cr -Stride of the convolution. Default: 1. -\item \code{padding} :: \verb{ }integer()`\cr -‘dilation * (kernel_size - 1) - padding’ zero-padding will be added to both sides of the input. Default: 0. -\item \code{output_padding} ::\code{integer()}\cr -Additional size added to one side of the output shape. Default: 0. -\item \code{groups} :: \code{integer()}\cr -Number of blocked connections from input channels to output channels. Default: 1 -\item \code{bias} :: \code{logical(1)}\cr -If ‘True’, adds a learnable bias to the output. Default: ‘TRUE’. -\item \code{dilation} :: \code{integer()}\cr -Spacing between kernel elements. Default: 1. -\item \code{padding_mode} :: \code{character(1)}\cr -The padding mode. One of \code{"zeros"}, \code{"reflect"}, \code{"replicate"}, or \code{"circular"}. Default is \code{"zeros"}. -} -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_conv_transpose3d", kernel_size = 3, out_channels = 2) -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{mlr3torch::PipeOpTorchConvTranspose} -> \code{PipeOpTorchConvTranspose3D} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchConvTranspose3D-new}{\code{PipeOpTorchConvTranspose3D$new()}} -\item \href{#method-PipeOpTorchConvTranspose3D-clone}{\code{PipeOpTorchConvTranspose3D$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchConvTranspose3D-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchConvTranspose3D$new(id = "nn_conv_transpose3d", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchConvTranspose3D-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchConvTranspose3D$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_dropout.Rd b/man/mlr_pipeops_nn_dropout.Rd deleted file mode 100644 index 0708f1ec..00000000 --- a/man/mlr_pipeops_nn_dropout.Rd +++ /dev/null @@ -1,169 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchDropout.R -\name{mlr_pipeops_nn_dropout} -\alias{mlr_pipeops_nn_dropout} -\alias{PipeOpTorchDropout} -\title{Dropout} -\description{ -During training, randomly zeroes some of the elements of the input -tensor with probability \code{p} using samples from a Bernoulli -distribution. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{p} :: \code{numeric(1)}\cr -Probability of an element to be zeroed. Default: 0.5 inplace -\item \code{inplace} :: \code{logical(1)}\cr -If set to \code{TRUE}, will do this operation in-place. Default: \code{FALSE}. -} -} - -\section{Internals}{ - -Calls \code{\link[torch:nn_dropout]{torch::nn_dropout()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_dropout") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchDropout} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchDropout-new}{\code{PipeOpTorchDropout$new()}} -\item \href{#method-PipeOpTorchDropout-clone}{\code{PipeOpTorchDropout$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchDropout-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchDropout$new(id = "nn_dropout", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchDropout-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchDropout$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_elu.Rd b/man/mlr_pipeops_nn_elu.Rd deleted file mode 100644 index 8ce7375a..00000000 --- a/man/mlr_pipeops_nn_elu.Rd +++ /dev/null @@ -1,167 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_elu} -\alias{mlr_pipeops_nn_elu} -\alias{PipeOpTorchELU} -\title{ELU Activation Function} -\description{ -Applies element-wise, -\deqn{ELU(x) = max(0,x) + min(0, \alpha * (exp(x) - 1))}. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{alpha} :: \code{numeric(1)}\cr -The alpha value for the ELU formulation. Default: 1.0 -\item \code{inplace} :: \code{logical(1)}\cr -Whether to do the operation in-place. Default: \code{FALSE}. -} -} - -\section{Internals}{ - Calls \code{\link[torch:nn_elu]{torch::nn_elu()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_elu") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchELU} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchELU-new}{\code{PipeOpTorchELU$new()}} -\item \href{#method-PipeOpTorchELU-clone}{\code{PipeOpTorchELU$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchELU-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchELU$new(id = "nn_elu", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchELU-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchELU$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_flatten.Rd b/man/mlr_pipeops_nn_flatten.Rd deleted file mode 100644 index f848734a..00000000 --- a/man/mlr_pipeops_nn_flatten.Rd +++ /dev/null @@ -1,165 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchReshape.R -\name{mlr_pipeops_nn_flatten} -\alias{mlr_pipeops_nn_flatten} -\alias{PipeOpTorchFlatten} -\title{Flattens a Tensor} -\description{ -For use with \link[torch]{nn_sequential}. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\code{start_dim} :: \code{integer(1)}\cr -At wich dimension to start flattening. Default is 2. -\code{end_dim} :: \code{integer(1)}\cr -At wich dimension to stop flattening. Default is -1. -} - -\section{Internals}{ - -Calls \code{\link[torch:nn_flatten]{torch::nn_flatten()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_flatten") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchFlatten} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchFlatten-new}{\code{PipeOpTorchFlatten$new()}} -\item \href{#method-PipeOpTorchFlatten-clone}{\code{PipeOpTorchFlatten$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchFlatten-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchFlatten$new(id = "nn_flatten", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchFlatten-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchFlatten$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_gelu.Rd b/man/mlr_pipeops_nn_gelu.Rd deleted file mode 100644 index 8b9715d7..00000000 --- a/man/mlr_pipeops_nn_gelu.Rd +++ /dev/null @@ -1,164 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_gelu} -\alias{mlr_pipeops_nn_gelu} -\alias{PipeOpTorchGELU} -\title{GELU Activation Function} -\description{ -Gelu -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{approximate} :: \code{character(1)}\cr -Whether to use an approximation algorithm. Default is \code{"none"}. -} -} - -\section{Internals}{ - Calls \code{\link[torch:nn_gelu]{torch::nn_gelu()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_gelu") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchGELU} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchGELU-new}{\code{PipeOpTorchGELU$new()}} -\item \href{#method-PipeOpTorchGELU-clone}{\code{PipeOpTorchGELU$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchGELU-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchGELU$new(id = "nn_gelu", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchGELU-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchGELU$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_glu.Rd b/man/mlr_pipeops_nn_glu.Rd deleted file mode 100644 index 8a2ff5c8..00000000 --- a/man/mlr_pipeops_nn_glu.Rd +++ /dev/null @@ -1,164 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_glu} -\alias{mlr_pipeops_nn_glu} -\alias{PipeOpTorchGLU} -\title{GLU Activation Function} -\description{ -The gated linear unit. Computes: -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{dim} :: \code{integer(1)}\cr -Dimension on which to split the input. Default: -1 -} -} - -\section{Internals}{ - Calls \code{\link[torch:nn_glu]{torch::nn_glu()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_glu") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchGLU} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchGLU-new}{\code{PipeOpTorchGLU$new()}} -\item \href{#method-PipeOpTorchGLU-clone}{\code{PipeOpTorchGLU$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchGLU-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchGLU$new(id = "nn_glu", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchGLU-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchGLU$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_hardshrink.Rd b/man/mlr_pipeops_nn_hardshrink.Rd deleted file mode 100644 index c61f2e22..00000000 --- a/man/mlr_pipeops_nn_hardshrink.Rd +++ /dev/null @@ -1,164 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_hardshrink} -\alias{mlr_pipeops_nn_hardshrink} -\alias{PipeOpTorchHardShrink} -\title{Hard Shrink Activation Function} -\description{ -Applies the hard shrinkage function element-wise -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{lambd} :: \code{numeric(1)}\cr -The lambda value for the Hardshrink formulation formulation. Default 0.5. -} -} - -\section{Internals}{ - Calls \code{\link[torch:nn_hardshrink]{torch::nn_hardshrink()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_hardshrink") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchHardShrink} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchHardShrink-new}{\code{PipeOpTorchHardShrink$new()}} -\item \href{#method-PipeOpTorchHardShrink-clone}{\code{PipeOpTorchHardShrink$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchHardShrink-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchHardShrink$new(id = "nn_hardshrink", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchHardShrink-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchHardShrink$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_hardsigmoid.Rd b/man/mlr_pipeops_nn_hardsigmoid.Rd deleted file mode 100644 index d0b4fedb..00000000 --- a/man/mlr_pipeops_nn_hardsigmoid.Rd +++ /dev/null @@ -1,161 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_hardsigmoid} -\alias{mlr_pipeops_nn_hardsigmoid} -\alias{PipeOpTorchHardSigmoid} -\title{Hard Sigmoid Activation Function} -\description{ -Applies the element-wise function \eqn{\mbox{Hardsigmoid}(x) = \frac{ReLU6(x + 3)}{6}} -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -No parameters. -} - -\section{Internals}{ - Calls \code{\link[torch:nn_hardsigmoid]{torch::nn_hardsigmoid()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_hardsigmoid") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchHardSigmoid} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchHardSigmoid-new}{\code{PipeOpTorchHardSigmoid$new()}} -\item \href{#method-PipeOpTorchHardSigmoid-clone}{\code{PipeOpTorchHardSigmoid$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchHardSigmoid-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchHardSigmoid$new(id = "nn_hardsigmoid", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchHardSigmoid-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchHardSigmoid$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_hardtanh.Rd b/man/mlr_pipeops_nn_hardtanh.Rd deleted file mode 100644 index 2d16549a..00000000 --- a/man/mlr_pipeops_nn_hardtanh.Rd +++ /dev/null @@ -1,162 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_hardtanh} -\alias{mlr_pipeops_nn_hardtanh} -\alias{PipeOpTorchHardTanh} -\title{Hard Tanh Activation Function} -\description{ -Applies the HardTanh function element-wise. -} -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{min_val} :: \code{numeric(1)}\cr -Minimum value of the linear region range. Default: -1. -\item \code{max_val} :: \code{numeric(1)}\cr -Maximum value of the linear region range. Default: 1. -\item \code{inplace} :: \code{logical(1)}\cr -Can optionally do the operation in-place. Default: \code{FALSE}. -} -} - -\section{Internals}{ - Calls \code{\link[torch:nn_hardtanh]{torch::nn_hardtanh()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_hardtanh") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchHardTanh} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchHardTanh-new}{\code{PipeOpTorchHardTanh$new()}} -\item \href{#method-PipeOpTorchHardTanh-clone}{\code{PipeOpTorchHardTanh$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchHardTanh-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchHardTanh$new(id = "nn_hardtanh", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchHardTanh-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchHardTanh$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_head.Rd b/man/mlr_pipeops_nn_head.Rd deleted file mode 100644 index bfd9bd03..00000000 --- a/man/mlr_pipeops_nn_head.Rd +++ /dev/null @@ -1,169 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchHead.R -\name{mlr_pipeops_nn_head} -\alias{mlr_pipeops_nn_head} -\alias{PipeOpTorchHead} -\title{Output Head} -\description{ -Output head for classification and regresssion. - -\strong{NOTE} -Because the method \verb{$shapes_out()} does not have access to the task, it returns \code{c(NA, NA)}. -When this \code{\link{PipeOp}} is trained however, the model descriptor has the correct output shape. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{bias} :: \code{logical(1)}\cr -Whether to use a bias. Default is \code{TRUE}. -} -} - -\section{Internals}{ - -Calls \code{\link[torch:nn_linear]{torch::nn_linear()}} with the input and output features inferred from the input shape / task. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_head") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchHead} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchHead-new}{\code{PipeOpTorchHead$new()}} -\item \href{#method-PipeOpTorchHead-clone}{\code{PipeOpTorchHead$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchHead-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchHead$new(id = "nn_head", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchHead-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchHead$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_layer_norm.Rd b/man/mlr_pipeops_nn_layer_norm.Rd deleted file mode 100644 index ecc366b5..00000000 --- a/man/mlr_pipeops_nn_layer_norm.Rd +++ /dev/null @@ -1,171 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchLayerNorm.R -\name{mlr_pipeops_nn_layer_norm} -\alias{mlr_pipeops_nn_layer_norm} -\alias{PipeOpTorchLayerNorm} -\title{Layer Normalization} -\description{ -Applies Layer Normalization for last certain number of dimensions. -} -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{dims} :: \code{integer(1)}\cr -The number of dimensions over which will be normalized (starting from the last dimension). -\item \code{elementwise_affine} :: \code{logical(1)}\cr -Whether to learn affine-linear parameters initialized to \code{1} for weights and to \code{0} for biases. -The default is \code{TRUE}. -\item \code{eps} :: \code{numeric(1)}\cr -A value added to the denominator for numerical stability. -} -} - -\section{Internals}{ - -Calls \code{\link[torch:nn_layer_norm]{torch::nn_layer_norm()}} when trained. -The parameter \code{normalized_shape} is inferred as the dimensions of the last \code{dims} dimensions of the input shape. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_layer_norm", dims = 1) -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchLayerNorm} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchLayerNorm-new}{\code{PipeOpTorchLayerNorm$new()}} -\item \href{#method-PipeOpTorchLayerNorm-clone}{\code{PipeOpTorchLayerNorm$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchLayerNorm-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchLayerNorm$new(id = "nn_layer_norm", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchLayerNorm-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchLayerNorm$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_leaky_relu.Rd b/man/mlr_pipeops_nn_leaky_relu.Rd deleted file mode 100644 index 9b16959e..00000000 --- a/man/mlr_pipeops_nn_leaky_relu.Rd +++ /dev/null @@ -1,167 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_leaky_relu} -\alias{mlr_pipeops_nn_leaky_relu} -\alias{PipeOpTorchLeakyReLU} -\title{Leaky ReLU Activation Function} -\description{ -Applies element-wise, -\eqn{LeakyReLU(x) = max(0, x) + negative_slope * min(0, x)} -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{negative_slope} :: \code{numeric(1)}\cr -Controls the angle of the negative slope. Default: 1e-2. -\item \code{inplace} :: \code{logical(1)}\cr -Can optionally do the operation in-place. Default: ‘FALSE’. -} -} - -\section{Internals}{ - Calls \code{\link[torch:nn_hardswish]{torch::nn_hardswish()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_leaky_relu") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchLeakyReLU} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchLeakyReLU-new}{\code{PipeOpTorchLeakyReLU$new()}} -\item \href{#method-PipeOpTorchLeakyReLU-clone}{\code{PipeOpTorchLeakyReLU$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchLeakyReLU-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchLeakyReLU$new(id = "nn_leaky_relu", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchLeakyReLU-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchLeakyReLU$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_linear.Rd b/man/mlr_pipeops_nn_linear.Rd deleted file mode 100644 index 513c5c0e..00000000 --- a/man/mlr_pipeops_nn_linear.Rd +++ /dev/null @@ -1,169 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchLinear.R -\name{mlr_pipeops_nn_linear} -\alias{mlr_pipeops_nn_linear} -\alias{PipeOpTorchLinear} -\title{Linear Layer} -\description{ -Applies a linear transformation to the incoming data: \eqn{y = xA^T + b}. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{out_features} :: \code{integer(1)}\cr -The output features of the linear layer. -\item \code{bias} :: \code{logical(1)}\cr -Whether to use a bias. -Default is \code{TRUE}. -} -} - -\section{Internals}{ - -Calls \code{\link[torch:nn_linear]{torch::nn_linear()}} when trained where the parameter \code{in_features} is inferred as the second -to last dimension of the input tensor. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_linear", out_features = 10) -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchLinear} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchLinear-new}{\code{PipeOpTorchLinear$new()}} -\item \href{#method-PipeOpTorchLinear-clone}{\code{PipeOpTorchLinear$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchLinear-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchLinear$new(id = "nn_linear", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchLinear-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchLinear$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_log_sigmoid.Rd b/man/mlr_pipeops_nn_log_sigmoid.Rd deleted file mode 100644 index d6c84891..00000000 --- a/man/mlr_pipeops_nn_log_sigmoid.Rd +++ /dev/null @@ -1,161 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_log_sigmoid} -\alias{mlr_pipeops_nn_log_sigmoid} -\alias{PipeOpTorchLogSigmoid} -\title{Log Sigmoid Activation Function} -\description{ -Applies element-wise \eqn{LogSigmoid(x_i) = log(\frac{1}{1 + exp(-x_i)})} -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -No parameters. -} - -\section{Internals}{ - Calls \code{\link[torch:nn_log_sigmoid]{torch::nn_log_sigmoid()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_log_sigmoid") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchLogSigmoid} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchLogSigmoid-new}{\code{PipeOpTorchLogSigmoid$new()}} -\item \href{#method-PipeOpTorchLogSigmoid-clone}{\code{PipeOpTorchLogSigmoid$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchLogSigmoid-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchLogSigmoid$new(id = "nn_log_sigmoid", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchLogSigmoid-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchLogSigmoid$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_max_pool1d.Rd b/man/mlr_pipeops_nn_max_pool1d.Rd deleted file mode 100644 index e09c4737..00000000 --- a/man/mlr_pipeops_nn_max_pool1d.Rd +++ /dev/null @@ -1,183 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchMaxPool.R -\name{mlr_pipeops_nn_max_pool1d} -\alias{mlr_pipeops_nn_max_pool1d} -\alias{PipeOpTorchMaxPool1D} -\title{1D Max Pooling} -\description{ -Applies a 1D max pooling over an input signal composed of several input -planes. -} -\section{Input and Output Channels}{ - -If \code{return_indices} is \code{FALSE} during construction, there is one input channel 'input' and one output channel 'output'. -If \code{return_indices} is \code{TRUE}, there are two output channels 'output' and 'indices'. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{kernel_size} :: \code{integer()}\cr -The size of the window. Can be single number or a vector. -\item \code{stride} :: (\verb{integer(1))}\cr -The stride of the window. Can be a single number or a vector. Default: \code{kernel_size} -\item \code{padding} :: \code{integer()}\cr -Implicit zero paddings on both sides of the input. Can be a single number or a tuple (padW,). Default: 0 -\item \code{dilation} :: \code{integer()}\cr -Controls the spacing between the kernel points; also known as the à trous algorithm. Default: 1 -\item \code{ceil_mode} :: \code{logical(1)}\cr -When True, will use ceil instead of floor to compute the output shape. Default: \code{FALSE} -} -} - -\section{Internals}{ - -Calls \code{\link[torch:nn_max_pool1d]{torch::nn_max_pool1d()}} during training. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_max_pool1d") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{mlr3torch::PipeOpTorchMaxPool} -> \code{PipeOpTorchMaxPool1D} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchMaxPool1D-new}{\code{PipeOpTorchMaxPool1D$new()}} -\item \href{#method-PipeOpTorchMaxPool1D-clone}{\code{PipeOpTorchMaxPool1D$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchMaxPool1D-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchMaxPool1D$new( - id = "nn_max_pool1d", - return_indices = FALSE, - param_vals = list() -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{return_indices}}{(\code{logical(1)})\cr -Whether to return the indices. -If this is \code{TRUE}, there are two output channels \code{"output"} and \code{"indices"}.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchMaxPool1D-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchMaxPool1D$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_max_pool2d.Rd b/man/mlr_pipeops_nn_max_pool2d.Rd deleted file mode 100644 index 4a4bbb79..00000000 --- a/man/mlr_pipeops_nn_max_pool2d.Rd +++ /dev/null @@ -1,183 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchMaxPool.R -\name{mlr_pipeops_nn_max_pool2d} -\alias{mlr_pipeops_nn_max_pool2d} -\alias{PipeOpTorchMaxPool2D} -\title{2D Max Pooling} -\description{ -Applies a 2D max pooling over an input signal composed of several input -planes. -} -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Internals}{ - -Calls \code{\link[torch:nn_max_pool2d]{torch::nn_max_pool2d()}} during training. -} - -\section{Input and Output Channels}{ - -If \code{return_indices} is \code{FALSE} during construction, there is one input channel 'input' and one output channel 'output'. -If \code{return_indices} is \code{TRUE}, there are two output channels 'output' and 'indices'. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{kernel_size} :: \code{integer()}\cr -The size of the window. Can be single number or a vector. -\item \code{stride} :: (\verb{integer(1))}\cr -The stride of the window. Can be a single number or a vector. Default: \code{kernel_size} -\item \code{padding} :: \code{integer()}\cr -Implicit zero paddings on both sides of the input. Can be a single number or a tuple (padW,). Default: 0 -\item \code{dilation} :: \code{integer()}\cr -Controls the spacing between the kernel points; also known as the à trous algorithm. Default: 1 -\item \code{ceil_mode} :: \code{logical(1)}\cr -When True, will use ceil instead of floor to compute the output shape. Default: \code{FALSE} -} -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_max_pool2d") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{mlr3torch::PipeOpTorchMaxPool} -> \code{PipeOpTorchMaxPool2D} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchMaxPool2D-new}{\code{PipeOpTorchMaxPool2D$new()}} -\item \href{#method-PipeOpTorchMaxPool2D-clone}{\code{PipeOpTorchMaxPool2D$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchMaxPool2D-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchMaxPool2D$new( - id = "nn_max_pool2d", - return_indices = FALSE, - param_vals = list() -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{return_indices}}{(\code{logical(1)})\cr -Whether to return the indices. -If this is \code{TRUE}, there are two output channels \code{"output"} and \code{"indices"}.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchMaxPool2D-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchMaxPool2D$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_max_pool3d.Rd b/man/mlr_pipeops_nn_max_pool3d.Rd deleted file mode 100644 index 277ad6d9..00000000 --- a/man/mlr_pipeops_nn_max_pool3d.Rd +++ /dev/null @@ -1,183 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchMaxPool.R -\name{mlr_pipeops_nn_max_pool3d} -\alias{mlr_pipeops_nn_max_pool3d} -\alias{PipeOpTorchMaxPool3D} -\title{3D Max Pooling} -\description{ -Applies a 3D max pooling over an input signal composed of several input -planes. -} -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Internals}{ - -Calls \code{\link[torch:nn_max_pool3d]{torch::nn_max_pool3d()}} during training. -} - -\section{Input and Output Channels}{ - -If \code{return_indices} is \code{FALSE} during construction, there is one input channel 'input' and one output channel 'output'. -If \code{return_indices} is \code{TRUE}, there are two output channels 'output' and 'indices'. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{kernel_size} :: \code{integer()}\cr -The size of the window. Can be single number or a vector. -\item \code{stride} :: (\verb{integer(1))}\cr -The stride of the window. Can be a single number or a vector. Default: \code{kernel_size} -\item \code{padding} :: \code{integer()}\cr -Implicit zero paddings on both sides of the input. Can be a single number or a tuple (padW,). Default: 0 -\item \code{dilation} :: \code{integer()}\cr -Controls the spacing between the kernel points; also known as the à trous algorithm. Default: 1 -\item \code{ceil_mode} :: \code{logical(1)}\cr -When True, will use ceil instead of floor to compute the output shape. Default: \code{FALSE} -} -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_max_pool3d") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{mlr3torch::PipeOpTorchMaxPool} -> \code{PipeOpTorchMaxPool3D} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchMaxPool3D-new}{\code{PipeOpTorchMaxPool3D$new()}} -\item \href{#method-PipeOpTorchMaxPool3D-clone}{\code{PipeOpTorchMaxPool3D$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchMaxPool3D-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchMaxPool3D$new( - id = "nn_max_pool3d", - return_indices = FALSE, - param_vals = list() -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{return_indices}}{(\code{logical(1)})\cr -Whether to return the indices. -If this is \code{TRUE}, there are two output channels \code{"output"} and \code{"indices"}.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchMaxPool3D-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchMaxPool3D$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_merge.Rd b/man/mlr_pipeops_nn_merge.Rd deleted file mode 100644 index ff6a184c..00000000 --- a/man/mlr_pipeops_nn_merge.Rd +++ /dev/null @@ -1,172 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchMerge.R -\name{mlr_pipeops_nn_merge} -\alias{mlr_pipeops_nn_merge} -\alias{PipeOpTorchMerge} -\title{Merge Operation} -\description{ -Base class for merge operations such as addition (\code{\link{PipeOpTorchMergeSum}}), multiplication -(\code{\link{PipeOpTorchMergeProd}} or concatenation (\code{\link{PipeOpTorchMergeCat}}). -} -\section{State}{ - -The state is the value calculated by the public method \code{shapes_out()}. -} - -\section{Input and Output Channels}{ - -\code{PipeOpTorchMerge}s has either a \emph{vararg} input channel if the constructor argument \code{innum} is not set, or -input channels \code{"input1"}, ..., \code{"input"}. There is one output channel \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{Parameters}{ - See the respective child class. -} - -\section{Internals}{ - -Per default, the \code{private$.shapes_out()} method outputs the broadcasted tensors. There are two things to be aware: -\enumerate{ -\item \code{NA}s are assumed to batch (this should almost always be the batch size in the first dimension). -\item Tensors are expected to have the same number of dimensions, i.e. missing dimensions are not filled with 1s. -The reason is that again that the first dimension should be the batch dimension. -This private method can be overwritten by \code{\link{PipeOpTorch}}s inheriting from this class. -} -} - -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchMerge} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchMerge-new}{\code{PipeOpTorchMerge$new()}} -\item \href{#method-PipeOpTorchMerge-clone}{\code{PipeOpTorchMerge$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchMerge-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchMerge$new( - id, - module_generator, - param_set = ps(), - innum = 0, - param_vals = list() -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{module_generator}}{(\code{nn_module_generator})\cr -The torch module generator.} - -\item{\code{param_set}}{(\code{paradox::ParamSet})\cr -The parameter set.} - -\item{\code{innum}}{(\code{integer(1)})\cr -The number of inputs. Default is 0 which means there is one \emph{vararg} input channel.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchMerge-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchMerge$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_merge_cat.Rd b/man/mlr_pipeops_nn_merge_cat.Rd deleted file mode 100644 index 6cfc99e8..00000000 --- a/man/mlr_pipeops_nn_merge_cat.Rd +++ /dev/null @@ -1,185 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchMerge.R -\name{mlr_pipeops_nn_merge_cat} -\alias{mlr_pipeops_nn_merge_cat} -\alias{PipeOpTorchMergeCat} -\title{Merge by Concatenation} -\description{ -Concatenates multiple tensors on a given dimension. -No broadcasting rules are applied here, you must reshape the tensors before to have the same shape. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. - - -\code{PipeOpTorchMerge}s has either a \emph{vararg} input channel if the constructor argument \code{innum} is not set, or -input channels \code{"input1"}, ..., \code{"input"}. There is one output channel \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{dim} :: \code{integer(1)}\cr -The dimension along which to concatenate the tensors. -} -} - -\section{Internals}{ - -Calls \code{\link[=nn_merge_cat]{nn_merge_cat()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_merge_cat") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{\link[mlr3torch:PipeOpTorchMerge]{mlr3torch::PipeOpTorchMerge}} -> \code{PipeOpTorchMergeCat} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchMergeCat-new}{\code{PipeOpTorchMergeCat$new()}} -\item \href{#method-PipeOpTorchMergeCat-speak}{\code{PipeOpTorchMergeCat$speak()}} -\item \href{#method-PipeOpTorchMergeCat-clone}{\code{PipeOpTorchMergeCat$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchMergeCat-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchMergeCat$new(id = "nn_merge_cat", innum = 0, param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{innum}}{(\code{integer(1)})\cr -The number of inputs. Default is 0 which means there is one \emph{vararg} input channel.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchMergeCat-speak}{}}} -\subsection{Method \code{speak()}}{ -What does the cat say? -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchMergeCat$speak()}\if{html}{\out{
}} -} - -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchMergeCat-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchMergeCat$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_merge_prod.Rd b/man/mlr_pipeops_nn_merge_prod.Rd deleted file mode 100644 index b7fe76f4..00000000 --- a/man/mlr_pipeops_nn_merge_prod.Rd +++ /dev/null @@ -1,170 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchMerge.R -\name{mlr_pipeops_nn_merge_prod} -\alias{mlr_pipeops_nn_merge_prod} -\alias{PipeOpTorchMergeProd} -\title{Merge by Product} -\description{ -Calculates the product of all input tensors. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. - - -\code{PipeOpTorchMerge}s has either a \emph{vararg} input channel if the constructor argument \code{innum} is not set, or -input channels \code{"input1"}, ..., \code{"input"}. There is one output channel \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -No parameters. -} - -\section{Internals}{ - -Calls \code{\link[=nn_merge_prod]{nn_merge_prod()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_merge_prod") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{\link[mlr3torch:PipeOpTorchMerge]{mlr3torch::PipeOpTorchMerge}} -> \code{PipeOpTorchMergeProd} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchMergeProd-new}{\code{PipeOpTorchMergeProd$new()}} -\item \href{#method-PipeOpTorchMergeProd-clone}{\code{PipeOpTorchMergeProd$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchMergeProd-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchMergeProd$new(id = "nn_merge_prod", innum = 0, param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{innum}}{(\code{integer(1)})\cr -The number of inputs. Default is 0 which means there is one \emph{vararg} input channel.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchMergeProd-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchMergeProd$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_merge_sum.Rd b/man/mlr_pipeops_nn_merge_sum.Rd deleted file mode 100644 index 73858dc7..00000000 --- a/man/mlr_pipeops_nn_merge_sum.Rd +++ /dev/null @@ -1,227 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchMerge.R -\name{mlr_pipeops_nn_merge_sum} -\alias{mlr_pipeops_nn_merge_sum} -\alias{PipeOpTorchMergeSum} -\title{Merge by Summation} -\description{ -Calculates the sum of all input tensors. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. - - -\code{PipeOpTorchMerge}s has either a \emph{vararg} input channel if the constructor argument \code{innum} is not set, or -input channels \code{"input1"}, ..., \code{"input"}. There is one output channel \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -No parameters. -} - -\section{Internals}{ - -Calls \code{\link[=nn_merge_sum]{nn_merge_sum()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_merge_sum") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} - -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{\link[mlr3torch:PipeOpTorchMerge]{mlr3torch::PipeOpTorchMerge}} -> \code{PipeOpTorchMergeSum} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchMergeSum-new}{\code{PipeOpTorchMergeSum$new()}} -\item \href{#method-PipeOpTorchMergeSum-clone}{\code{PipeOpTorchMergeSum$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchMergeSum-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchMergeSum$new(id = "nn_merge_sum", innum = 0, param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{innum}}{(\code{integer(1)})\cr -The number of inputs. Default is 0 which means there is one \emph{vararg} input channel.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchMergeSum-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchMergeSum$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_prelu.Rd b/man/mlr_pipeops_nn_prelu.Rd deleted file mode 100644 index b065394b..00000000 --- a/man/mlr_pipeops_nn_prelu.Rd +++ /dev/null @@ -1,169 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_prelu} -\alias{mlr_pipeops_nn_prelu} -\alias{PipeOpTorchPReLU} -\title{PReLU Activation Function} -\description{ -Applies element-wise the function -\eqn{PReLU(x) = max(0,x) + weight * min(0,x)} -where weight is a learnable parameter. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{num_parameters} :: \code{integer(1)}: -Number of a to learn. Although it takes an int as input, there is only two values are legitimate: 1, or the -number of channels at input. Default: 1. -\item \code{init} :: \code{numeric(1)}\cr T -The initial value of a. Default: 0.25. -} -} - -\section{Internals}{ - Calls \code{\link[torch:nn_prelu]{torch::nn_prelu()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_prelu") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchPReLU} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchPReLU-new}{\code{PipeOpTorchPReLU$new()}} -\item \href{#method-PipeOpTorchPReLU-clone}{\code{PipeOpTorchPReLU$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchPReLU-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchPReLU$new(id = "nn_prelu", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchPReLU-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchPReLU$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_relu.Rd b/man/mlr_pipeops_nn_relu.Rd deleted file mode 100644 index a3dd171a..00000000 --- a/man/mlr_pipeops_nn_relu.Rd +++ /dev/null @@ -1,164 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_relu} -\alias{mlr_pipeops_nn_relu} -\alias{PipeOpTorchReLU} -\title{ReLU Activation Function} -\description{ -Applies the rectified linear unit function element-wise. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{inplace} :: \code{logical(1)}\cr -Whether to do the operation in-place. Default: \code{FALSE}. -} -} - -\section{Internals}{ - Calls \code{\link[torch:nn_relu]{torch::nn_relu()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_relu") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchReLU} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchReLU-new}{\code{PipeOpTorchReLU$new()}} -\item \href{#method-PipeOpTorchReLU-clone}{\code{PipeOpTorchReLU$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchReLU-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchReLU$new(id = "nn_relu", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchReLU-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchReLU$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_relu6.Rd b/man/mlr_pipeops_nn_relu6.Rd deleted file mode 100644 index 48230853..00000000 --- a/man/mlr_pipeops_nn_relu6.Rd +++ /dev/null @@ -1,164 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_relu6} -\alias{mlr_pipeops_nn_relu6} -\alias{PipeOpTorchReLU6} -\title{ReLU6 Activation Function} -\description{ -Applies the element-wise function \eqn{ReLU6(x) = min(max(0,x), 6)}. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{inplace} :: \code{logical(1)}\cr -Whether to do the operation in-place. Default: \code{FALSE}. -} -} - -\section{Internals}{ - Calls \code{\link[torch:nn_relu6]{torch::nn_relu6()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_relu6") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchReLU6} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchReLU6-new}{\code{PipeOpTorchReLU6$new()}} -\item \href{#method-PipeOpTorchReLU6-clone}{\code{PipeOpTorchReLU6$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchReLU6-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchReLU6$new(id = "nn_relu6", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchReLU6-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchReLU6$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_reshape.Rd b/man/mlr_pipeops_nn_reshape.Rd deleted file mode 100644 index 4a80e200..00000000 --- a/man/mlr_pipeops_nn_reshape.Rd +++ /dev/null @@ -1,166 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchReshape.R -\name{mlr_pipeops_nn_reshape} -\alias{mlr_pipeops_nn_reshape} -\alias{PipeOpTorchReshape} -\title{Reshape a Tensor} -\description{ -Reshape a tensor to the given shape. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{shape} :: \code{integer(1)}\cr -The desired output shape. Unknown dimension (one at most) can either be specified as \code{-1} or \code{NA}. -} -} - -\section{Internals}{ - -Calls \code{\link[=nn_reshape]{nn_reshape()}} when trained. -This internally calls \code{\link[torch:torch_reshape]{torch::torch_reshape()}} with the given \code{shape}. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_reshape") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchReshape} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchReshape-new}{\code{PipeOpTorchReshape$new()}} -\item \href{#method-PipeOpTorchReshape-clone}{\code{PipeOpTorchReshape$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchReshape-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchReshape$new(id = "nn_reshape", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchReshape-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchReshape$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_rrelu.Rd b/man/mlr_pipeops_nn_rrelu.Rd deleted file mode 100644 index 70023721..00000000 --- a/man/mlr_pipeops_nn_rrelu.Rd +++ /dev/null @@ -1,168 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_rrelu} -\alias{mlr_pipeops_nn_rrelu} -\alias{PipeOpTorchRReLU} -\title{RReLU Activation Function} -\description{ -Randomized leaky ReLU. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{lower}:: \code{numeric(1)}\cr -Lower bound of the uniform distribution. Default: 1/8. -\item \code{upper}:: \code{numeric(1)}\cr -Upper bound of the uniform distribution. Default: 1/3. -\item \code{inplace} :: \code{logical(1)}\cr -Whether to do the operation in-place. Default: \code{FALSE}. -} -} - -\section{Internals}{ - Calls \code{\link[torch:nn_rrelu]{torch::nn_rrelu()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_rrelu") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchRReLU} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchRReLU-new}{\code{PipeOpTorchRReLU$new()}} -\item \href{#method-PipeOpTorchRReLU-clone}{\code{PipeOpTorchRReLU$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchRReLU-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchRReLU$new(id = "nn_rrelu", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchRReLU-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchRReLU$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_selu.Rd b/man/mlr_pipeops_nn_selu.Rd deleted file mode 100644 index 87afed1f..00000000 --- a/man/mlr_pipeops_nn_selu.Rd +++ /dev/null @@ -1,167 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_selu} -\alias{mlr_pipeops_nn_selu} -\alias{PipeOpTorchSELU} -\title{SELU Activation Function} -\description{ -Applies element-wise, -\deqn{SELU(x) = scale * (max(0,x) + min(0, \alpha * (exp(x) - 1)))}, -with \eqn{\alpha=1.6732632423543772848170429916717} and -\eqn{scale=1.0507009873554804934193349852946}. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{inplace} :: \code{logical(1)}\cr -Whether to do the operation in-place. Default: \code{FALSE}. -} -} - -\section{Internals}{ - Calls \code{\link[torch:nn_selu]{torch::nn_selu()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_selu") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchSELU} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchSELU-new}{\code{PipeOpTorchSELU$new()}} -\item \href{#method-PipeOpTorchSELU-clone}{\code{PipeOpTorchSELU$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchSELU-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchSELU$new(id = "nn_selu", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchSELU-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchSELU$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_sigmoid.Rd b/man/mlr_pipeops_nn_sigmoid.Rd deleted file mode 100644 index 628e393f..00000000 --- a/man/mlr_pipeops_nn_sigmoid.Rd +++ /dev/null @@ -1,161 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_sigmoid} -\alias{mlr_pipeops_nn_sigmoid} -\alias{PipeOpTorchSigmoid} -\title{Sigmoid Activation Function} -\description{ -Applies element-wise \eqn{Sigmoid(x_i) = \frac{1}{1 + exp(-x_i)}} -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -No parameters. -} - -\section{Internals}{ - Calls \code{\link[torch:nn_sigmoid]{torch::nn_sigmoid()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_sigmoid") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchSigmoid} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchSigmoid-new}{\code{PipeOpTorchSigmoid$new()}} -\item \href{#method-PipeOpTorchSigmoid-clone}{\code{PipeOpTorchSigmoid$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchSigmoid-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchSigmoid$new(id = "nn_sigmoid", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchSigmoid-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchSigmoid$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_softmax.Rd b/man/mlr_pipeops_nn_softmax.Rd deleted file mode 100644 index d08d04ec..00000000 --- a/man/mlr_pipeops_nn_softmax.Rd +++ /dev/null @@ -1,165 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchSoftmax.R -\name{mlr_pipeops_nn_softmax} -\alias{mlr_pipeops_nn_softmax} -\alias{PipeOpTorchSoftmax} -\title{Softmax} -\description{ -Applies a softmax function. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{dim} :: \code{integer(1)}\cr -A dimension along which Softmax will be computed (so every slice along dim will sum to 1). -} -} - -\section{Internals}{ - -Calls \code{\link[torch:nn_softmax]{torch::nn_softmax()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_softmax") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchSoftmax} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchSoftmax-new}{\code{PipeOpTorchSoftmax$new()}} -\item \href{#method-PipeOpTorchSoftmax-clone}{\code{PipeOpTorchSoftmax$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchSoftmax-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchSoftmax$new(id = "nn_softmax", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchSoftmax-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchSoftmax$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_softplus.Rd b/man/mlr_pipeops_nn_softplus.Rd deleted file mode 100644 index ba1a897b..00000000 --- a/man/mlr_pipeops_nn_softplus.Rd +++ /dev/null @@ -1,166 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_softplus} -\alias{mlr_pipeops_nn_softplus} -\alias{PipeOpTorchSoftPlus} -\title{SoftPlus Activation Function} -\description{ -Applies element-wise, the function \eqn{Softplus(x) = 1/\beta * log(1 + exp(\beta * x))}. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{beta} :: \code{numeric(1)}\cr -The beta value for the Softplus formulation. Default: 1 -\item \code{threshold} :: \code{numeric(1)}\cr -Values above this revert to a linear function. Default: 20 -} -} - -\section{Internals}{ - Calls \code{\link[torch:nn_softplus]{torch::nn_softplus()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_softplus") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchSoftPlus} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchSoftPlus-new}{\code{PipeOpTorchSoftPlus$new()}} -\item \href{#method-PipeOpTorchSoftPlus-clone}{\code{PipeOpTorchSoftPlus$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchSoftPlus-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchSoftPlus$new(id = "nn_softplus", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchSoftPlus-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchSoftPlus$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_softshrink.Rd b/man/mlr_pipeops_nn_softshrink.Rd deleted file mode 100644 index bbf197a9..00000000 --- a/man/mlr_pipeops_nn_softshrink.Rd +++ /dev/null @@ -1,164 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_softshrink} -\alias{mlr_pipeops_nn_softshrink} -\alias{PipeOpTorchSoftShrink} -\title{Soft Shrink Activation Function} -\description{ -Applies the soft shrinkage function elementwise -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{lamd} :: \code{numeric(1)}\cr -The lambda (must be no less than zero) value for the Softshrink formulation. Default: 0.5 -} -} - -\section{Internals}{ - Calls \code{\link[torch:nn_softshrink]{torch::nn_softshrink()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_softshrink") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchSoftShrink} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchSoftShrink-new}{\code{PipeOpTorchSoftShrink$new()}} -\item \href{#method-PipeOpTorchSoftShrink-clone}{\code{PipeOpTorchSoftShrink$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchSoftShrink-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchSoftShrink$new(id = "nn_softshrink", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchSoftShrink-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchSoftShrink$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_softsign.Rd b/man/mlr_pipeops_nn_softsign.Rd deleted file mode 100644 index 6b079e6b..00000000 --- a/man/mlr_pipeops_nn_softsign.Rd +++ /dev/null @@ -1,161 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_softsign} -\alias{mlr_pipeops_nn_softsign} -\alias{PipeOpTorchSoftSign} -\title{SoftSign Activation Function} -\description{ -Applies element-wise, the function \eqn{SoftSign(x) = x/(1 + |x|} -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -No parameters. -} - -\section{Internals}{ - Calls \code{\link[torch:nn_softsign]{torch::nn_softsign()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_softsign") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchSoftSign} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchSoftSign-new}{\code{PipeOpTorchSoftSign$new()}} -\item \href{#method-PipeOpTorchSoftSign-clone}{\code{PipeOpTorchSoftSign$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchSoftSign-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchSoftSign$new(id = "nn_softsign", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchSoftSign-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchSoftSign$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_squeeze.Rd b/man/mlr_pipeops_nn_squeeze.Rd deleted file mode 100644 index 32fc5d40..00000000 --- a/man/mlr_pipeops_nn_squeeze.Rd +++ /dev/null @@ -1,310 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchReshape.R -\name{mlr_pipeops_nn_squeeze} -\alias{mlr_pipeops_nn_squeeze} -\alias{PipeOpTorchSqueeze} -\alias{PipeOpTorchUnsqueeze} -\title{Squeeze a Tensor} -\description{ -Squeezes a tensor by calling \code{\link[torch:torch_squeeze]{torch::torch_squeeze()}} with the given dimension \code{dim}. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. - - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. - - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. - - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{dim} :: \code{integer(1)}\cr -The dimension to squeeze. If \code{NULL}, all dimensions of size 1 will be squeezed. -Negative values are interpreted downwards from the last dimension. -} - - -\itemize{ -\item \code{dim} :: \code{integer(1)}\cr -The dimension which to unsqueeze. Negative values are interpreted downwards from the last dimension. -} -} - -\section{Internals}{ - -Calls \code{\link[=nn_squeeze]{nn_squeeze()}} when trained. - - -Calls \code{\link[=nn_unsqueeze]{nn_unsqueeze()}} when trained. -This internally calls \code{\link[torch:torch_unsqueeze]{torch::torch_unsqueeze()}}. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_squeeze") -pipeop -# The available parameters -pipeop$param_set -# Construct the PipeOp -pipeop = po("nn_squeeze") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} - -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchSqueeze} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchSqueeze-new}{\code{PipeOpTorchSqueeze$new()}} -\item \href{#method-PipeOpTorchSqueeze-clone}{\code{PipeOpTorchSqueeze$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchSqueeze-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchSqueeze$new(id = "nn_squeeze", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchSqueeze-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchSqueeze$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchUnsqueeze} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchUnsqueeze-new}{\code{PipeOpTorchUnsqueeze$new()}} -\item \href{#method-PipeOpTorchUnsqueeze-clone}{\code{PipeOpTorchUnsqueeze$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchUnsqueeze-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchUnsqueeze$new(id = "nn_unsqueeze", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchUnsqueeze-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchUnsqueeze$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_tanh.Rd b/man/mlr_pipeops_nn_tanh.Rd deleted file mode 100644 index d626dbee..00000000 --- a/man/mlr_pipeops_nn_tanh.Rd +++ /dev/null @@ -1,161 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_tanh} -\alias{mlr_pipeops_nn_tanh} -\alias{PipeOpTorchTanh} -\title{Tanh Activation Function} -\description{ -Applies the element-wise function: -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -No parameters. -} - -\section{Internals}{ - Calls \code{\link[torch:nn_tanh]{torch::nn_tanh()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_tanh") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchTanh} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchTanh-new}{\code{PipeOpTorchTanh$new()}} -\item \href{#method-PipeOpTorchTanh-clone}{\code{PipeOpTorchTanh$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchTanh-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchTanh$new(id = "nn_tanh", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchTanh-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchTanh$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_tanhshrink.Rd b/man/mlr_pipeops_nn_tanhshrink.Rd deleted file mode 100644 index 8dc2513a..00000000 --- a/man/mlr_pipeops_nn_tanhshrink.Rd +++ /dev/null @@ -1,161 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_tanhshrink} -\alias{mlr_pipeops_nn_tanhshrink} -\alias{PipeOpTorchTanhShrink} -\title{Tanh Shrink Activation Function} -\description{ -Applies element-wise, \eqn{Tanhshrink(x) = x - Tanh(x)} -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -No parameters. -} - -\section{Internals}{ - Calls \code{\link[torch:nn_tanhshrink]{torch::nn_tanhshrink()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_tanhshrink") -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchTanhShrink} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchTanhShrink-new}{\code{PipeOpTorchTanhShrink$new()}} -\item \href{#method-PipeOpTorchTanhShrink-clone}{\code{PipeOpTorchTanhShrink$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchTanhShrink-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchTanhShrink$new(id = "nn_tanhshrink", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchTanhShrink-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchTanhShrink$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_nn_threshold.Rd b/man/mlr_pipeops_nn_threshold.Rd deleted file mode 100644 index 161acae7..00000000 --- a/man/mlr_pipeops_nn_threshold.Rd +++ /dev/null @@ -1,168 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchActivation.R -\name{mlr_pipeops_nn_threshold} -\alias{mlr_pipeops_nn_threshold} -\alias{PipeOpTorchThreshold} -\title{Treshold Activation Function} -\description{ -Thresholds each element of the input Tensor. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \verb{$shapes_out()}. -} - -\section{Credit}{ - -Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{threshold} :: \code{numeric(1)}\cr -The value to threshold at. -\item \code{value} :: \code{numeric(1)}\cr -The value to replace with. -\item \code{inplace} :: \code{logical(1)}\cr -Can optionally do the operation in-place. Default: ‘FALSE’. -} -} - -\section{Internals}{ - Calls \code{\link[torch:nn_threshold]{torch::nn_threshold()}} when trained. -} - -\examples{ -# Construct the PipeOp -pipeop = po("nn_threshold", threshold = 1, value = 2) -pipeop -# The available parameters -pipeop$param_set -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorch]{mlr3torch::PipeOpTorch}} -> \code{PipeOpTorchThreshold} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchThreshold-new}{\code{PipeOpTorchThreshold$new()}} -\item \href{#method-PipeOpTorchThreshold-clone}{\code{PipeOpTorchThreshold$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchThreshold-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchThreshold$new(id = "nn_threshold", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchThreshold-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchThreshold$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_preproc_torch.Rd b/man/mlr_pipeops_preproc_torch.Rd deleted file mode 100644 index ccb219ea..00000000 --- a/man/mlr_pipeops_preproc_torch.Rd +++ /dev/null @@ -1,302 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTaskPreprocTorch.R -\name{mlr_pipeops_preproc_torch} -\alias{mlr_pipeops_preproc_torch} -\alias{PipeOpTaskPreprocTorch} -\title{Base Class for Lazy Tensor Preprocessing} -\description{ -This \code{PipeOp} can be used to preprocess (one or more) \code{\link{lazy_tensor}} columns contained in an \code{\link[mlr3:Task]{mlr3::Task}}. -The preprocessing function is specified as construction argument \code{fn} and additional arguments to this -function can be defined through the \code{PipeOp}'s parameter set. -The preprocessing is done per column, i.e. the number of lazy tensor output columns is equal -to the number of lazy tensor input columns. - -To create custom preprocessing \code{PipeOp}s you can use \code{\link{pipeop_preproc_torch}}. -} -\section{Inheriting}{ - -In addition to specifying the construction arguments, you can overwrite the private \code{.shapes_out()} method. -If you don't overwrite it, the output shapes are assumed to be unknown (\code{NULL}). -\itemize{ -\item \code{.shapes_out(shapes_in, param_vals, task)}\cr -(\code{list()}, \verb{list(), }Task\code{or}NULL\verb{) -> }list()\verb{\\cr This private method calculates the output shapes of the lazy tensor columns that are created from applying the preprocessing function with the provided parameter values (}param_vals\verb{). The }task\verb{is very rarely needed, but if it is it should be checked that it is not}NULL`. - -This private method only has the responsibility to calculate the output shapes for one input column, i.e. the -input \code{shapes_in} can be assumed to have exactly one shape vector for which it must calculate the output shapes -and return it as a \code{list()} of length 1. -It can also be assumed that the shape is not \code{NULL} (i.e. unknown). -Also, the first dimension can be \code{NA}, i.e. is unknown (as for the batch dimension). -} -} - -\section{Input and Output Channels}{ - -See \code{\link{PipeOpTaskPreproc}}. -} - -\section{State}{ - -In addition to state elements from \code{\link{PipeOpTaskPreprocSimple}}, the state also contains the \verb{$param_vals} that -were set during training. -} - -\section{Parameters}{ - -In addition to the parameters inherited from \code{\link{PipeOpTaskPreproc}} as well as those specified during construction -as the argument \code{param_set} there are the following parameters: -\itemize{ -\item \code{stages} :: \code{character(1)}\cr -The stages during which to apply the preprocessing. -Can be one of \code{"train"}, \code{"predict"} or \code{"both"}. -The initial value of this parameter is set to \code{"train"} when the \code{PipeOp}'s id starts with \code{"augment_"} and -to \code{"both"} otherwise. -Note that the preprocessing that is applied during \verb{$predict()} uses the parameters that were set during -\verb{$train()} and not those that are set when performing the prediction. -} -} - -\section{Internals}{ - -During \verb{$train()} / \verb{$predict()}, a \code{\link{PipeOpModule}} with one input and one output channel is created. -The pipeop applies the function \code{fn} to the input tensor while additionally -passing the parameter values (minus \code{stages} and \code{affect_columns}) to \code{fn}. -The preprocessing graph of the lazy tensor columns is shallowly cloned and the \code{PipeOpModule} is added. -This is done to avoid modifying user input and means that identical \code{PipeOpModule}s can be part of different -preprocessing graphs. This is only possible, because the created \code{PipeOpModule} is stateless. - -At a later point in the graph, preprocessing graphs will be merged if possible to avoid unnecessary computation. -This is best illustrated by example: -One lazy tensor column's preprocessing graph is \code{A -> B}. -Then, two branches are created \code{B -> C} and \code{B -> D}, creating two preprocessing graphs -\code{A -> B -> C} and \code{A -> B -> D}. When loading the data, we want to run the preprocessing only once, i.e. we don't -want to run the \code{A -> B} part twice. For this reason, \code{\link[=task_dataset]{task_dataset()}} will try to merge graphs and cache -results from graphs. However, only graphs using the same dataset can currently be merged. - -Also, the shapes created during \verb{$train()} and \verb{$predict()} might differ. -To avoid the creation of graphs where the predict shapes are incompatible with the train shapes, -the hypothetical predict shapes are already calculated during \verb{$train()} (this is why the parameters that are set -during train are also used during predict) and the \code{\link{PipeOpTorchModel}} will check the train and predict shapes for -compatibility before starting the training. - -Otherwise, this mechanism is very similar to the \code{\link{ModelDescriptor}} construct. -} - -\examples{ -# Creating a simple task -d = data.table( - x1 = as_lazy_tensor(rnorm(10)), - x2 = as_lazy_tensor(rnorm(10)), - x3 = as_lazy_tensor(as.double(1:10)), - y = rnorm(10) -) - -taskin = as_task_regr(d, target = "y") - -# Creating a simple preprocessing pipeop -po_simple = po("preproc_torch", - # get rid of environment baggage - fn = mlr3misc::crate(function(x, a) x + a), - param_set = paradox::ps(a = paradox::p_int(tags = c("train", "required"))) -) - -po_simple$param_set$set_values( - a = 100, - affect_columns = selector_name(c("x1", "x2")), - stages = "both" # use during train and predict -) - -taskout_train = po_simple$train(list(taskin))[[1L]] -materialize(taskout_train$data(cols = c("x1", "x2")), rbind = TRUE) - -taskout_predict_noaug = po_simple$predict(list(taskin))[[1L]] -materialize(taskout_predict_noaug$data(cols = c("x1", "x2")), rbind = TRUE) - -po_simple$param_set$set_values( - stages = "train" -) - -# transformation is not applied -taskout_predict_aug = po_simple$predict(list(taskin))[[1L]] -materialize(taskout_predict_aug$data(cols = c("x1", "x2")), rbind = TRUE) - -# Creating a more complex preprocessing PipeOp -PipeOpPreprocTorchPoly = R6::R6Class("PipeOpPreprocTorchPoly", - inherit = PipeOpTaskPreprocTorch, - public = list( - initialize = function(id = "preproc_poly", param_vals = list()) { - param_set = paradox::ps( - n_degree = paradox::p_int(lower = 1L, tags = c("train", "required")) - ) - param_set$set_values( - n_degree = 1L - ) - fn = mlr3misc::crate(function(x, n_degree) { - torch::torch_cat( - lapply(seq_len(n_degree), function(d) torch_pow(x, d)), - dim = 2L - ) - }) - - super$initialize( - fn = fn, - id = id, - packages = character(0), - param_vals = param_vals, - param_set = param_set, - stages_init = "both" - ) - } - ), - private = list( - .shapes_out = function(shapes_in, param_vals, task) { - # shapes_in is a list of length 1 containing the shapes - checkmate::assert_true(length(shapes_in[[1L]]) == 2L) - if (shapes_in[[1L]][2L] != 1L) { - stop("Input shape must be (NA, 1)") - } - list(c(NA, param_vals$n_degree)) - } - ) -) - -po_poly = PipeOpPreprocTorchPoly$new( - param_vals = list(n_degree = 3L, affect_columns = selector_name("x3")) -) - -po_poly$shapes_out(list(c(NA, 1L)), stage = "train") - -taskout = po_poly$train(list(taskin))[[1L]] -materialize(taskout$data(cols = "x3"), rbind = TRUE) -} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3pipelines:PipeOpTaskPreproc]{mlr3pipelines::PipeOpTaskPreproc}} -> \code{PipeOpTaskPreprocTorch} -} -\section{Active bindings}{ -\if{html}{\out{
}} -\describe{ -\item{\code{fn}}{The preprocessing function.} - -\item{\code{rowwise}}{Whether the preprocessing is applied rowwise.} -} -\if{html}{\out{
}} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTaskPreprocTorch-new}{\code{PipeOpTaskPreprocTorch$new()}} -\item \href{#method-PipeOpTaskPreprocTorch-shapes_out}{\code{PipeOpTaskPreprocTorch$shapes_out()}} -\item \href{#method-PipeOpTaskPreprocTorch-clone}{\code{PipeOpTaskPreprocTorch$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTaskPreprocTorch-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \code{\link[R6:R6Class]{R6}} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTaskPreprocTorch$new( - fn, - id = "preproc_torch", - param_vals = list(), - param_set = ps(), - packages = character(0), - rowwise = FALSE, - stages_init = NULL, - tags = NULL -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{fn}}{(\code{function} or \code{character(2)})\cr -The preprocessing function. Must not modify its input in-place. -If it is a \code{character(2)}, the first element should be the namespace and the second element the name.} - -\item{\code{id}}{(\code{character(1)})\cr -The id for of the new object.} - -\item{\code{param_vals}}{(named \code{list()})\cr -Parameter values to be set after construction.} - -\item{\code{param_set}}{(\code{\link{ParamSet}})\cr -In case the function \code{fn} takes additional parameter besides a \code{\link{torch_tensor}} they can be -specfied as parameters. None of the parameters can have the \code{"predict"} tag. -All tags should include \code{"train"}.} - -\item{\code{packages}}{(\code{character()})\cr -The packages the preprocessing function depends on.} - -\item{\code{rowwise}}{(\code{logical(1)})\cr -Whether the preprocessing function is applied rowwise (and then concatenated by row) or directly to the whole -tensor. In the first case there is no batch dimension.} - -\item{\code{stages_init}}{(\code{character(1)})\cr -Initial value for the \code{stages} parameter.} - -\item{\code{tags}}{(\code{character()})\cr -Tags for the pipeop.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTaskPreprocTorch-shapes_out}{}}} -\subsection{Method \code{shapes_out()}}{ -Calculates the output shapes that would result in applying the preprocessing to one or more -lazy tensor columns with the provided shape. -Names are ignored and only order matters. -It uses the parameter values that are currently set. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTaskPreprocTorch$shapes_out(shapes_in, stage = NULL, task = NULL)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{shapes_in}}{(\code{list()} of (\code{integer()} or \code{NULL}))\cr -The input input shapes of the lazy tensors. -\code{NULL} indicates that the shape is unknown. -First dimension must be \code{NA} (if it is not \code{NULL}).} - -\item{\code{stage}}{(\code{character(1)})\cr -The stage: either \code{"train"} or \code{"predict"}.} - -\item{\code{task}}{(\code{\link{Task}} or \code{NULL})\cr -The task, which is very rarely needed.} -} -\if{html}{\out{
}} -} -\subsection{Returns}{ -\code{list()} of (\code{integer()} or \code{NULL}) -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTaskPreprocTorch-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTaskPreprocTorch$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_torch.Rd b/man/mlr_pipeops_torch.Rd deleted file mode 100644 index efb5d3a3..00000000 --- a/man/mlr_pipeops_torch.Rd +++ /dev/null @@ -1,363 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorch.R -\name{mlr_pipeops_torch} -\alias{mlr_pipeops_torch} -\alias{PipeOpTorch} -\title{Base Class for Torch Module Constructor Wrappers} -\description{ -\code{PipeOpTorch} is the base class for all \code{\link{PipeOp}}s that represent neural network layers in a \code{\link{Graph}}. -During \strong{training}, it generates a \code{\link{PipeOpModule}} that wraps an \code{\link[torch:nn_module]{nn_module}} and attaches it -to the architecture, which is also represented as a \code{\link{Graph}} consisting mostly of \code{\link{PipeOpModule}}s -an \code{\link{PipeOpNOP}}s. - -While the former \code{\link{Graph}} operates on \code{\link{ModelDescriptor}}s, the latter operates on \link[=torch_tensor]{tensors}. - -The relationship between a \code{PipeOpTorch} and a \code{\link{PipeOpModule}} is similar to the -relationshop between a \code{nn_module_generator} (like \code{\link[torch:nn_linear]{nn_linear}}) and a -\code{\link[torch:nn_module]{nn_module}} (like the output of \code{nn_linear(...)}). -A crucial difference is that the \code{PipeOpTorch} infers auxiliary parameters (like \code{in_features} for -\code{nn_linear}) automatically from the intermediate tensor shapes that are being communicated through the -\code{\link{ModelDescriptor}}. - -During \strong{prediction}, \code{PipeOpTorch} takes in a \code{\link[mlr3:Task]{Task}} in each channel and outputs the same new -\code{\link[mlr3:Task]{Task}} resulting from their \link[=PipeOpFeatureUnion]{feature union} in each channel. -If there is only one input and output channel, the task is simply piped through. -} -\section{Inheriting}{ - -When inheriting from this class, one should overload either the \code{private$.shapes_out()} and the -\code{private$.shape_dependent_params()} methods, or overload \code{private$.make_module()}. -\itemize{ -\item \code{.make_module(shapes_in, param_vals, task)}\cr -(\code{list()}, \code{list()}) -> \code{nn_module}\cr -This private method is called to generated the \code{nn_module} that is passed as argument \code{module} to -\code{\link{PipeOpModule}}. It must be overwritten, when no \code{module_generator} is provided. -If left as is, it calls the provided \code{module_generator} with the arguments obtained by -the private method \code{.shape_dependent_params()}. -\item \code{.shapes_out(shapes_in, param_vals, task)}\cr -(\code{list()}, \code{list()}, \code{Task} or \code{NULL}) -> named \code{list()}\cr -This private method gets a list of \code{numeric} vectors (\code{shapes_in}), the parameter values (\code{param_vals}), -as well as an (optional) \code{\link{Task}}. -The \code{shapes_in} can be assumed to be in the same order as the input names of the \code{PipeOp}. -The output shapes must be in the same order as the output names of the \code{PipeOp}. -In case the output shapes depends on the task (as is the case for \code{\link{PipeOpTorchHead}}), the function should return -valid output shapes (possibly containing \code{NA}s) if the \code{task} argument is provided or not. -\item \code{.shape_dependent_params(shapes_in, param_vals, task)}\cr -(\code{list()}, \code{list()}) -> named \code{list()}\cr -This private method has the same inputs as \code{.shapes_out}. -If \code{.make_module()} is not overwritten, it constructs the arguments passed to \code{module_generator}. -Usually this means that it must infer the auxiliary parameters that can be inferred from the input shapes -and add it to the user-supplied parameter values (\code{param_vals}). -} -} - -\section{Input and Output Channels}{ - -During \emph{training}, all inputs and outputs are of class \code{\link{ModelDescriptor}}. -During \emph{prediction}, all input and output channels are of class \code{\link{Task}}. -} - -\section{State}{ - -The state is the value calculated by the public method \code{shapes_out()}. -} - -\section{Parameters}{ - -The \code{\link[paradox:ParamSet]{ParamSet}} is specified by the child class inheriting from \code{\link{PipeOpTorch}}. -Usually the parameters are the arguments of the wrapped \code{\link{nn_module}} minus the auxiliary parameter that can -be automatically inferred from the shapes of the input tensors. -} - -\section{Internals}{ - -During training, the \code{PipeOpTorch} creates a \code{\link{PipeOpModule}} for the given parameter specification and the -input shapes from the incoming \href{s}{\code{ModelDescriptor}} using the private method \code{.make_module()}. -The input shapes are provided by the slot \code{pointer_shape} of the incoming \code{\link{ModelDescriptor}}s. -The channel names of this \code{\link{PipeOpModule}} are identical to the channel names of the generating \code{\link{PipeOpTorch}}. - -A \link[=model_descriptor_union]{model descriptor union} of all incoming \code{\link{ModelDescriptor}}s is then created. -Note that this modifies the \code{\link[=Graph]{graph}} of the first \code{\link{ModelDescriptor}} \strong{in place} for efficiency. -The \code{\link{PipeOpModule}} is added to the \code{\link[=Graph]{graph}} slot of this union and the the edges that connect the -sending \code{PipeOpModule}s to the input channel of this \code{PipeOpModule} are addeded to the graph. -This is possible because every incoming \code{\link{ModelDescriptor}} contains the information about the -\code{id} and the \code{channel} name of the sending \code{PipeOp} in the slot \code{pointer}. - -The new graph in the \code{\link{model_descriptor_union}} represents the current state of the neural network -architecture. It is structurally similar to the subgraph that consists of all pipeops of class \code{PipeOpTorch} and -\code{\link{PipeOpTorchIngress}} that are ancestors of this \code{PipeOpTorch}. - -For the output, a shallow copy of the \code{\link{ModelDescriptor}} is created and the \code{pointer} and -\code{pointer_shape} are updated accordingly. The shallow copy means that all \code{\link{ModelDescriptor}}s point to the same -\code{\link{Graph}} which allows the graph to be modified by-reference in different parts of the code. -} - -\examples{ -## Creating a neural network -# In torch - -task = tsk("iris") - -network_generator = torch::nn_module( - initialize = function(task, d_hidden) { - d_in = length(task$feature_names) - self$linear = torch::nn_linear(d_in, d_hidden) - self$output = if (task$task_type == "regr") { - torch::nn_linear(d_hidden, 1) - } else if (task$task_type == "classif") { - torch::nn_linear(d_hidden, length(task$class_names)) - } - }, - forward = function(x) { - x = self$linear(x) - x = torch::nnf_relu(x) - self$output(x) - } -) - -network = network_generator(task, d_hidden = 50) -x = torch::torch_tensor(as.matrix(task$data(1, task$feature_names))) -y = torch::with_no_grad(network(x)) - - -# In mlr3torch -network_generator = po("torch_ingress_num") \%>>\% - po("nn_linear", out_features = 50) \%>>\% - po("nn_head") -md = network_generator$train(task)[[1L]] -network = model_descriptor_to_module(md) -y = torch::with_no_grad(network(torch_ingress_num.input = x)) - - - -## Implementing a custom PipeOpTorch - -# defining a custom module -nn_custom = nn_module("nn_custom", - initialize = function(d_in1, d_in2, d_out1, d_out2, bias = TRUE) { - self$linear1 = nn_linear(d_in1, d_out1, bias) - self$linear2 = nn_linear(d_in2, d_out2, bias) - }, - forward = function(input1, input2) { - output1 = self$linear1(input1) - output2 = self$linear1(input2) - - list(output1 = output1, output2 = output2) - } -) - -# wrapping the module into a custom PipeOpTorch - -library(paradox) - -PipeOpTorchCustom = R6::R6Class("PipeOpTorchCustom", - inherit = PipeOpTorch, - public = list( - initialize = function(id = "nn_custom", param_vals = list()) { - param_set = ps( - d_out1 = p_int(lower = 1, tags = c("required", "train")), - d_out2 = p_int(lower = 1, tags = c("required", "train")), - bias = p_lgl(default = TRUE, tags = "train") - ) - super$initialize( - id = id, - param_vals = param_vals, - param_set = param_set, - inname = c("input1", "input2"), - outname = c("output1", "output2"), - module_generator = nn_custom - ) - } - ), - private = list( - .shape_dependent_params = function(shapes_in, param_vals, task) { - c(param_vals, - list(d_in1 = tail(shapes_in[["input1"]], 1)), d_in2 = tail(shapes_in[["input2"]], 1) - ) - }, - .shapes_out = function(shapes_in, param_vals, task) { - list( - input1 = c(head(shapes_in[["input1"]], -1), param_vals$d_out1), - input2 = c(head(shapes_in[["input2"]], -1), param_vals$d_out2) - ) - } - ) -) - -## Training - -# generate input -task = tsk("iris") -task1 = task$clone()$select(paste0("Sepal.", c("Length", "Width"))) -task2 = task$clone()$select(paste0("Petal.", c("Length", "Width"))) -graph = gunion(list(po("torch_ingress_num_1"), po("torch_ingress_num_2"))) -mds_in = graph$train(list(task1, task2), single_input = FALSE) - -mds_in[[1L]][c("graph", "task", "ingress", "pointer", "pointer_shape")] -mds_in[[2L]][c("graph", "task", "ingress", "pointer", "pointer_shape")] - -# creating the PipeOpTorch and training it -po_torch = PipeOpTorchCustom$new() -po_torch$param_set$values = list(d_out1 = 10, d_out2 = 20) -train_input = list(input1 = mds_in[[1L]], input2 = mds_in[[2L]]) -mds_out = do.call(po_torch$train, args = list(input = train_input)) -po_torch$state - -# the new model descriptors - -# the resulting graphs are identical -identical(mds_out[[1L]]$graph, mds_out[[2L]]$graph) -# not that as a side-effect, also one of the input graphs is modified in-place for efficiency -mds_in[[1L]]$graph$edges - -# The new task has both Sepal and Petal features -identical(mds_out[[1L]]$task, mds_out[[2L]]$task) -mds_out[[2L]]$task - -# The new ingress slot contains all ingressors -identical(mds_out[[1L]]$ingress, mds_out[[2L]]$ingress) -mds_out[[1L]]$ingress - -# The pointer and pointer_shape slots are different -mds_out[[1L]]$pointer -mds_out[[2L]]$pointer - -mds_out[[1L]]$pointer_shape -mds_out[[2L]]$pointer_shape - -## Prediction -predict_input = list(input1 = task1, input2 = task2) -tasks_out = do.call(po_torch$predict, args = list(input = predict_input)) -identical(tasks_out[[1L]], tasks_out[[2L]]) -} -\seealso{ -Other Graph Network: -\code{\link{ModelDescriptor}()}, -\code{\link{TorchIngressToken}()}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{model_descriptor_to_learner}()}, -\code{\link{model_descriptor_to_module}()}, -\code{\link{model_descriptor_union}()}, -\code{\link{nn_graph}()} -} -\concept{Graph Network} -\section{Super class}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{PipeOpTorch} -} -\section{Public fields}{ -\if{html}{\out{
}} -\describe{ -\item{\code{module_generator}}{(\code{nn_module_generator} or \code{NULL})\cr -The module generator wrapped by this \code{PipeOpTorch}. If \code{NULL}, the private method -\code{private$.make_module(shapes_in, param_vals)} must be overwritte, see section 'Inheriting'. -Do not change this after construction.} -} -\if{html}{\out{
}} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorch-new}{\code{PipeOpTorch$new()}} -\item \href{#method-PipeOpTorch-shapes_out}{\code{PipeOpTorch$shapes_out()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorch-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorch$new( - id, - module_generator, - param_set = ps(), - param_vals = list(), - inname = "input", - outname = "output", - packages = "torch", - tags = NULL -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{module_generator}}{(\code{nn_module_generator})\cr -The torch module generator.} - -\item{\code{param_set}}{(\code{paradox::ParamSet})\cr -The parameter set.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} - -\item{\code{inname}}{(\code{character()})\cr -The names of the \code{\link{PipeOp}}'s input channels. These will be the input channels of the generated \code{\link{PipeOpModule}}. -Unless the wrapped \code{module_generator}'s forward method (if present) has the argument \code{...}, \code{inname} must be -identical to those argument names in order to avoid any ambiguity.\cr -If the forward method has the argument \code{...}, the order of the input channels determines how the tensors -will be passed to the wrapped \code{nn_module}.\cr -If left as \code{NULL} (default), the argument \code{module_generator} must be given and the argument names of the -\code{modue_generator}'s forward function are set as \code{inname}.} - -\item{\code{outname}}{(\code{character()}) \cr -The names of the output channels channels. These will be the ouput channels of the generated \code{\link{PipeOpModule}} -and therefore also the names of the list returned by its \verb{$train()}. -In case there is more than one output channel, the \code{nn_module} that is constructed by this -\code{\link{PipeOp}} during training must return a named \code{list()}, where the names of the list are the -names out the output channels. The default is \code{"output"}.} - -\item{\code{packages}}{(\code{character()})\cr -The R packages this object depends on.} - -\item{\code{tags}}{(\code{character()})\cr -The tags of the \code{\link{PipeOp}}. The tags \code{"torch"} is always added.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorch-shapes_out}{}}} -\subsection{Method \code{shapes_out()}}{ -Calculates the output shapes for the given input shapes, parameters and task. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorch$shapes_out(shapes_in, task = NULL)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{shapes_in}}{(\code{list()} of \code{integer()})\cr -The input input shapes, which must be in the same order as the input channel names of the \code{PipeOp}.} - -\item{\code{task}}{(\code{\link{Task}} or \code{NULL})\cr -The task, which is very rarely used (default is \code{NULL}). An exception is \code{\link{PipeOpTorchHead}}.} -} -\if{html}{\out{
}} -} -\subsection{Returns}{ -A named \code{list()} containing the output shapes. The names are the names of the output channels of -the \code{PipeOp}. -} -} -} diff --git a/man/mlr_pipeops_torch_callbacks.Rd b/man/mlr_pipeops_torch_callbacks.Rd deleted file mode 100644 index 1c4e2b23..00000000 --- a/man/mlr_pipeops_torch_callbacks.Rd +++ /dev/null @@ -1,126 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchCallbacks.R -\name{mlr_pipeops_torch_callbacks} -\alias{mlr_pipeops_torch_callbacks} -\alias{PipeOpTorchCallbacks} -\title{Callback Configuration} -\description{ -Configures the callbacks of a deep learning model. -} -\section{Input and Output Channels}{ - -There is one input channel \code{"input"} and one output channel \code{"output"}. -During \emph{training}, the channels are of class \code{\link{ModelDescriptor}}. -During \emph{prediction}, the channels are of class \code{\link{Task}}. -} - -\section{State}{ - -The state is the value calculated by the public method \code{shapes_out()}. -} - -\section{Parameters}{ - -The parameters are defined dynamically from the callbacks, where the id of the respective callbacks is the -respective set id. -} - -\section{Internals}{ - -During training the callbacks are cloned and added to the \code{\link{ModelDescriptor}}. -} - -\examples{ -po_cb = po("torch_callbacks", "checkpoint") -po_cb$param_set -mdin = po("torch_ingress_num")$train(list(tsk("iris"))) -mdin[[1L]]$callbacks -mdout = po_cb$train(mdin)[[1L]] -mdout$callbacks -# Can be called again -po_cb1 = po("torch_callbacks", t_clbk("progress")) -mdout1 = po_cb1$train(list(mdout))[[1L]] -mdout1$callbacks -} -\seealso{ -Other Model Configuration: -\code{\link{ModelDescriptor}()}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_optimizer}}, -\code{\link{model_descriptor_union}()} - -Other PipeOp: -\code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch_optimizer}} -} -\concept{Model Configuration} -\concept{PipeOp} -\section{Super class}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{PipeOpTorchCallbacks} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchCallbacks-new}{\code{PipeOpTorchCallbacks$new()}} -\item \href{#method-PipeOpTorchCallbacks-clone}{\code{PipeOpTorchCallbacks$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchCallbacks-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchCallbacks$new( - callbacks = list(), - id = "torch_callbacks", - param_vals = list() -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{callbacks}}{(\code{list} of \code{\link{TorchCallback}}s) \cr -The callbacks (or something convertible via \code{\link[=as_torch_callbacks]{as_torch_callbacks()}}). -Must have unique ids. -All callbacks are cloned during construction.} - -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchCallbacks-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchCallbacks$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_torch_ingress.Rd b/man/mlr_pipeops_torch_ingress.Rd deleted file mode 100644 index 583ec51f..00000000 --- a/man/mlr_pipeops_torch_ingress.Rd +++ /dev/null @@ -1,192 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchIngress.R -\name{mlr_pipeops_torch_ingress} -\alias{mlr_pipeops_torch_ingress} -\alias{PipeOpTorchIngress} -\title{Entrypoint to Torch Network} -\description{ -Use this as entry-point to mlr3torch-networks. -Unless you are an advanced user, you should not need to use this directly but \code{\link{PipeOpTorchIngressNumeric}}, -\code{\link{PipeOpTorchIngressCategorical}} or \code{\link{PipeOpTorchIngressLazyTensor}}. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is set to the input shape. -} - -\section{Parameters}{ - -Defined by the construction argument \code{param_set}. -} - -\section{Internals}{ - -Creates an object of class \code{\link{TorchIngressToken}} for the given task. -The purpuse of this is to store the information on how to construct the torch dataloader from the task for this -entry point of the network. -} - -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} - -Other Graph Network: -\code{\link{ModelDescriptor}()}, -\code{\link{TorchIngressToken}()}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{model_descriptor_to_learner}()}, -\code{\link{model_descriptor_to_module}()}, -\code{\link{model_descriptor_union}()}, -\code{\link{nn_graph}()} -} -\concept{Graph Network} -\concept{PipeOps} -\section{Super class}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{PipeOpTorchIngress} -} -\section{Active bindings}{ -\if{html}{\out{
}} -\describe{ -\item{\code{feature_types}}{(\code{character(1)})\cr -The features types that can be consumed by this \code{PipeOpTorchIngress}.} -} -\if{html}{\out{
}} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchIngress-new}{\code{PipeOpTorchIngress$new()}} -\item \href{#method-PipeOpTorchIngress-clone}{\code{PipeOpTorchIngress$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchIngress-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchIngress$new( - id, - param_set = ps(), - param_vals = list(), - packages = character(0), - feature_types -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_set}}{(\code{paradox::ParamSet})\cr -The parameter set.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} - -\item{\code{packages}}{(\code{character()})\cr -The R packages this object depends on.} - -\item{\code{feature_types}}{(\code{character()})\cr -The feature types. -See \code{\link[=mlr_reflections]{mlr_reflections$task_feature_types}} for available values.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchIngress-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchIngress$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_torch_ingress_categ.Rd b/man/mlr_pipeops_torch_ingress_categ.Rd deleted file mode 100644 index be3d2f98..00000000 --- a/man/mlr_pipeops_torch_ingress_categ.Rd +++ /dev/null @@ -1,180 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchIngress.R -\name{mlr_pipeops_torch_ingress_categ} -\alias{mlr_pipeops_torch_ingress_categ} -\alias{PipeOpTorchIngressCategorical} -\title{Torch Entry Point for Categorical Features} -\description{ -Ingress PipeOp that represents a categorical (\code{factor()}, \code{ordered()} and \code{logical()}) entry point to a torch network. -} -\section{Parameters}{ - -\itemize{ -\item \code{select} :: \code{logical(1)}\cr -Whether \code{PipeOp} should selected the supported feature types. Otherwise it will err on receiving tasks -with unsupported feature types. -} -} - -\section{Internals}{ - -Uses \code{\link[=batchgetter_categ]{batchgetter_categ()}}. -} - -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is set to the input shape. -} - -\examples{ -graph = po("select", selector = selector_type("factor")) \%>>\% - po("torch_ingress_categ") -task = tsk("german_credit") -# The output is a model descriptor -md = graph$train(task)[[1L]] -ingress = md$ingress[[1L]] -ingress$batchgetter(task$data(1, ingress$features), "cpu") -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} - -Other Graph Network: -\code{\link{ModelDescriptor}()}, -\code{\link{TorchIngressToken}()}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{model_descriptor_to_learner}()}, -\code{\link{model_descriptor_to_module}()}, -\code{\link{model_descriptor_union}()}, -\code{\link{nn_graph}()} -} -\concept{Graph Network} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorchIngress]{mlr3torch::PipeOpTorchIngress}} -> \code{PipeOpTorchIngressCategorical} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchIngressCategorical-new}{\code{PipeOpTorchIngressCategorical$new()}} -\item \href{#method-PipeOpTorchIngressCategorical-clone}{\code{PipeOpTorchIngressCategorical$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchIngressCategorical-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchIngressCategorical$new( - id = "torch_ingress_categ", - param_vals = list() -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchIngressCategorical-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchIngressCategorical$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_torch_ingress_ltnsr.Rd b/man/mlr_pipeops_torch_ingress_ltnsr.Rd deleted file mode 100644 index 514f1c20..00000000 --- a/man/mlr_pipeops_torch_ingress_ltnsr.Rd +++ /dev/null @@ -1,215 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchIngress.R -\name{mlr_pipeops_torch_ingress_ltnsr} -\alias{mlr_pipeops_torch_ingress_ltnsr} -\alias{PipeOpTorchIngressLazyTensor} -\title{Ingress for Lazy Tensor} -\description{ -Ingress for a single \code{\link{lazy_tensor}} column. -} -\section{Parameters}{ - -\itemize{ -\item \code{shape} :: \code{integer()}\cr -The shape of the tensor, where the first dimension (batch) must be \code{NA}. -When it is not specified, the lazy tensor input column needs to have a known shape. -} -} - -\section{Internals}{ - -The returned batchgetter materializes the lazy tensor column to a tensor. -} - -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is set to the input shape. -} - -\examples{ -po_ingress = po("torch_ingress_ltnsr") -task = tsk("lazy_iris") - -md = po_ingress$train(list(task))[[1L]] - -ingress = md$ingress -x_batch = ingress[[1L]]$batchgetter(data = task$data(1, "x"), device = "cpu", cache = NULL) -x_batch - -# Now we try a lazy tensor with unknown shape, i.e. the shapes between the rows can differ - -ds = dataset( - initialize = function() self$x = list(torch_randn(3, 10, 10), torch_randn(3, 8, 8)), - .getitem = function(i) list(x = self$x[[i]]), - .length = function() 2)() - -task_unknown = as_task_regr(data.table( - x = as_lazy_tensor(ds, dataset_shapes = list(x = NULL)), - y = rnorm(2) -), target = "y", id = "example2") - -# this task (as it is) can NOT be processed by PipeOpTorchIngressLazyTensor -# It therefore needs to be preprocessed -po_resize = po("trafo_resize", size = c(6, 6)) -task_unknown_resize = po_resize$train(list(task_unknown))[[1L]] - -# printing the transformed column still shows unknown shapes, -# because the preprocessing pipeop cannot infer them, -# however we know that the shape is now (3, 10, 10) for all rows -task_unknown_resize$data(1:2, "x") -po_ingress$param_set$set_values(shape = c(NA, 3, 6, 6)) - -md2 = po_ingress$train(list(task_unknown_resize))[[1L]] - -ingress2 = md2$ingress -x_batch2 = ingress2[[1L]]$batchgetter( - data = task_unknown_resize$data(1:2, "x"), - device = "cpu", - cache = NULL -) - -x_batch2 -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} - -Other Graph Network: -\code{\link{ModelDescriptor}()}, -\code{\link{TorchIngressToken}()}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{model_descriptor_to_learner}()}, -\code{\link{model_descriptor_to_module}()}, -\code{\link{model_descriptor_union}()}, -\code{\link{nn_graph}()} -} -\concept{Graph Network} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorchIngress]{mlr3torch::PipeOpTorchIngress}} -> \code{PipeOpTorchIngressLazyTensor} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchIngressLazyTensor-new}{\code{PipeOpTorchIngressLazyTensor$new()}} -\item \href{#method-PipeOpTorchIngressLazyTensor-clone}{\code{PipeOpTorchIngressLazyTensor$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchIngressLazyTensor-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchIngressLazyTensor$new( - id = "torch_ingress_ltnsr", - param_vals = list() -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchIngressLazyTensor-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchIngressLazyTensor$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_torch_ingress_num.Rd b/man/mlr_pipeops_torch_ingress_num.Rd deleted file mode 100644 index 080d724e..00000000 --- a/man/mlr_pipeops_torch_ingress_num.Rd +++ /dev/null @@ -1,168 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchIngress.R -\name{mlr_pipeops_torch_ingress_num} -\alias{mlr_pipeops_torch_ingress_num} -\alias{PipeOpTorchIngressNumeric} -\title{Torch Entry Point for Numeric Features} -\description{ -Ingress PipeOp that represents a numeric (\code{integer()} and \code{numeric()}) entry point to a torch network. -} -\section{Internals}{ - -Uses \code{\link[=batchgetter_num]{batchgetter_num()}}. -} - -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is set to the input shape. -} - -\examples{ -graph = po("select", selector = selector_type(c("numeric", "integer"))) \%>>\% - po("torch_ingress_num") -task = tsk("german_credit") -# The output is a model descriptor -md = graph$train(task)[[1L]] -ingress = md$ingress[[1L]] -ingress$batchgetter(task$data(1:5, ingress$features), "cpu") -} -\seealso{ -Other Graph Network: -\code{\link{ModelDescriptor}()}, -\code{\link{TorchIngressToken}()}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{model_descriptor_to_learner}()}, -\code{\link{model_descriptor_to_module}()}, -\code{\link{model_descriptor_union}()}, -\code{\link{nn_graph}()} - -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{Graph Network} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorchIngress]{mlr3torch::PipeOpTorchIngress}} -> \code{PipeOpTorchIngressNumeric} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchIngressNumeric-new}{\code{PipeOpTorchIngressNumeric$new()}} -\item \href{#method-PipeOpTorchIngressNumeric-clone}{\code{PipeOpTorchIngressNumeric$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchIngressNumeric-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchIngressNumeric$new(id = "torch_ingress_num", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchIngressNumeric-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchIngressNumeric$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_torch_loss.Rd b/man/mlr_pipeops_torch_loss.Rd deleted file mode 100644 index fd953769..00000000 --- a/man/mlr_pipeops_torch_loss.Rd +++ /dev/null @@ -1,167 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchLoss.R -\name{mlr_pipeops_torch_loss} -\alias{mlr_pipeops_torch_loss} -\alias{PipeOpTorchLoss} -\title{Loss Configuration} -\description{ -Configures the loss of a deep learning model. -} -\section{Input and Output Channels}{ - -One input channel called \code{"input"} and one output channel called \code{"output"}. -For an explanation see \code{\link{PipeOpTorch}}. -} - -\section{State}{ - -The state is the value calculated by the public method \code{shapes_out()}. -} - -\section{Parameters}{ - -The parameters are defined dynamically from the loss set during construction. -} - -\section{Internals}{ - -During training the loss is cloned and added to the \code{\link{ModelDescriptor}}. -} - -\examples{ -po_loss = po("torch_loss", loss = t_loss("cross_entropy")) -po_loss$param_set -mdin = po("torch_ingress_num")$train(list(tsk("iris"))) -mdin[[1L]]$loss -mdout = po_loss$train(mdin)[[1L]] -mdout$loss -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} - -Other Model Configuration: -\code{\link{ModelDescriptor}()}, -\code{\link{mlr_pipeops_torch_callbacks}}, -\code{\link{mlr_pipeops_torch_optimizer}}, -\code{\link{model_descriptor_union}()} -} -\concept{Model Configuration} -\concept{PipeOps} -\section{Super class}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{PipeOpTorchLoss} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchLoss-new}{\code{PipeOpTorchLoss$new()}} -\item \href{#method-PipeOpTorchLoss-clone}{\code{PipeOpTorchLoss$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchLoss-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchLoss$new(loss, id = "torch_loss", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{loss}}{(\code{\link{TorchLoss}} or \code{character(1)} or \code{nn_loss})\cr -The loss (or something convertible via \code{\link[=as_torch_loss]{as_torch_loss()}}).} - -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchLoss-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchLoss$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_torch_model.Rd b/man/mlr_pipeops_torch_model.Rd deleted file mode 100644 index 818b558d..00000000 --- a/man/mlr_pipeops_torch_model.Rd +++ /dev/null @@ -1,185 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchModel.R -\name{mlr_pipeops_torch_model} -\alias{mlr_pipeops_torch_model} -\alias{PipeOpTorchModel} -\title{PipeOp Torch Model} -\description{ -Builds a Torch Learner from a \code{\link{ModelDescriptor}} and trains it with the given parameter specification. -The task type must be specified during construction. -} -\section{Input and Output Channels}{ - -There is one input channel \code{"input"} that takes in \code{ModelDescriptor} during traing and a \code{Task} of the specified -\code{task_type} during prediction. -The output is \code{NULL} during training and a \code{Prediction} of given \code{task_type} during prediction. -} - -\section{State}{ - -A trained \code{\link{LearnerTorchModel}}. -} - -\section{Parameters}{ - -\itemize{ -\item \code{batch_size} :: (\code{integer(1)})\cr -The batch size. -\item \code{epochs} :: \code{integer(1)}\cr -The number of epochs. -\item \code{device} :: \code{character(1)}\cr -The device. One of \code{"auto"}, \code{"cpu"}, or \code{"cuda"} or other values defined in \code{mlr_reflections$torch$devices}. -The value is initialized to \code{"auto"}, which will select \code{"cuda"} if possible, then try \code{"mps"} and otherwise -fall back to \code{"cpu"}. -\item \code{measures_train} :: \code{\link{Measure}} or \code{list()} of \code{\link{Measure}}s. -Measures to be evaluated during training. -\item \code{measures_valid} :: \code{\link{Measure}} or \code{list()} of \code{\link{Measure}}s. -Measures to be evaluated during validation. -\item \code{num_threads} :: \code{integer(1)}\cr -The number of threads for intraop pararallelization (if \code{device} is \code{"cpu"}). -This value is initialized to 1. -\item \code{shuffle} :: \code{logical(1)}\cr -Whether to shuffle the instances in the dataset. This value is initialized to \code{TRUE}. -\item \code{seed} :: \code{integer(1)} or \code{"random"}\cr -The seed that is used during training and prediction. -This value is initialized to \code{"random"}, which means that a random seed will be sampled at the beginning of the -training phase. This seed (either set or randomly sampled) is available via \verb{$model$seed} after training -and used during prediction. -Note that by setting the seed during the training phase this will mean that by default (i.e. when \code{seed} is -\code{"random"}), clones of the learner will use a different seed. -} - -Additionally there are the parameters for the optimizer, the loss function and the callbacks. -They are prefixed with \code{"opt."}, \code{"loss."} and \code{"cb.."} respectively. -} - -\section{Internals}{ - -A \code{\link{LearnerTorchModel}} is created by calling \code{\link[=model_descriptor_to_learner]{model_descriptor_to_learner()}} on the -provided \code{\link{ModelDescriptor}} that is received through the input channel. -Then the parameters are set according to the parameters specified in \code{PipeOpTorchModel} and -its '$train()\verb{ method is called on the [}Task\verb{] stored in the [}ModelDescriptor`]. -} - -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model_classif}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super class}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{PipeOpTorchModel} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchModel-new}{\code{PipeOpTorchModel$new()}} -\item \href{#method-PipeOpTorchModel-clone}{\code{PipeOpTorchModel$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchModel-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchModel$new(task_type, id = "torch_model", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{task_type}}{(\code{character(1)})\cr -The task type of the model.} - -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchModel-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchModel$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_torch_model_classif.Rd b/man/mlr_pipeops_torch_model_classif.Rd deleted file mode 100644 index 4d06225c..00000000 --- a/man/mlr_pipeops_torch_model_classif.Rd +++ /dev/null @@ -1,168 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchModel.R -\name{mlr_pipeops_torch_model_classif} -\alias{mlr_pipeops_torch_model_classif} -\alias{PipeOpTorchModelClassif} -\title{PipeOp Torch Classifier} -\description{ -Builds a torch classifier and trains it. -} -\section{Parameters}{ - See \code{\link{LearnerTorch}} -} - -\section{Input and Output Channels}{ - -There is one input channel \code{"input"} that takes in \code{ModelDescriptor} during traing and a \code{Task} of the specified -\code{task_type} during prediction. -The output is \code{NULL} during training and a \code{Prediction} of given \code{task_type} during prediction. -} - -\section{State}{ - -A trained \code{\link{LearnerTorchModel}}. -} - -\section{Internals}{ - -A \code{\link{LearnerTorchModel}} is created by calling \code{\link[=model_descriptor_to_learner]{model_descriptor_to_learner()}} on the -provided \code{\link{ModelDescriptor}} that is received through the input channel. -Then the parameters are set according to the parameters specified in \code{PipeOpTorchModel} and -its '$train()\verb{ method is called on the [}Task\verb{] stored in the [}ModelDescriptor`]. -} - -\examples{ -# simple logistic regression - -# configure the model descriptor -md = as_graph(po("torch_ingress_num") \%>>\% - po("nn_head") \%>>\% - po("torch_loss", "cross_entropy") \%>>\% - po("torch_optimizer", "adam"))$train(tsk("iris"))[[1L]] - -print(md) - -# build the learner from the model descriptor and train it -po_model = po("torch_model_classif", batch_size = 50, epochs = 1) -po_model$train(list(md)) -po_model$state -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_regr}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorchModel]{mlr3torch::PipeOpTorchModel}} -> \code{PipeOpTorchModelClassif} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchModelClassif-new}{\code{PipeOpTorchModelClassif$new()}} -\item \href{#method-PipeOpTorchModelClassif-clone}{\code{PipeOpTorchModelClassif$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchModelClassif-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchModelClassif$new(id = "torch_model_classif", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchModelClassif-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchModelClassif$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_torch_model_regr.Rd b/man/mlr_pipeops_torch_model_regr.Rd deleted file mode 100644 index bd440fd5..00000000 --- a/man/mlr_pipeops_torch_model_regr.Rd +++ /dev/null @@ -1,168 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchModel.R -\name{mlr_pipeops_torch_model_regr} -\alias{mlr_pipeops_torch_model_regr} -\alias{PipeOpTorchModelRegr} -\title{Torch Regression Model} -\description{ -Builds a torch regression model and trains it. -} -\section{Parameters}{ - See \code{\link{LearnerTorch}} -} - -\section{Input and Output Channels}{ - -There is one input channel \code{"input"} that takes in \code{ModelDescriptor} during traing and a \code{Task} of the specified -\code{task_type} during prediction. -The output is \code{NULL} during training and a \code{Prediction} of given \code{task_type} during prediction. -} - -\section{State}{ - -A trained \code{\link{LearnerTorchModel}}. -} - -\section{Internals}{ - -A \code{\link{LearnerTorchModel}} is created by calling \code{\link[=model_descriptor_to_learner]{model_descriptor_to_learner()}} on the -provided \code{\link{ModelDescriptor}} that is received through the input channel. -Then the parameters are set according to the parameters specified in \code{PipeOpTorchModel} and -its '$train()\verb{ method is called on the [}Task\verb{] stored in the [}ModelDescriptor`]. -} - -\examples{ -# simple linear regression - -# build the model descriptor -md = as_graph(po("torch_ingress_num") \%>>\% - po("nn_head") \%>>\% - po("torch_loss", "mse") \%>>\% - po("torch_optimizer", "adam"))$train(tsk("mtcars"))[[1L]] - -print(md) - -# build the learner from the model descriptor and train it -po_model = po("torch_model_regr", batch_size = 20, epochs = 1) -po_model$train(list(md)) -po_model$state -} -\seealso{ -Other PipeOps: -\code{\link{mlr_pipeops_nn_avg_pool1d}}, -\code{\link{mlr_pipeops_nn_avg_pool2d}}, -\code{\link{mlr_pipeops_nn_avg_pool3d}}, -\code{\link{mlr_pipeops_nn_batch_norm1d}}, -\code{\link{mlr_pipeops_nn_batch_norm2d}}, -\code{\link{mlr_pipeops_nn_batch_norm3d}}, -\code{\link{mlr_pipeops_nn_celu}}, -\code{\link{mlr_pipeops_nn_conv1d}}, -\code{\link{mlr_pipeops_nn_conv2d}}, -\code{\link{mlr_pipeops_nn_conv3d}}, -\code{\link{mlr_pipeops_nn_conv_transpose1d}}, -\code{\link{mlr_pipeops_nn_conv_transpose2d}}, -\code{\link{mlr_pipeops_nn_conv_transpose3d}}, -\code{\link{mlr_pipeops_nn_dropout}}, -\code{\link{mlr_pipeops_nn_elu}}, -\code{\link{mlr_pipeops_nn_flatten}}, -\code{\link{mlr_pipeops_nn_gelu}}, -\code{\link{mlr_pipeops_nn_glu}}, -\code{\link{mlr_pipeops_nn_hardshrink}}, -\code{\link{mlr_pipeops_nn_hardsigmoid}}, -\code{\link{mlr_pipeops_nn_hardtanh}}, -\code{\link{mlr_pipeops_nn_head}}, -\code{\link{mlr_pipeops_nn_layer_norm}}, -\code{\link{mlr_pipeops_nn_leaky_relu}}, -\code{\link{mlr_pipeops_nn_linear}}, -\code{\link{mlr_pipeops_nn_log_sigmoid}}, -\code{\link{mlr_pipeops_nn_max_pool1d}}, -\code{\link{mlr_pipeops_nn_max_pool2d}}, -\code{\link{mlr_pipeops_nn_max_pool3d}}, -\code{\link{mlr_pipeops_nn_merge}}, -\code{\link{mlr_pipeops_nn_merge_cat}}, -\code{\link{mlr_pipeops_nn_merge_prod}}, -\code{\link{mlr_pipeops_nn_merge_sum}}, -\code{\link{mlr_pipeops_nn_prelu}}, -\code{\link{mlr_pipeops_nn_relu}}, -\code{\link{mlr_pipeops_nn_relu6}}, -\code{\link{mlr_pipeops_nn_reshape}}, -\code{\link{mlr_pipeops_nn_rrelu}}, -\code{\link{mlr_pipeops_nn_selu}}, -\code{\link{mlr_pipeops_nn_sigmoid}}, -\code{\link{mlr_pipeops_nn_softmax}}, -\code{\link{mlr_pipeops_nn_softplus}}, -\code{\link{mlr_pipeops_nn_softshrink}}, -\code{\link{mlr_pipeops_nn_softsign}}, -\code{\link{mlr_pipeops_nn_squeeze}}, -\code{\link{mlr_pipeops_nn_tanh}}, -\code{\link{mlr_pipeops_nn_tanhshrink}}, -\code{\link{mlr_pipeops_nn_threshold}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_model}}, -\code{\link{mlr_pipeops_torch_model_classif}} -} -\concept{PipeOps} -\section{Super classes}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3torch:PipeOpTorchModel]{mlr3torch::PipeOpTorchModel}} -> \code{PipeOpTorchModelRegr} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchModelRegr-new}{\code{PipeOpTorchModelRegr$new()}} -\item \href{#method-PipeOpTorchModelRegr-clone}{\code{PipeOpTorchModelRegr$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchModelRegr-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchModelRegr$new(id = "torch_model_regr", param_vals = list())}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchModelRegr-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchModelRegr$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_pipeops_torch_optimizer.Rd b/man/mlr_pipeops_torch_optimizer.Rd deleted file mode 100644 index 673f7692..00000000 --- a/man/mlr_pipeops_torch_optimizer.Rd +++ /dev/null @@ -1,121 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchOptimizer.R -\name{mlr_pipeops_torch_optimizer} -\alias{mlr_pipeops_torch_optimizer} -\alias{PipeOpTorchOptimizer} -\title{Optimizer Configuration} -\description{ -Configures the optimizer of a deep learning model. -} -\section{Input and Output Channels}{ - -There is one input channel \code{"input"} and one output channel \code{"output"}. -During \emph{training}, the channels are of class \code{\link{ModelDescriptor}}. -During \emph{prediction}, the channels are of class \code{\link{Task}}. -} - -\section{State}{ - -The state is the value calculated by the public method \code{shapes_out()}. -} - -\section{Parameters}{ - -The parameters are defined dynamically from the optimizer that is set during construction. -} - -\section{Internals}{ - -During training, the optimizer is cloned and added to the \code{\link{ModelDescriptor}}. -Note that the parameter set of the stored \code{\link{TorchOptimizer}} is reference-identical to the parameter set of the -pipeop itself. -} - -\examples{ -po_opt = po("torch_optimizer", "sgd", lr = 0.01) -po_opt$param_set -mdin = po("torch_ingress_num")$train(list(tsk("iris"))) -mdin[[1L]]$optimizer -mdout = po_opt$train(mdin) -mdout[[1L]]$optimizer -} -\seealso{ -Other PipeOp: -\code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch_callbacks}} - -Other Model Configuration: -\code{\link{ModelDescriptor}()}, -\code{\link{mlr_pipeops_torch_callbacks}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{model_descriptor_union}()} -} -\concept{Model Configuration} -\concept{PipeOp} -\section{Super class}{ -\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{PipeOpTorchOptimizer} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-PipeOpTorchOptimizer-new}{\code{PipeOpTorchOptimizer$new()}} -\item \href{#method-PipeOpTorchOptimizer-clone}{\code{PipeOpTorchOptimizer$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchOptimizer-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchOptimizer$new( - optimizer = t_opt("adam"), - id = "torch_optimizer", - param_vals = list() -)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{optimizer}}{(\code{\link{TorchOptimizer}} or \code{character(1)} or \code{torch_optimizer_generator})\cr -The optimizer (or something convertible via \code{\link[=as_torch_optimizer]{as_torch_optimizer()}}).} - -\item{\code{id}}{(\code{character(1)})\cr -Identifier of the resulting object.} - -\item{\code{param_vals}}{(\code{list()})\cr -List of hyperparameter settings, overwriting the hyperparameter settings that would -otherwise be set during construction.} -} -\if{html}{\out{
}} -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-PipeOpTorchOptimizer-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{PipeOpTorchOptimizer$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_resamplings_row_roles.Rd b/man/mlr_resamplings_row_roles.Rd deleted file mode 100644 index 0aa2e172..00000000 --- a/man/mlr_resamplings_row_roles.Rd +++ /dev/null @@ -1,145 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/ResamplingRowRoles.R -\name{mlr_resamplings_row_roles} -\alias{mlr_resamplings_row_roles} -\alias{ResamplingRowRoles} -\title{Resampling Using Row Roles} -\description{ -In mlr3 it is possible to manually set the row roles \code{use} and \code{test}. -This resampling sets the rows from \code{use} as the training ids and those from \code{test} as the test ids. -This can be useful for tasks like \link[=mlr_tasks_tiny_imagenet]{tiny imagenet} that come with predefined splits. -} -\examples{ -resampling = rsmp("row_roles") -resampling - -task = tsk("mtcars") -splits = partition(task) -task$row_roles$use = splits$train -task$row_roles$test = splits$test -rr = resample(task, lrn("regr.featureless"), resampling) -rr$score() -} -\section{Super class}{ -\code{\link[mlr3:Resampling]{mlr3::Resampling}} -> \code{ResamplingRowRoles} -} -\section{Active bindings}{ -\if{html}{\out{
}} -\describe{ -\item{\code{iters}}{(\code{integer(1)})\cr -The number of iterations which are always one for this resampling.} -} -\if{html}{\out{
}} -} -\section{Methods}{ -\subsection{Public methods}{ -\itemize{ -\item \href{#method-ResamplingRowRoles-new}{\code{ResamplingRowRoles$new()}} -\item \href{#method-ResamplingRowRoles-instantiate}{\code{ResamplingRowRoles$instantiate()}} -\item \href{#method-ResamplingRowRoles-train_set}{\code{ResamplingRowRoles$train_set()}} -\item \href{#method-ResamplingRowRoles-test_set}{\code{ResamplingRowRoles$test_set()}} -\item \href{#method-ResamplingRowRoles-clone}{\code{ResamplingRowRoles$clone()}} -} -} -\if{html}{\out{ -
Inherited methods - -
-}} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-ResamplingRowRoles-new}{}}} -\subsection{Method \code{new()}}{ -Creates a new instance of this \link[R6:R6Class]{R6} class. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{ResamplingRowRoles$new()}\if{html}{\out{
}} -} - -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-ResamplingRowRoles-instantiate}{}}} -\subsection{Method \code{instantiate()}}{ -Materializes fixed training and test splits for a given task and stores them in \verb{$instance}. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{ResamplingRowRoles$instantiate(task)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{task}}{(\link{Task})\cr -Task used for instantiation.} -} -\if{html}{\out{
}} -} -\subsection{Returns}{ -Returns the object itself, but modified \strong{by reference}. -You need to explicitly \verb{$clone()} the object beforehand if you want to keeps -the object in its previous state. -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-ResamplingRowRoles-train_set}{}}} -\subsection{Method \code{train_set()}}{ -Returns the row ids of the i-th train set. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{ResamplingRowRoles$train_set(i)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{i}}{(\code{integer(1)})\cr -Iteration.} -} -\if{html}{\out{
}} -} -\subsection{Returns}{ -(\code{integer()}) of row ids. -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-ResamplingRowRoles-test_set}{}}} -\subsection{Method \code{test_set()}}{ -Returns the row ids of the i-th test set. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{ResamplingRowRoles$test_set(i)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{i}}{(\code{integer(1)})\cr -Iteration.} -} -\if{html}{\out{
}} -} -\subsection{Returns}{ -(\code{integer()}) of row ids. -} -} -\if{html}{\out{
}} -\if{html}{\out{}} -\if{latex}{\out{\hypertarget{method-ResamplingRowRoles-clone}{}}} -\subsection{Method \code{clone()}}{ -The objects of this class are cloneable with this method. -\subsection{Usage}{ -\if{html}{\out{
}}\preformatted{ResamplingRowRoles$clone(deep = FALSE)}\if{html}{\out{
}} -} - -\subsection{Arguments}{ -\if{html}{\out{
}} -\describe{ -\item{\code{deep}}{Whether to make a deep clone.} -} -\if{html}{\out{
}} -} -} -} diff --git a/man/mlr_tasks_lazy_iris.Rd b/man/mlr_tasks_lazy_iris.Rd deleted file mode 100644 index a35a9b4c..00000000 --- a/man/mlr_tasks_lazy_iris.Rd +++ /dev/null @@ -1,46 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TaskClassif_lazy_iris.R -\name{mlr_tasks_lazy_iris} -\alias{mlr_tasks_lazy_iris} -\title{Iris Classification Task} -\format{ -\link[R6:R6Class]{R6::R6Class} inheriting from \link[mlr3:TaskClassif]{mlr3::TaskClassif}. -} -\source{ -\url{https://en.wikipedia.org/wiki/Iris_flower_data_set} -} -\description{ -A classification task for the popular \link[datasets:iris]{datasets::iris} data set. -Just like the iris task, but the features are represented as one lazy tensor column. -} -\section{Construction}{ - - -\if{html}{\out{
}}\preformatted{tsk("lazy_iris") -}\if{html}{\out{
}} -} - -\section{Meta Information}{ - -\itemize{ -\item Task type: \dQuote{classif} -\item Properties: \dQuote{multiclass} -\item Has Missings: no -\item Target: \dQuote{Species} -\item Features: \dQuote{x} -\item Backend Dimension: 150x3 -\item Default Roles (use / test / holdout): 150, 0, 0 -} -} - -\examples{ -task = tsk("lazy_iris") -df = task$data() -materialize(df$x[1:6], rbind = TRUE) -} -\references{ -Anderson E (1936). -\dQuote{The Species Problem in Iris.} -\emph{Annals of the Missouri Botanical Garden}, \bold{23}(3), 457. -\doi{10.2307/2394164}. -} diff --git a/man/mlr_tasks_mnist.Rd b/man/mlr_tasks_mnist.Rd deleted file mode 100644 index 6af1a5d8..00000000 --- a/man/mlr_tasks_mnist.Rd +++ /dev/null @@ -1,54 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TaskClassif_mnist.R -\name{mlr_tasks_mnist} -\alias{mlr_tasks_mnist} -\title{MNIST Image classification} -\source{ -\url{https://torchvision.mlverse.org/reference/mnist_dataset.html} -} -\description{ -Classic MNIST image classification. - -The underlying \code{\link{DataBackend}} contains columns \code{"label"}, \code{"image"}, \code{"row_id"}, \code{"split"}, where the last column -indicates whether the row belongs to the train or test set. - -The first 60000 rows belong to the training set, the last 10000 rows to the test set. -} -\section{Download}{ - -The \link[=Task]{task}'s backend is a \code{\link{DataBackendLazy}} which will download the data once it is requested. -Other meta-data is already available before that. -You can cache these datasets by setting the \code{mlr3torch.cache} option to \code{TRUE} or to a specific path to be used -as the cache directory. -} - -\section{Construction}{ - - -\if{html}{\out{
}}\preformatted{tsk("mnist") -}\if{html}{\out{
}} -} - -\section{Meta Information}{ - -\itemize{ -\item Task type: \dQuote{classif} -\item Properties: \dQuote{multiclass} -\item Has Missings: no -\item Target: \dQuote{label} -\item Features: \dQuote{image} -\item Backend Dimension: 70000x3 -\item Default Roles (use / test / holdout): 60000, 10000, 0 -} -} - -\examples{ -task = tsk("mnist") -task -} -\references{ -Lecun, Y., Bottou, L., Bengio, Y., Haffner, P. (1998). -\dQuote{Gradient-based learning applied to document recognition.} -\emph{Proceedings of the IEEE}, \bold{86}(11), 2278-2324. -\doi{10.1109/5.726791}. -} diff --git a/man/mlr_tasks_tiny_imagenet.Rd b/man/mlr_tasks_tiny_imagenet.Rd deleted file mode 100644 index 12730832..00000000 --- a/man/mlr_tasks_tiny_imagenet.Rd +++ /dev/null @@ -1,46 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TaskClassif_tiny_imagenet.R -\name{mlr_tasks_tiny_imagenet} -\alias{mlr_tasks_tiny_imagenet} -\title{Tiny ImageNet Classification Task} -\description{ -Subset of the famous ImageNet dataset. -The data is obtained from \code{\link[torchvision:tiny_imagenet_dataset]{torchvision::tiny_imagenet_dataset()}}. -It contains the train, validation and test data. -The row role \code{use} is set to the training data, the row role \code{test} to the valdiation data and the row role -\code{holdout} is set to the test data. -There are no labels available for the test data. - -The underlying \code{\link{DataBackend}} contains columns \code{"class"}, \code{"image"}, \code{"row_id"}, \code{"split"}, where the last column -indicates whether the row belongs to the train, validation or test set. -} -\section{Construction}{ - - -\if{html}{\out{
}}\preformatted{tsk("tiny_imagenet") -}\if{html}{\out{
}} -} - -\section{Meta Information}{ - -\itemize{ -\item Task type: \dQuote{classif} -\item Properties: \dQuote{multiclass} -\item Has Missings: no -\item Target: \dQuote{class} -\item Features: \dQuote{image} -\item Backend Dimension: 120000x3 -\item Default Roles (use / test / holdout): 100000, 10000, 10000 -} -} - -\examples{ -task = tsk("tiny_imagenet") -task -} -\references{ -Deng, Jia, Dong, Wei, Socher, Richard, Li, Li-Jia, Li, Kai, Fei-Fei, Li (2009). -\dQuote{Imagenet: A large-scale hierarchical image database.} -In \emph{2009 IEEE conference on computer vision and pattern recognition}, 248--255. -IEEE. -} diff --git a/man/model_descriptor_to_learner.Rd b/man/model_descriptor_to_learner.Rd deleted file mode 100644 index ca28a14f..00000000 --- a/man/model_descriptor_to_learner.Rd +++ /dev/null @@ -1,36 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/nn_graph.R -\name{model_descriptor_to_learner} -\alias{model_descriptor_to_learner} -\title{Create a Torch Learner from a ModelDescriptor} -\usage{ -model_descriptor_to_learner(model_descriptor) -} -\arguments{ -\item{model_descriptor}{(\code{\link{ModelDescriptor}})\cr -The model descriptor.} -} -\value{ -\code{\link{Learner}} -} -\description{ -First a \code{\link{nn_graph}} is created using \code{\link{model_descriptor_to_module}} and then a learner is created from this -module and the remaining information from the model descriptor, which must include the optimizer and loss function -and optionally callbacks. -} -\seealso{ -Other Graph Network: -\code{\link{ModelDescriptor}()}, -\code{\link{TorchIngressToken}()}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{model_descriptor_to_module}()}, -\code{\link{model_descriptor_union}()}, -\code{\link{nn_graph}()} -} -\concept{Graph Network} diff --git a/man/model_descriptor_to_module.Rd b/man/model_descriptor_to_module.Rd deleted file mode 100644 index 7eb09a67..00000000 --- a/man/model_descriptor_to_module.Rd +++ /dev/null @@ -1,47 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/nn_graph.R -\name{model_descriptor_to_module} -\alias{model_descriptor_to_module} -\title{Create a nn_graph from ModelDescriptor} -\usage{ -model_descriptor_to_module( - model_descriptor, - output_pointers = NULL, - list_output = FALSE -) -} -\arguments{ -\item{model_descriptor}{(\code{\link{ModelDescriptor}})\cr -Model Descriptor. \code{pointer} is ignored, instead \code{output_pointer} values are used. \verb{$graph} member is -modified by-reference.} - -\item{output_pointers}{(\code{list} of \code{character})\cr -Collection of \code{pointer}s that indicate what part of the \code{model_descriptor$graph} is being used for output. -Entries have the format of \code{ModelDescriptor$pointer}.} - -\item{list_output}{(\code{logical(1)})\cr -Whether output should be a list of tensors. If \code{FALSE}, then \code{length(output_pointers)} must be 1.} -} -\value{ -\code{\link{nn_graph}} -} -\description{ -Creates the \code{\link{nn_graph}} from a \code{\link{ModelDescriptor}}. Mostly for internal use, since the \code{\link{ModelDescriptor}} is in -most circumstances harder to use than just creating \code{\link{nn_graph}} directly. -} -\seealso{ -Other Graph Network: -\code{\link{ModelDescriptor}()}, -\code{\link{TorchIngressToken}()}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{model_descriptor_to_learner}()}, -\code{\link{model_descriptor_union}()}, -\code{\link{nn_graph}()} -} -\concept{Graph Network} diff --git a/man/model_descriptor_union.Rd b/man/model_descriptor_union.Rd deleted file mode 100644 index 1eee931e..00000000 --- a/man/model_descriptor_union.Rd +++ /dev/null @@ -1,60 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/ModelDescriptor.R -\name{model_descriptor_union} -\alias{model_descriptor_union} -\title{Union of ModelDescriptors} -\usage{ -model_descriptor_union(md1, md2) -} -\arguments{ -\item{md1}{(\code{ModelDescriptor}) -The first \code{\link{ModelDescriptor}}.} - -\item{md2}{(\code{ModelDescriptor}) -The second \code{\link{ModelDescriptor}}.} -} -\value{ -\code{\link{ModelDescriptor}} -} -\description{ -This is a mostly internal function that is used in \code{\link{PipeOpTorch}}s with multiple input channels. - -It creates the union of multiple \code{\link{ModelDescriptor}}s: -\itemize{ -\item \code{graph}s are combinded (if they are not identical to begin with). The first entry's \code{graph} is modified by -reference. -\item \code{PipeOp}s with the same ID must be identical. No new input edges may be added to \code{PipeOp}s. -\item Drops \code{pointer} / \code{pointer_shape} entries. -\item The new task is the \link[=PipeOpFeatureUnion]{feature union} of the two incoming tasks. -\item The \code{optimizer} and \code{loss} of both \code{\link{ModelDescriptor}}s must be identical. -\item Ingress tokens and callbacks are merged, where objects with the same \code{"id"} must be identical. -} -} -\details{ -The requirement that no new input edgedes may be added to \code{PipeOp}s is not theoretically necessary, but since -we assume that ModelDescriptor is being built from beginning to end (i.e. \code{PipeOp}s never get new ancestors) we -can make this assumption and simplify things. Otherwise we'd need to treat "..."-inputs special.) -} -\seealso{ -Other Graph Network: -\code{\link{ModelDescriptor}()}, -\code{\link{TorchIngressToken}()}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{model_descriptor_to_learner}()}, -\code{\link{model_descriptor_to_module}()}, -\code{\link{nn_graph}()} - -Other Model Configuration: -\code{\link{ModelDescriptor}()}, -\code{\link{mlr_pipeops_torch_callbacks}}, -\code{\link{mlr_pipeops_torch_loss}}, -\code{\link{mlr_pipeops_torch_optimizer}} -} -\concept{Graph Network} -\concept{Model Configuration} diff --git a/man/nn_graph.Rd b/man/nn_graph.Rd deleted file mode 100644 index 3bca9e6f..00000000 --- a/man/nn_graph.Rd +++ /dev/null @@ -1,57 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/nn_graph.R -\name{nn_graph} -\alias{nn_graph} -\title{Graph Network} -\usage{ -nn_graph(graph, shapes_in, output_map = graph$output$name, list_output = FALSE) -} -\arguments{ -\item{graph}{(\code{\link[mlr3pipelines:Graph]{Graph}})\cr -The \code{\link[mlr3pipelines:Graph]{Graph}} to wrap. Is \strong{not} cloned.} - -\item{shapes_in}{(named \code{integer})\cr -Shape info of tensors that go into \code{graph}. Names must be \code{graph$input$name}, possibly in different order.} - -\item{output_map}{(\code{character})\cr -Which of \code{graph}'s outputs to use. Must be a subset of \code{graph$output$name}.} - -\item{list_output}{(\code{logical(1)})\cr -Whether output should be a list of tensors. If \code{FALSE} (default), then \code{length(output_map)} must be 1.} -} -\value{ -\code{\link{nn_graph}} -} -\description{ -Represents a neural network using a \code{\link{Graph}} that usually costains mostly \code{\link{PipeOpModule}}s. -} -\examples{ -graph = mlr3pipelines::Graph$new() -graph$add_pipeop(po("module_1", module = nn_linear(10, 20)), clone = FALSE) -graph$add_pipeop(po("module_2", module = nn_relu()), clone = FALSE) -graph$add_pipeop(po("module_3", module = nn_linear(20, 1)), clone = FALSE) -graph$add_edge("module_1", "module_2") -graph$add_edge("module_2", "module_3") - -network = nn_graph(graph, shapes_in = list(module_1.input = c(NA, 10))) - -x = torch_randn(16, 10) - -network(module_1.input = x) -} -\seealso{ -Other Graph Network: -\code{\link{ModelDescriptor}()}, -\code{\link{TorchIngressToken}()}, -\code{\link{mlr_learners_torch_model}}, -\code{\link{mlr_pipeops_module}}, -\code{\link{mlr_pipeops_torch}}, -\code{\link{mlr_pipeops_torch_ingress}}, -\code{\link{mlr_pipeops_torch_ingress_categ}}, -\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, -\code{\link{mlr_pipeops_torch_ingress_num}}, -\code{\link{model_descriptor_to_learner}()}, -\code{\link{model_descriptor_to_module}()}, -\code{\link{model_descriptor_union}()} -} -\concept{Graph Network} diff --git a/man/nn_merge_cat.Rd b/man/nn_merge_cat.Rd deleted file mode 100644 index 99a4b1c8..00000000 --- a/man/nn_merge_cat.Rd +++ /dev/null @@ -1,16 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchMerge.R -\name{nn_merge_cat} -\alias{nn_merge_cat} -\title{Concatenates multiple tensors} -\usage{ -nn_merge_cat(dim = -1) -} -\arguments{ -\item{dim}{(\code{integer(1)})\cr -The dimension for the concatenation.} -} -\description{ -Concatenates multiple tensors on a given dimension. -No broadcasting rules are applied here, you must reshape the tensors before to have the same shape. -} diff --git a/man/nn_merge_prod.Rd b/man/nn_merge_prod.Rd deleted file mode 100644 index 2fb9ccf3..00000000 --- a/man/nn_merge_prod.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchMerge.R -\name{nn_merge_prod} -\alias{nn_merge_prod} -\title{Product of multiple tensors} -\usage{ -nn_merge_prod() -} -\description{ -Calculates the product of all input tensors. -} diff --git a/man/nn_merge_sum.Rd b/man/nn_merge_sum.Rd deleted file mode 100644 index 3e7fedf2..00000000 --- a/man/nn_merge_sum.Rd +++ /dev/null @@ -1,11 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchMerge.R -\name{nn_merge_sum} -\alias{nn_merge_sum} -\title{Sum of multiple tensors} -\usage{ -nn_merge_sum() -} -\description{ -Calculates the sum of all input tensors. -} diff --git a/man/nn_reshape.Rd b/man/nn_reshape.Rd deleted file mode 100644 index a18243d8..00000000 --- a/man/nn_reshape.Rd +++ /dev/null @@ -1,15 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchReshape.R -\name{nn_reshape} -\alias{nn_reshape} -\title{Reshape} -\usage{ -nn_reshape(shape) -} -\arguments{ -\item{shape}{(\code{integer()})\cr -The desired output shape.} -} -\description{ -Reshape a tensor to the given shape. -} diff --git a/man/nn_squeeze.Rd b/man/nn_squeeze.Rd deleted file mode 100644 index 357f0f9f..00000000 --- a/man/nn_squeeze.Rd +++ /dev/null @@ -1,15 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchReshape.R -\name{nn_squeeze} -\alias{nn_squeeze} -\title{Squeeze} -\usage{ -nn_squeeze(dim) -} -\arguments{ -\item{dim}{(\code{integer()})\cr -The dimension to squeeze.} -} -\description{ -Squeezes a tensor by calling \code{\link[torch:torch_squeeze]{torch::torch_squeeze()}} with the given dimension \code{dim}. -} diff --git a/man/nn_unsqueeze.Rd b/man/nn_unsqueeze.Rd deleted file mode 100644 index 0fc27e93..00000000 --- a/man/nn_unsqueeze.Rd +++ /dev/null @@ -1,15 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTorchReshape.R -\name{nn_unsqueeze} -\alias{nn_unsqueeze} -\title{Unsqueeze} -\usage{ -nn_unsqueeze(dim) -} -\arguments{ -\item{dim}{(\code{integer(1)})\cr -The dimension to unsqueeze.} -} -\description{ -Unsqueezes a tensor by calling \code{\link[torch:torch_unsqueeze]{torch::torch_unsqueeze()}} with the given dimension \code{dim}. -} diff --git a/man/pipeop_preproc_torch.Rd b/man/pipeop_preproc_torch.Rd deleted file mode 100644 index 3eb70276..00000000 --- a/man/pipeop_preproc_torch.Rd +++ /dev/null @@ -1,72 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PipeOpTaskPreprocTorch.R -\name{pipeop_preproc_torch} -\alias{pipeop_preproc_torch} -\title{Create Torch Preprocessing PipeOps} -\usage{ -pipeop_preproc_torch( - id, - fn, - shapes_out = NULL, - param_set = NULL, - packages = character(0), - rowwise = FALSE, - parent_env = parent.frame(), - stages_init = NULL, - tags = NULL -) -} -\arguments{ -\item{id}{(\code{character(1)})\cr -The id for of the new object.} - -\item{fn}{(\code{function})\cr -The preprocessing function.} - -\item{shapes_out}{(\code{function} or \code{NULL} or \code{"infer"})\cr -The private \code{.shapes_out(shapes_in, param_vals, task)} method of \code{\link{PipeOpTaskPreprocTorch}} -(see section Inheriting). -Special values are \code{NULL} and \code{infer}: -If \code{NULL}, the output shapes are unknown. -If "infer", the output shape function is inferred and calculates the output shapes as follows: -For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is -applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. -If the first dimension is not \code{NA}, the output shape of applying the preprocessing function is returned. -Method \code{"infer"} should be correct in most cases, but might fail in some edge cases.} - -\item{param_set}{(\code{\link{ParamSet}} or \code{NULL})\cr -The parameter set. -If this is left as \code{NULL} (default) the parameter set is inferred in the following way: -All parameters but the first and \code{...} of \code{fn} are set as untyped parameters with tags 'train' and those that -have no default value are tagged as 'required' as well. -Default values are not annotated.} - -\item{packages}{(\code{character()})\cr -The R packages this object depends on.} - -\item{rowwise}{(\code{logical(1)})\cr -Whether the preprocessing is applied row-wise.} - -\item{parent_env}{(\code{environment})\cr -The parent environment for the R6 class.} - -\item{stages_init}{(\code{character(1)})\cr -Initial value for the \code{stages} parameter. -If \code{NULL} (default), will be set to \code{"both"} in case the \code{id} starts with \code{"trafo"} and to \code{"train"} -if it starts with \code{"augment"}. Otherwise it must specified.} - -\item{tags}{(\code{character()})\cr -Tags for the pipeop} -} -\value{ -An \code{\link[R6:R6Class]{R6Class}} instance inheriting from \code{\link{PipeOpTaskPreprocTorch}} -} -\description{ -Function to create objects of class \code{\link{PipeOpTaskPreprocTorch}} in a more convenient way. -Start by reading the documentation of \code{\link{PipeOpTaskPreprocTorch}}. -} -\examples{ -PipeOpPreprocExample = pipeop_preproc_torch("preproc_example", function(x, a) x + a, ) -po_example = PipeOpPreprocExample$new() -po_example$param_set -} diff --git a/man/reset_layer.Rd b/man/reset_layer.Rd deleted file mode 100644 index 27bf47bc..00000000 --- a/man/reset_layer.Rd +++ /dev/null @@ -1,52 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/reset_last_layer.R -\name{reset_last_layer} -\alias{reset_last_layer} -\alias{reset_last_layer.AlexNet} -\alias{reset_last_layer.resnet} -\title{Reset a classification models last layer} -\usage{ -reset_last_layer(model, num_classes, bias, freeze) - -\method{reset_last_layer}{AlexNet}(model, num_classes, bias = TRUE, freeze = FALSE) - -\method{reset_last_layer}{resnet}(model, num_classes, bias = TRUE, freeze = FALSE) -} -\arguments{ -\item{model}{A pretrained model, e.g. -\code{torchvision::model_alexnet(pretrained = TRUE)}} - -\item{num_classes}{Number of desired output classes.} - -\item{bias}{\verb{[TRUE]} Whether to use bias in the last layer.} - -\item{freeze}{(\code{logical(1)})\cr -Whether to freee all layers expect for the output layer.} -} -\value{ -Same as input \code{model} with modified last layer. -} -\description{ -Used for pretrained models where the last layer is set to e.g. 1000 classes -but training is intended to be applied to e.g. 10 classes. -} -\note{ -As of this, this also freezes the parameters of all but the last layer. -} -\examples{ -\dontrun{ -# AlexNet -if (mlr3misc::requires_namespaces("torchvision")) { - model = torchvision::model_alexnet(pretrained = TRUE) - model$classifier[[7]]$out_feature - model = reset_last_layer(model, 10) - model$classifier[[7]]$out_feature - - # ResNet - model = torchvision::model_resnet18(pretrained = TRUE) - model$fc$out_feature - model = reset_last_layer(model, 10) - model$fc$out_feature -} -} -} diff --git a/man/t_clbk.Rd b/man/t_clbk.Rd deleted file mode 100644 index 8c2779ed..00000000 --- a/man/t_clbk.Rd +++ /dev/null @@ -1,61 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TorchCallback.R -\name{t_clbk} -\alias{t_clbk} -\alias{t_clbks} -\title{Sugar Function for Torch Callback} -\usage{ -t_clbk(.key, ...) - -t_clbks(.keys) -} -\arguments{ -\item{.key}{(\code{character(1)})\cr -The key of the torch callback.} - -\item{...}{(any)\cr -See description of \code{\link[=dictionary_sugar_get]{dictionary_sugar_get()}}.} - -\item{.keys}{(\code{character()})\cr -The keys of the callbacks.} -} -\value{ -\code{\link{TorchCallback}} - -\code{list()} of \code{\link{TorchCallback}}s -} -\description{ -Retrieves one or more \href{s}{\code{TorchCallback}} from \code{\link{mlr3torch_callbacks}}. -Works like \code{\link[mlr3:mlr_sugar]{mlr3::lrn()}} and \code{\link[mlr3:mlr_sugar]{mlr3::lrns()}}. -} -\examples{ -t_clbk("progress") -} -\seealso{ -Other Callback: -\code{\link{TorchCallback}}, -\code{\link{as_torch_callback}()}, -\code{\link{as_torch_callbacks}()}, -\code{\link{callback_set}()}, -\code{\link{mlr3torch_callbacks}}, -\code{\link{mlr_callback_set}}, -\code{\link{mlr_callback_set.checkpoint}}, -\code{\link{mlr_callback_set.progress}}, -\code{\link{mlr_context_torch}}, -\code{\link{torch_callback}()} - -Other Torch Descriptor: -\code{\link{TorchCallback}}, -\code{\link{TorchDescriptor}}, -\code{\link{TorchLoss}}, -\code{\link{TorchOptimizer}}, -\code{\link{as_torch_callbacks}()}, -\code{\link{as_torch_loss}()}, -\code{\link{as_torch_optimizer}()}, -\code{\link{mlr3torch_losses}}, -\code{\link{mlr3torch_optimizers}}, -\code{\link{t_loss}()}, -\code{\link{t_opt}()} -} -\concept{Callback} -\concept{Torch Descriptor} diff --git a/man/t_loss.Rd b/man/t_loss.Rd deleted file mode 100644 index 909eb1d2..00000000 --- a/man/t_loss.Rd +++ /dev/null @@ -1,51 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TorchLoss.R -\name{t_loss} -\alias{t_loss} -\alias{t_losses} -\title{Loss Function Quick Access} -\usage{ -t_loss(.key, ...) - -t_losses(.keys, ...) -} -\arguments{ -\item{.key}{(\code{character(1)})\cr -Key of the object to retrieve.} - -\item{...}{(any)\cr -See description of \code{\link{dictionary_sugar_get}}.} - -\item{.keys}{(\code{character()})\cr -The keys of the losses.} -} -\value{ -A \code{\link{TorchLoss}} -} -\description{ -Retrieve one or more \href{es}{\code{TorchLoss}} from \code{\link{mlr3torch_losses}}. -Works like \code{\link[mlr3:mlr_sugar]{mlr3::lrn()}} and \code{\link[mlr3:mlr_sugar]{mlr3::lrns()}}. -} -\examples{ -t_loss("mse", reduction = "mean") -# get the dictionary -t_loss() -t_losses(c("mse", "l1")) -# get the dictionary -t_losses() -} -\seealso{ -Other Torch Descriptor: -\code{\link{TorchCallback}}, -\code{\link{TorchDescriptor}}, -\code{\link{TorchLoss}}, -\code{\link{TorchOptimizer}}, -\code{\link{as_torch_callbacks}()}, -\code{\link{as_torch_loss}()}, -\code{\link{as_torch_optimizer}()}, -\code{\link{mlr3torch_losses}}, -\code{\link{mlr3torch_optimizers}}, -\code{\link{t_clbk}()}, -\code{\link{t_opt}()} -} -\concept{Torch Descriptor} diff --git a/man/t_opt.Rd b/man/t_opt.Rd deleted file mode 100644 index 364d5b7f..00000000 --- a/man/t_opt.Rd +++ /dev/null @@ -1,57 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TorchOptimizer.R -\name{t_opt} -\alias{t_opt} -\alias{t_opts} -\title{Optimizers Quick Access} -\usage{ -t_opt(.key, ...) - -t_opts(.keys, ...) -} -\arguments{ -\item{.key}{(\code{character(1)})\cr -Key of the object to retrieve.} - -\item{...}{(any)\cr -See description of \code{\link{dictionary_sugar_get}}.} - -\item{.keys}{(\code{character()})\cr -The keys of the optimizers.} -} -\value{ -A \code{\link{TorchOptimizer}} -} -\description{ -Retrieves one or more \href{s}{\code{TorchOptimizer}} from \code{\link{mlr3torch_optimizers}}. -Works like \code{\link[mlr3:mlr_sugar]{mlr3::lrn()}} and \code{\link[mlr3:mlr_sugar]{mlr3::lrns()}}. -} -\examples{ -t_opt("adam", lr = 0.1) -# get the dictionary -t_opt() -t_opts(c("adam", "sgd")) -# get the dictionary -t_opts() -} -\seealso{ -Other Torch Descriptor: -\code{\link{TorchCallback}}, -\code{\link{TorchDescriptor}}, -\code{\link{TorchLoss}}, -\code{\link{TorchOptimizer}}, -\code{\link{as_torch_callbacks}()}, -\code{\link{as_torch_loss}()}, -\code{\link{as_torch_optimizer}()}, -\code{\link{mlr3torch_losses}}, -\code{\link{mlr3torch_optimizers}}, -\code{\link{t_clbk}()}, -\code{\link{t_loss}()} - -Other Dictionary: -\code{\link{mlr3torch_callbacks}}, -\code{\link{mlr3torch_losses}}, -\code{\link{mlr3torch_optimizers}} -} -\concept{Dictionary} -\concept{Torch Descriptor} diff --git a/man/task_dataset.Rd b/man/task_dataset.Rd deleted file mode 100644 index c521a124..00000000 --- a/man/task_dataset.Rd +++ /dev/null @@ -1,57 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/task_dataset.R -\name{task_dataset} -\alias{task_dataset} -\title{Create a Dataset from a Task} -\usage{ -task_dataset(task, feature_ingress_tokens, target_batchgetter = NULL, device) -} -\arguments{ -\item{task}{(\code{\link{Task}})\cr -The task for which to build the \link[torch:dataset]{dataset}.} - -\item{feature_ingress_tokens}{(named \code{list()} of \code{\link{TorchIngressToken}})\cr -Each ingress token defines one item in the \verb{$x} value of a batch with corresponding names.} - -\item{target_batchgetter}{(\verb{function(data, device)})\cr -A function taking in arguments \code{data}, which is a \code{data.table} containing only the target variable, and \code{device}. -It must return the target as a torch \link[torch:torch_tensor]{tensor} on the selected device.} - -\item{device}{(\code{character()})\cr -The device, e.g. \code{"cuda"} or \code{"cpu"}.} -} -\value{ -\code{\link[torch:dataset]{torch::dataset}} -} -\description{ -Creates a torch \link[torch:dataset]{dataset} from an mlr3 \code{\link{Task}}. -The resulting dataset's \verb{$.get_batch()} method returns a list with elements \code{x}, \code{y} and \code{index}: -\itemize{ -\item \code{x} is a list with tensors, whose content is defined by the parameter \code{feature_ingress_tokens}. -\item \code{y} is the target variable and its content is defined by the parameter \code{target_batchgetter}. -\item \code{.index} is the index of the batch in the task's data. -} - -The data is returned on the device specified by the parameter \code{device}. -} -\examples{ -task = tsk("iris") -sepal_ingress = TorchIngressToken( - features = c("Sepal.Length", "Sepal.Width"), - batchgetter = batchgetter_num, - shape = c(NA, 2) -) -petal_ingress = TorchIngressToken( - features = c("Petal.Length", "Petal.Width"), - batchgetter = batchgetter_num, - shape = c(NA, 2) -) -ingress_tokens = list(sepal = sepal_ingress, petal = petal_ingress) - -target_batchgetter = function(data, device) { - torch_tensor(data = data[[1L]], dtype = torch_float32(), device)$unsqueeze(2) -} -dataset = task_dataset(task, ingress_tokens, target_batchgetter, "cpu") -batch = dataset$.getbatch(1:10) -batch -} diff --git a/man/torch_callback.Rd b/man/torch_callback.Rd deleted file mode 100644 index 6e1ef091..00000000 --- a/man/torch_callback.Rd +++ /dev/null @@ -1,141 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/TorchCallback.R -\name{torch_callback} -\alias{torch_callback} -\title{Create a Callback Desctiptor} -\usage{ -torch_callback( - id, - classname = paste0("CallbackSet", capitalize(id)), - param_set = NULL, - packages = NULL, - label = capitalize(id), - man = NULL, - on_begin = NULL, - on_end = NULL, - on_epoch_begin = NULL, - on_before_valid = NULL, - on_epoch_end = NULL, - on_batch_begin = NULL, - on_batch_end = NULL, - on_after_backward = NULL, - on_batch_valid_begin = NULL, - on_batch_valid_end = NULL, - initialize = NULL, - public = NULL, - private = NULL, - active = NULL, - parent_env = parent.frame(), - inherit = CallbackSet, - lock_objects = FALSE -) -} -\arguments{ -\item{id}{(\code{character(1)})\cr`\cr -The id for the torch callback.} - -\item{classname}{(\code{character(1)})\cr -The class name.} - -\item{param_set}{(\code{ParamSet})\cr -The parameter set, if not present it is inferred from the \verb{$initialize()} method.} - -\item{packages}{(\code{character()})\cr\verb{The packages the callback depends on. Default is}NULL`.} - -\item{label}{(\code{character(1)})\cr -The label for the torch callback. -Defaults to the capitalized \code{id}.} - -\item{man}{(\code{character(1)})\cr -String in the format \verb{[pkg]::[topic]} pointing to a manual page for this object. -The referenced help package can be opened via method \verb{$help()}. -The default is \code{NULL}.} - -\item{on_begin, on_end, on_epoch_begin, on_before_valid, on_epoch_end, on_batch_begin, on_batch_end, on_after_backward, on_batch_valid_begin, on_batch_valid_end}{(\code{function})\cr -Function to execute at the given stage, see section \emph{Stages}.} - -\item{initialize}{(\verb{function()})\cr -The initialization method of the callback.} - -\item{public, private, active}{(\code{list()})\cr -Additional public, private, and active fields to add to the callback.} - -\item{parent_env}{(\code{environment()})\cr -The parent environment for the \code{\link{R6Class}}.} - -\item{inherit}{(\code{R6ClassGenerator})\cr -From which class to inherit. -This class must either be \code{\link{CallbackSet}} (default) or inherit from it.} - -\item{lock_objects}{(\code{logical(1)})\cr -Whether to lock the objects of the resulting \code{\link{R6Class}}. -If \code{FALSE} (default), values can be freely assigned to \code{self} without declaring them in the -class definition.} -} -\value{ -\code{\link{TorchCallback}} -} -\description{ -Convenience function to create a custom \code{\link{TorchCallback}}. -All arguments that are available in \code{\link[=callback_set]{callback_set()}} are also available here. -For more information on how to correctly implement a new callback, see \code{\link{CallbackSet}}. -} -\section{Internals}{ - -It first creates an \code{R6} class inheriting from \code{\link{CallbackSet}} (using \code{\link[=callback_set]{callback_set()}}) and -then wraps this generator in a \code{\link{TorchCallback}} that can be passed to a torch learner. -} - -\section{Stages}{ - -\itemize{ -\item \code{begin} :: Run before the training loop begins. -\item \code{epoch_begin} :: Run he beginning of each epoch. -\item \code{before_validation} :: Run before each validation loop. -\item \code{batch_begin} :: Run before the forward call. -\item \code{after_backward} :: Run after the backward call. -\item \code{batch_end} :: Run after the optimizer step. -\item \code{batch_valid_begin} :: Run before the forward call in the validation loop. -\item \code{batch_valid_end} :: Run after the forward call in the validation loop. -\item \code{epoch_end} :: Run at the end of each epoch. -\item \code{end} :: Run at last, using \code{on.exit()}. -} -} - -\examples{ -custom_tcb = torch_callback("custom", - initialize = function(name) { - self$name = name - }, - on_begin = function() { - cat("Hello", self$name, ", we will train for ", self$ctx$total_epochs, "epochs.\n") - }, - on_end = function() { - cat("Training is done.") - } -) - -learner = lrn("classif.torch_featureless", - batch_size = 16, - epochs = 1, - callbacks = custom_tcb, - cb.custom.name = "Marie", - device = "cpu" -) -task = tsk("iris") -learner$train(task) -} -\seealso{ -Other Callback: -\code{\link{TorchCallback}}, -\code{\link{as_torch_callback}()}, -\code{\link{as_torch_callbacks}()}, -\code{\link{callback_set}()}, -\code{\link{mlr3torch_callbacks}}, -\code{\link{mlr_callback_set}}, -\code{\link{mlr_callback_set.checkpoint}}, -\code{\link{mlr_callback_set.progress}}, -\code{\link{mlr_context_torch}}, -\code{\link{t_clbk}()} -} -\concept{Callback} From 83b8e2d95f2d0ed3b3a6e36ee7225398d306d97a Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 7 Feb 2024 18:05:11 +0100 Subject: [PATCH 85/90] Update R/task_dataset.R --- R/task_dataset.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/task_dataset.R b/R/task_dataset.R index 8f13e0cd..75148c71 100644 --- a/R/task_dataset.R +++ b/R/task_dataset.R @@ -91,7 +91,7 @@ task_dataset = dataset( } ) -# This returns a +# This returns a data.table or NULL (if nothing was merged) merge_lazy_tensor_graphs = function(lts) { # we only attempt to merge preprocessing graphs that have the same dataset_hash hashes = map_chr(lts, function(lt) dd(lt)$dataset_hash) From f9493af3cfe7d004cc70b1a13640dd72e8eed39d Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 7 Feb 2024 18:05:21 +0100 Subject: [PATCH 86/90] Update DESCRIPTION --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index aae8dbf3..90a2c9f0 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -42,7 +42,7 @@ Imports: checkmate (>= 2.2.0), coro, lgr, - mlr3misc (>= 0.13.0), + mlr3misc (>= 0.14.0), methods, data.table, paradox (>= 0.11.0), From a6317dc1148e2ac9f41aaaf47ef5b279332574d9 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 7 Feb 2024 18:05:29 +0100 Subject: [PATCH 87/90] Update R/materialize.R --- R/materialize.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/materialize.R b/R/materialize.R index 02138a1e..b6ed2497 100644 --- a/R/materialize.R +++ b/R/materialize.R @@ -52,7 +52,7 @@ materialize = function(x, device = "cpu", rbind = FALSE, ...) { #' @param cache (`character(1)` or `environment()` or `NULL`)\cr #' Optional cache for (intermediate) materialization results. #' Per default, caching will be enabled when the same dataset or data descriptor (with different output pointer) -#' is used for more than one lazy tensor columns. +#' is used for more than one lazy tensor column. #' @export materialize.list = function(x, device = "cpu", rbind = FALSE, cache = "auto", ...) { # nolint x_lt = x[map_lgl(x, is_lazy_tensor)] From 05644c462ef926988d82908a3bf2aaef3cd938a9 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 7 Feb 2024 18:05:37 +0100 Subject: [PATCH 88/90] Update R/utils.R --- R/utils.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/utils.R b/R/utils.R index 527dd3a4..8383c1e8 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1,6 +1,6 @@ #' Auto Device #' -#' First tries cuda, then mp, then cpu. +#' First tries cuda, then cpu. #' #' @param device (`character(1)`)\cr #' The device. If not `NULL`, is returned as is. From eccccaa7a4d0baf6c029a534232414d223966af2 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 7 Feb 2024 18:06:37 +0100 Subject: [PATCH 89/90] cleanup --- tests/testthat/helper_autotest.R | 10 ---------- tests/testthat/setup.R | 22 ---------------------- tests/testthat/teardown.R | 2 -- 3 files changed, 34 deletions(-) diff --git a/tests/testthat/helper_autotest.R b/tests/testthat/helper_autotest.R index 7ba3aea1..f8c26741 100644 --- a/tests/testthat/helper_autotest.R +++ b/tests/testthat/helper_autotest.R @@ -379,13 +379,3 @@ expect_pipeop_torch_preprocess = function(obj, shapes_in, exclude = character(0) } }) } - - -#' @title Autotest Learner Torch -#' @descrition -#' The autotest for torch learners differs from the standard mlr3 autotest for learners. -#' The reason is, that we do not have to test the -expect_learner_torch = function(learner) { - -} - diff --git a/tests/testthat/setup.R b/tests/testthat/setup.R index 8d1083a1..9fde85e8 100644 --- a/tests/testthat/setup.R +++ b/tests/testthat/setup.R @@ -15,25 +15,3 @@ old_threshold = lg$threshold old_plan = future::plan() lg$set_threshold("warn") future::plan("sequential") - -prev_auto_device = mlr3torch::auto_device - -assignInNamespace(ns = "mlr3torch", x = "auto_device", value = function(device = NULL) { - if (device == "auto") { - device = if (cuda_is_available()) { - "cuda" - } else if (backends_mps_is_available() && identical(Sys.getenv("GITHUB_ACTIONS"), "true")) { - # We are not the only ones experiencing issues: - # https://discuss.pytorch.org/t/mps-back-end-out-of-memory-on-github-action/189773 - if (identical(Sys.getenv("GITHUB_ACTIONS"), "true") && nzchar(Sys.getenv("_R_CHECK_PACKAGE_NAME_", ""))) { - "cpu" - } else { - "mps" - } - } else { - "cpu" - } - lg$debug("Auto-detected device '%s'.", device) - } - return(device) -}) diff --git a/tests/testthat/teardown.R b/tests/testthat/teardown.R index d9a7e54f..69101ac9 100644 --- a/tests/testthat/teardown.R +++ b/tests/testthat/teardown.R @@ -1,5 +1,3 @@ lg$set_threshold(old_threshold) future::plan(old_plan) lg_mlr3$set_threshold(old_threshold_mlr3) - -assignInNamespace(ns = "mlr3torch", x = "auto_device", value = prev_auto_device) From c18f7d022fb488b5974a5bdb98f15670cb431a58 Mon Sep 17 00:00:00 2001 From: Sebastian Fischer Date: Wed, 7 Feb 2024 18:08:46 +0100 Subject: [PATCH 90/90] docs --- man/DataDescriptor.Rd | 168 ++++++++ man/ModelDescriptor.Rd | 91 +++++ man/PipeOpPreprocTorchAugmentCenterCrop.Rd | 23 ++ man/PipeOpPreprocTorchAugmentColorJitter.Rd | 26 ++ man/PipeOpPreprocTorchAugmentCrop.Rd | 26 ++ man/PipeOpPreprocTorchAugmentHflip.Rd | 22 ++ man/PipeOpPreprocTorchAugmentRandomAffine.Rd | 27 ++ man/PipeOpPreprocTorchAugmentRandomApply.Rd | 24 ++ man/PipeOpPreprocTorchAugmentRandomChoice.Rd | 23 ++ man/PipeOpPreprocTorchAugmentRandomCrop.Rd | 27 ++ ...PreprocTorchAugmentRandomHorizontalFlip.Rd | 23 ++ man/PipeOpPreprocTorchAugmentRandomOrder.Rd | 23 ++ ...eOpPreprocTorchAugmentRandomResizedCrop.Rd | 26 ++ ...OpPreprocTorchAugmentRandomVerticalFlip.Rd | 23 ++ man/PipeOpPreprocTorchAugmentResizedCrop.Rd | 28 ++ man/PipeOpPreprocTorchAugmentRotate.Rd | 27 ++ man/PipeOpPreprocTorchAugmentVflip.Rd | 22 ++ ...PipeOpPreprocTorchTrafoAdjustBrightness.Rd | 23 ++ man/PipeOpPreprocTorchTrafoAdjustGamma.Rd | 24 ++ man/PipeOpPreprocTorchTrafoAdjustHue.Rd | 23 ++ ...PipeOpPreprocTorchTrafoAdjustSaturation.Rd | 23 ++ man/PipeOpPreprocTorchTrafoGrayscale.Rd | 23 ++ man/PipeOpPreprocTorchTrafoNop.Rd | 12 + man/PipeOpPreprocTorchTrafoNormalize.Rd | 24 ++ man/PipeOpPreprocTorchTrafoPad.Rd | 25 ++ man/PipeOpPreprocTorchTrafoResize.Rd | 24 ++ man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd | 22 ++ man/PipeOpPreprocTorchTrafoScale.Rd | 12 + man/TorchCallback.Rd | 161 ++++++++ man/TorchDescriptor.Rd | 172 +++++++++ man/TorchIngressToken.Rd | 70 ++++ man/TorchLoss.Rd | 176 +++++++++ man/TorchOptimizer.Rd | 167 ++++++++ man/as_lazy_tensor.Rd | 18 + man/as_torch_callback.Rd | 38 ++ man/as_torch_callbacks.Rd | 52 +++ man/as_torch_loss.Rd | 40 ++ man/as_torch_optimizer.Rd | 41 ++ man/assert_lazy_tensor.Rd | 15 + man/auto_device.Rd | 15 + man/batchgetter_categ.Rd | 22 ++ man/batchgetter_num.Rd | 22 ++ man/callback_set.Rd | 77 ++++ man/equals-.lazy_tensor.Rd | 20 + man/hash_input.lazy_tensor.Rd | 15 + man/is_lazy_tensor.Rd | 15 + man/lazy_tensor.Rd | 18 + man/materialize.Rd | 69 ++++ man/materialize_internal.Rd | 46 +++ man/mlr3torch-package.Rd | 35 ++ man/mlr3torch_callbacks.Rd | 45 +++ man/mlr3torch_losses.Rd | 51 +++ man/mlr3torch_optimizers.Rd | 53 +++ man/mlr_backends_lazy.Rd | 271 +++++++++++++ man/mlr_context_torch.Rd | 167 ++++++++ man/mlr_learners.alexnet.Rd | 2 - man/mlr_learners.mlp.Rd | 4 +- man/mlr_learners.torch_featureless.Rd | 4 +- man/mlr_learners_torch.Rd | 2 - man/mlr_learners_torch_image.Rd | 2 - man/mlr_learners_torch_model.Rd | 4 +- man/mlr_pipeops_module.Rd | 187 +++++++++ man/mlr_pipeops_nn_avg_pool1d.Rd | 179 +++++++++ man/mlr_pipeops_nn_avg_pool2d.Rd | 179 +++++++++ man/mlr_pipeops_nn_avg_pool3d.Rd | 179 +++++++++ man/mlr_pipeops_nn_batch_norm1d.Rd | 177 +++++++++ man/mlr_pipeops_nn_batch_norm2d.Rd | 177 +++++++++ man/mlr_pipeops_nn_batch_norm3d.Rd | 177 +++++++++ man/mlr_pipeops_nn_celu.Rd | 168 ++++++++ man/mlr_pipeops_nn_conv1d.Rd | 183 +++++++++ man/mlr_pipeops_nn_conv2d.Rd | 183 +++++++++ man/mlr_pipeops_nn_conv3d.Rd | 183 +++++++++ man/mlr_pipeops_nn_conv_transpose1d.Rd | 186 +++++++++ man/mlr_pipeops_nn_conv_transpose2d.Rd | 185 +++++++++ man/mlr_pipeops_nn_conv_transpose3d.Rd | 185 +++++++++ man/mlr_pipeops_nn_dropout.Rd | 171 ++++++++ man/mlr_pipeops_nn_elu.Rd | 169 ++++++++ man/mlr_pipeops_nn_flatten.Rd | 167 ++++++++ man/mlr_pipeops_nn_gelu.Rd | 166 ++++++++ man/mlr_pipeops_nn_glu.Rd | 166 ++++++++ man/mlr_pipeops_nn_hardshrink.Rd | 166 ++++++++ man/mlr_pipeops_nn_hardsigmoid.Rd | 163 ++++++++ man/mlr_pipeops_nn_hardtanh.Rd | 164 ++++++++ man/mlr_pipeops_nn_head.Rd | 171 ++++++++ man/mlr_pipeops_nn_layer_norm.Rd | 173 +++++++++ man/mlr_pipeops_nn_leaky_relu.Rd | 169 ++++++++ man/mlr_pipeops_nn_linear.Rd | 171 ++++++++ man/mlr_pipeops_nn_log_sigmoid.Rd | 163 ++++++++ man/mlr_pipeops_nn_max_pool1d.Rd | 185 +++++++++ man/mlr_pipeops_nn_max_pool2d.Rd | 185 +++++++++ man/mlr_pipeops_nn_max_pool3d.Rd | 185 +++++++++ man/mlr_pipeops_nn_merge.Rd | 172 +++++++++ man/mlr_pipeops_nn_merge_cat.Rd | 187 +++++++++ man/mlr_pipeops_nn_merge_prod.Rd | 172 +++++++++ man/mlr_pipeops_nn_merge_sum.Rd | 229 +++++++++++ man/mlr_pipeops_nn_prelu.Rd | 171 ++++++++ man/mlr_pipeops_nn_relu.Rd | 166 ++++++++ man/mlr_pipeops_nn_relu6.Rd | 166 ++++++++ man/mlr_pipeops_nn_reshape.Rd | 168 ++++++++ man/mlr_pipeops_nn_rrelu.Rd | 170 ++++++++ man/mlr_pipeops_nn_selu.Rd | 169 ++++++++ man/mlr_pipeops_nn_sigmoid.Rd | 163 ++++++++ man/mlr_pipeops_nn_softmax.Rd | 167 ++++++++ man/mlr_pipeops_nn_softplus.Rd | 168 ++++++++ man/mlr_pipeops_nn_softshrink.Rd | 166 ++++++++ man/mlr_pipeops_nn_softsign.Rd | 163 ++++++++ man/mlr_pipeops_nn_squeeze.Rd | 314 +++++++++++++++ man/mlr_pipeops_nn_tanh.Rd | 163 ++++++++ man/mlr_pipeops_nn_tanhshrink.Rd | 163 ++++++++ man/mlr_pipeops_nn_threshold.Rd | 170 ++++++++ man/mlr_pipeops_preproc_torch.Rd | 304 +++++++++++++++ man/mlr_pipeops_torch.Rd | 365 ++++++++++++++++++ man/mlr_pipeops_torch_callbacks.Rd | 128 ++++++ man/mlr_pipeops_torch_ingress.Rd | 192 +++++++++ man/mlr_pipeops_torch_ingress_categ.Rd | 182 +++++++++ man/mlr_pipeops_torch_ingress_ltnsr.Rd | 217 +++++++++++ man/mlr_pipeops_torch_ingress_num.Rd | 170 ++++++++ man/mlr_pipeops_torch_loss.Rd | 169 ++++++++ man/mlr_pipeops_torch_model.Rd | 185 +++++++++ man/mlr_pipeops_torch_model_classif.Rd | 170 ++++++++ man/mlr_pipeops_torch_model_regr.Rd | 170 ++++++++ man/mlr_pipeops_torch_optimizer.Rd | 123 ++++++ man/mlr_resamplings_row_roles.Rd | 145 +++++++ man/mlr_tasks_lazy_iris.Rd | 48 +++ man/mlr_tasks_mnist.Rd | 54 +++ man/mlr_tasks_tiny_imagenet.Rd | 46 +++ man/model_descriptor_to_learner.Rd | 36 ++ man/model_descriptor_to_module.Rd | 47 +++ man/model_descriptor_union.Rd | 60 +++ man/nn_graph.Rd | 59 +++ man/nn_merge_cat.Rd | 16 + man/nn_merge_prod.Rd | 11 + man/nn_merge_sum.Rd | 11 + man/nn_reshape.Rd | 15 + man/nn_squeeze.Rd | 15 + man/nn_unsqueeze.Rd | 15 + man/pipeop_preproc_torch.Rd | 72 ++++ man/reset_layer.Rd | 54 +++ man/t_clbk.Rd | 61 +++ man/t_loss.Rd | 51 +++ man/t_opt.Rd | 57 +++ man/task_dataset.Rd | 59 +++ man/torch_callback.Rd | 143 +++++++ 143 files changed, 14880 insertions(+), 12 deletions(-) create mode 100644 man/DataDescriptor.Rd create mode 100644 man/ModelDescriptor.Rd create mode 100644 man/PipeOpPreprocTorchAugmentCenterCrop.Rd create mode 100644 man/PipeOpPreprocTorchAugmentColorJitter.Rd create mode 100644 man/PipeOpPreprocTorchAugmentCrop.Rd create mode 100644 man/PipeOpPreprocTorchAugmentHflip.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRandomAffine.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRandomApply.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRandomChoice.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRandomCrop.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRandomOrder.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd create mode 100644 man/PipeOpPreprocTorchAugmentResizedCrop.Rd create mode 100644 man/PipeOpPreprocTorchAugmentRotate.Rd create mode 100644 man/PipeOpPreprocTorchAugmentVflip.Rd create mode 100644 man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd create mode 100644 man/PipeOpPreprocTorchTrafoAdjustGamma.Rd create mode 100644 man/PipeOpPreprocTorchTrafoAdjustHue.Rd create mode 100644 man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd create mode 100644 man/PipeOpPreprocTorchTrafoGrayscale.Rd create mode 100644 man/PipeOpPreprocTorchTrafoNop.Rd create mode 100644 man/PipeOpPreprocTorchTrafoNormalize.Rd create mode 100644 man/PipeOpPreprocTorchTrafoPad.Rd create mode 100644 man/PipeOpPreprocTorchTrafoResize.Rd create mode 100644 man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd create mode 100644 man/PipeOpPreprocTorchTrafoScale.Rd create mode 100644 man/TorchCallback.Rd create mode 100644 man/TorchDescriptor.Rd create mode 100644 man/TorchIngressToken.Rd create mode 100644 man/TorchLoss.Rd create mode 100644 man/TorchOptimizer.Rd create mode 100644 man/as_lazy_tensor.Rd create mode 100644 man/as_torch_callback.Rd create mode 100644 man/as_torch_callbacks.Rd create mode 100644 man/as_torch_loss.Rd create mode 100644 man/as_torch_optimizer.Rd create mode 100644 man/assert_lazy_tensor.Rd create mode 100644 man/auto_device.Rd create mode 100644 man/batchgetter_categ.Rd create mode 100644 man/batchgetter_num.Rd create mode 100644 man/callback_set.Rd create mode 100644 man/equals-.lazy_tensor.Rd create mode 100644 man/hash_input.lazy_tensor.Rd create mode 100644 man/is_lazy_tensor.Rd create mode 100644 man/lazy_tensor.Rd create mode 100644 man/materialize.Rd create mode 100644 man/materialize_internal.Rd create mode 100644 man/mlr3torch-package.Rd create mode 100644 man/mlr3torch_callbacks.Rd create mode 100644 man/mlr3torch_losses.Rd create mode 100644 man/mlr3torch_optimizers.Rd create mode 100644 man/mlr_backends_lazy.Rd create mode 100644 man/mlr_context_torch.Rd create mode 100644 man/mlr_pipeops_module.Rd create mode 100644 man/mlr_pipeops_nn_avg_pool1d.Rd create mode 100644 man/mlr_pipeops_nn_avg_pool2d.Rd create mode 100644 man/mlr_pipeops_nn_avg_pool3d.Rd create mode 100644 man/mlr_pipeops_nn_batch_norm1d.Rd create mode 100644 man/mlr_pipeops_nn_batch_norm2d.Rd create mode 100644 man/mlr_pipeops_nn_batch_norm3d.Rd create mode 100644 man/mlr_pipeops_nn_celu.Rd create mode 100644 man/mlr_pipeops_nn_conv1d.Rd create mode 100644 man/mlr_pipeops_nn_conv2d.Rd create mode 100644 man/mlr_pipeops_nn_conv3d.Rd create mode 100644 man/mlr_pipeops_nn_conv_transpose1d.Rd create mode 100644 man/mlr_pipeops_nn_conv_transpose2d.Rd create mode 100644 man/mlr_pipeops_nn_conv_transpose3d.Rd create mode 100644 man/mlr_pipeops_nn_dropout.Rd create mode 100644 man/mlr_pipeops_nn_elu.Rd create mode 100644 man/mlr_pipeops_nn_flatten.Rd create mode 100644 man/mlr_pipeops_nn_gelu.Rd create mode 100644 man/mlr_pipeops_nn_glu.Rd create mode 100644 man/mlr_pipeops_nn_hardshrink.Rd create mode 100644 man/mlr_pipeops_nn_hardsigmoid.Rd create mode 100644 man/mlr_pipeops_nn_hardtanh.Rd create mode 100644 man/mlr_pipeops_nn_head.Rd create mode 100644 man/mlr_pipeops_nn_layer_norm.Rd create mode 100644 man/mlr_pipeops_nn_leaky_relu.Rd create mode 100644 man/mlr_pipeops_nn_linear.Rd create mode 100644 man/mlr_pipeops_nn_log_sigmoid.Rd create mode 100644 man/mlr_pipeops_nn_max_pool1d.Rd create mode 100644 man/mlr_pipeops_nn_max_pool2d.Rd create mode 100644 man/mlr_pipeops_nn_max_pool3d.Rd create mode 100644 man/mlr_pipeops_nn_merge.Rd create mode 100644 man/mlr_pipeops_nn_merge_cat.Rd create mode 100644 man/mlr_pipeops_nn_merge_prod.Rd create mode 100644 man/mlr_pipeops_nn_merge_sum.Rd create mode 100644 man/mlr_pipeops_nn_prelu.Rd create mode 100644 man/mlr_pipeops_nn_relu.Rd create mode 100644 man/mlr_pipeops_nn_relu6.Rd create mode 100644 man/mlr_pipeops_nn_reshape.Rd create mode 100644 man/mlr_pipeops_nn_rrelu.Rd create mode 100644 man/mlr_pipeops_nn_selu.Rd create mode 100644 man/mlr_pipeops_nn_sigmoid.Rd create mode 100644 man/mlr_pipeops_nn_softmax.Rd create mode 100644 man/mlr_pipeops_nn_softplus.Rd create mode 100644 man/mlr_pipeops_nn_softshrink.Rd create mode 100644 man/mlr_pipeops_nn_softsign.Rd create mode 100644 man/mlr_pipeops_nn_squeeze.Rd create mode 100644 man/mlr_pipeops_nn_tanh.Rd create mode 100644 man/mlr_pipeops_nn_tanhshrink.Rd create mode 100644 man/mlr_pipeops_nn_threshold.Rd create mode 100644 man/mlr_pipeops_preproc_torch.Rd create mode 100644 man/mlr_pipeops_torch.Rd create mode 100644 man/mlr_pipeops_torch_callbacks.Rd create mode 100644 man/mlr_pipeops_torch_ingress.Rd create mode 100644 man/mlr_pipeops_torch_ingress_categ.Rd create mode 100644 man/mlr_pipeops_torch_ingress_ltnsr.Rd create mode 100644 man/mlr_pipeops_torch_ingress_num.Rd create mode 100644 man/mlr_pipeops_torch_loss.Rd create mode 100644 man/mlr_pipeops_torch_model.Rd create mode 100644 man/mlr_pipeops_torch_model_classif.Rd create mode 100644 man/mlr_pipeops_torch_model_regr.Rd create mode 100644 man/mlr_pipeops_torch_optimizer.Rd create mode 100644 man/mlr_resamplings_row_roles.Rd create mode 100644 man/mlr_tasks_lazy_iris.Rd create mode 100644 man/mlr_tasks_mnist.Rd create mode 100644 man/mlr_tasks_tiny_imagenet.Rd create mode 100644 man/model_descriptor_to_learner.Rd create mode 100644 man/model_descriptor_to_module.Rd create mode 100644 man/model_descriptor_union.Rd create mode 100644 man/nn_graph.Rd create mode 100644 man/nn_merge_cat.Rd create mode 100644 man/nn_merge_prod.Rd create mode 100644 man/nn_merge_sum.Rd create mode 100644 man/nn_reshape.Rd create mode 100644 man/nn_squeeze.Rd create mode 100644 man/nn_unsqueeze.Rd create mode 100644 man/pipeop_preproc_torch.Rd create mode 100644 man/reset_layer.Rd create mode 100644 man/t_clbk.Rd create mode 100644 man/t_loss.Rd create mode 100644 man/t_opt.Rd create mode 100644 man/task_dataset.Rd create mode 100644 man/torch_callback.Rd diff --git a/man/DataDescriptor.Rd b/man/DataDescriptor.Rd new file mode 100644 index 00000000..4141738e --- /dev/null +++ b/man/DataDescriptor.Rd @@ -0,0 +1,168 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/DataDescriptor.R +\name{DataDescriptor} +\alias{DataDescriptor} +\title{Data Descriptor} +\description{ +A data descriptor is a rather internal data structure used in the \code{\link{lazy_tensor}} data type. +In essence it is an annotated \code{\link[torch:dataset]{torch::dataset}} and a preprocessing graph (consisting mosty of \code{\link{PipeOpModule}} +operators). The additional meta data (e.g. pointer, shapes) allows to preprocess \code{\link{lazy_tensor}}s in an +\code{\link[mlr3pipelines:Graph]{mlr3pipelines::Graph}} just like any (non-lazy) data types. +The preprocessing is applied when \code{\link[=materialize]{materialize()}} is called on the \code{\link{lazy_tensor}}. +} +\details{ +While it would be more natural to define this as an S3 class, we opted for an R6 class to avoid the usual +trouble of serializing S3 objects. +If each row contained a DataDescriptor as an S3 class, this would copy the object when serializing. +} +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Create a dataset +dsg = dataset( + initialize = function() self$x = torch_randn(10, 3, 3), + .getitem = function(i) list(x = self$x[i, ]), + .length = function() nrow(self$x) +) +ds = dsg() +dd = DataDescriptor$new(ds, list(x = c(NA, 3, 3))) +dd +} +\seealso{ +ModelDescriptor, lazy_tensor +} +\section{Public fields}{ +\if{html}{\out{
}} +\describe{ +\item{\code{dataset}}{(\code{\link[torch:dataset]{torch::dataset}})\cr +The dataset.} + +\item{\code{graph}}{(\code{\link{Graph}})\cr +The preprocessing graph.} + +\item{\code{dataset_shapes}}{(named \code{list()} of (\code{integer()} or \code{NULL}))\cr +The shapes of the output.} + +\item{\code{input_map}}{(\code{character()})\cr +The input map from the dataset to the preprocessing graph.} + +\item{\code{pointer}}{(\code{character(2)})\cr +The output pointer.} + +\item{\code{pointer_shape}}{(\code{integer()} | \code{NULL})\cr +The shape of the output indicated by \code{pointer}.} + +\item{\code{dataset_hash}}{(\code{character(1)})\cr +Hash for the wrapped dataset.} + +\item{\code{hash}}{(\code{character(1)})\cr +Hash for the data descriptor.} + +\item{\code{graph_input}}{(\code{character()})\cr +The input channels of the preprocessing graph (cached to save time).} + +\item{\code{pointer_shape_predict}}{(\code{integer()} or \code{NULL})\cr +Internal use only.} +} +\if{html}{\out{
}} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-DataDescriptor-new}{\code{DataDescriptor$new()}} +\item \href{#method-DataDescriptor-print}{\code{DataDescriptor$print()}} +\item \href{#method-DataDescriptor-clone}{\code{DataDescriptor$clone()}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-DataDescriptor-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{DataDescriptor$new( + dataset, + dataset_shapes, + graph = NULL, + input_map = NULL, + pointer = NULL, + pointer_shape = NULL, + pointer_shape_predict = NULL, + clone_graph = TRUE +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{dataset}}{(\code{\link[torch:dataset]{torch::dataset}})\cr +The torch dataset.} + +\item{\code{dataset_shapes}}{(named \code{list()} of (\code{integer()} or \code{NULL}))\cr +The shapes of the output. +Names are the elements of the list returned by the dataset. +If the shape is not \code{NULL} (unknown, e.g. for images of different sizes) the first dimension must be \code{NA} to +indicate the batch dimension.} + +\item{\code{graph}}{(\code{\link{Graph}})\cr +The preprocessing graph. +If left \code{NULL}, no preprocessing is applied to the data and \code{input_map}, \code{pointer}, \code{pointer_shape}, and +\code{pointer_shape_predict} are inferred in case the dataset returns only one element.} + +\item{\code{input_map}}{(\code{character()})\cr +Character vector that must have the same length as the input of the graph. +Specifies how the data from the \code{dataset} is fed into the preprocessing graph.} + +\item{\code{pointer}}{(\code{character(2)} | \code{NULL})\cr +Points to an output channel within \code{graph}: +Element 1 is the \code{PipeOp}'s id and element 2 is that \code{PipeOp}'s output channel.} + +\item{\code{pointer_shape}}{(\code{integer()} | \code{NULL})\cr +Shape of the output indicated by \code{pointer}.} + +\item{\code{pointer_shape_predict}}{(\code{integer()} or \code{NULL})\cr +Internal use only. +Used in a \code{\link{Graph}} to anticipate possible mismatches between train and predict shapes.} + +\item{\code{clone_graph}}{(\code{logical(1)})\cr +Whether to clone the preprocessing graph.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-DataDescriptor-print}{}}} +\subsection{Method \code{print()}}{ +Prints the object +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{DataDescriptor$print(...)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{...}}{(any)\cr +Unused} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-DataDescriptor-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{DataDescriptor$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/ModelDescriptor.Rd b/man/ModelDescriptor.Rd new file mode 100644 index 00000000..38a350f9 --- /dev/null +++ b/man/ModelDescriptor.Rd @@ -0,0 +1,91 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ModelDescriptor.R +\name{ModelDescriptor} +\alias{ModelDescriptor} +\title{Represent a Model with Meta-Info} +\usage{ +ModelDescriptor( + graph, + ingress, + task, + optimizer = NULL, + loss = NULL, + callbacks = NULL, + pointer = NULL, + pointer_shape = NULL +) +} +\arguments{ +\item{graph}{(\code{\link[mlr3pipelines:Graph]{Graph}})\cr +\code{Graph} of \code{\link{PipeOpModule}} and \code{\link{PipeOpNOP}} operators.} + +\item{ingress}{(uniquely named \code{list} of \code{TorchIngressToken})\cr +List of inputs that go into \code{graph}. Names of this must be a subset of \code{graph$input$name}.} + +\item{task}{(\code{\link[mlr3:Task]{Task}})\cr +(Training)-Task for which the model is being built. May be necessary for for some aspects of what loss to use etc.} + +\item{optimizer}{(\code{\link{TorchOptimizer}} | \code{NULL})\cr +Additional info: what optimizer to use.} + +\item{loss}{(\code{\link{TorchLoss}} | \code{NULL})\cr +Additional info: what loss to use.} + +\item{callbacks}{(A \code{list} of \code{\link{CallbackSet}} or \code{NULL})\cr +Additional info: what callbacks to use.} + +\item{pointer}{(\code{character(2)} | \code{NULL})\cr +Indicating an element on which a model is. Points to an output channel within \code{graph}: +Element 1 is the \code{PipeOp}'s id and element 2 is that \code{PipeOp}'s output channel.} + +\item{pointer_shape}{(\code{integer} | \code{NULL})\cr +Shape of the output indicated by \code{pointer}.} +} +\value{ +(\code{ModelDescriptor}) +} +\description{ +Represents a \emph{model}; possibly a complete model, possibly one in the process of being built up. + +This model takes input tensors of shapes \code{shapes_in} and +pipes them through \code{graph}. Input shapes get mapped to input channels of \code{graph}. +Output shapes are named by the output channels of \code{graph}; it is also possible +to represent no-ops on tensors, in which case names of input and output should be identical. + +\code{ModelDescriptor} objects typically represent partial models being built up, in which case the \code{pointer} slot +indicates a specific point in the graph that produces a tensor of shape \code{pointer_shape}, on which the graph should +be extended. +It is allowed for the \code{graph} in this structure to be modified by-reference in different parts of the code. +However, these modifications may never add edges with elements of the \code{Graph} as destination. In particular, no +element of \code{graph$input} may be removed by reference, e.g. by adding an edge to the \code{Graph} that has the input +channel of a \code{PipeOp} that was previously without parent as its destination. + +In most cases it is better to create a specific \code{ModelDescriptor} by training a \code{\link{Graph}} consisting (mostly) of +operators \code{\link{PipeOpTorchIngress}}, \code{\link{PipeOpTorch}}, \code{\link{PipeOpTorchLoss}}, \code{\link{PipeOpTorchOptimizer}}, and +\code{\link{PipeOpTorchCallbacks}}. + +A \code{ModelDescriptor} can be converted to a \code{\link{nn_graph}} via \code{\link{model_descriptor_to_module}}. +} +\seealso{ +Other Model Configuration: +\code{\link{mlr_pipeops_torch_callbacks}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_optimizer}}, +\code{\link{model_descriptor_union}()} + +Other Graph Network: +\code{\link{TorchIngressToken}()}, +\code{\link{mlr_learners_torch_model}}, +\code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{model_descriptor_to_learner}()}, +\code{\link{model_descriptor_to_module}()}, +\code{\link{model_descriptor_union}()}, +\code{\link{nn_graph}()} +} +\concept{Graph Network} +\concept{Model Configuration} diff --git a/man/PipeOpPreprocTorchAugmentCenterCrop.Rd b/man/PipeOpPreprocTorchAugmentCenterCrop.Rd new file mode 100644 index 00000000..6a0c706e --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentCenterCrop.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_center_crop} +\alias{mlr_pipeops_preproc_torch.augment_center_crop} +\alias{PipeOpPreprocTorchAugmentCenterCrop} +\title{PipeOpPreprocTorchAugmentCenterCrop} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_center_crop]{torchvision::transform_center_crop}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + size \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentColorJitter.Rd b/man/PipeOpPreprocTorchAugmentColorJitter.Rd new file mode 100644 index 00000000..bf55d6b6 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentColorJitter.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_color_jitter} +\alias{mlr_pipeops_preproc_torch.augment_color_jitter} +\alias{PipeOpPreprocTorchAugmentColorJitter} +\title{PipeOpPreprocTorchAugmentColorJitter} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_color_jitter]{torchvision::transform_color_jitter}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + brightness \tab numeric \tab 0 \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr + contrast \tab numeric \tab 0 \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr + saturation \tab numeric \tab 0 \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr + hue \tab numeric \tab 0 \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentCrop.Rd b/man/PipeOpPreprocTorchAugmentCrop.Rd new file mode 100644 index 00000000..15aa7624 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentCrop.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_crop} +\alias{mlr_pipeops_preproc_torch.augment_crop} +\alias{PipeOpPreprocTorchAugmentCrop} +\title{PipeOpPreprocTorchAugmentCrop} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_crop]{torchvision::transform_crop}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + top \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + left \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + height \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + width \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentHflip.Rd b/man/PipeOpPreprocTorchAugmentHflip.Rd new file mode 100644 index 00000000..39f23af7 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentHflip.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_hflip} +\alias{mlr_pipeops_preproc_torch.augment_hflip} +\alias{PipeOpPreprocTorchAugmentHflip} +\title{PipeOpPreprocTorchAugmentHflip} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_hflip]{torchvision::transform_hflip}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRandomAffine.Rd b/man/PipeOpPreprocTorchAugmentRandomAffine.Rd new file mode 100644 index 00000000..043feaab --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRandomAffine.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_random_affine} +\alias{mlr_pipeops_preproc_torch.augment_random_affine} +\alias{PipeOpPreprocTorchAugmentRandomAffine} +\title{PipeOpPreprocTorchAugmentRandomAffine} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_random_affine]{torchvision::transform_random_affine}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + degrees \tab untyped \tab - \tab \tab - \cr + translate \tab untyped \tab \tab \tab - \cr + scale \tab untyped \tab \tab \tab - \cr + resample \tab integer \tab 0 \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + fillcolor \tab untyped \tab 0 \tab \tab - \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRandomApply.Rd b/man/PipeOpPreprocTorchAugmentRandomApply.Rd new file mode 100644 index 00000000..169d6b1c --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRandomApply.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_random_apply} +\alias{mlr_pipeops_preproc_torch.augment_random_apply} +\alias{PipeOpPreprocTorchAugmentRandomApply} +\title{PipeOpPreprocTorchAugmentRandomApply} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_random_apply]{torchvision::transform_random_apply}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + transforms \tab untyped \tab - \tab \tab - \cr + p \tab numeric \tab 0.5 \tab \tab \eqn{[0, 1]}{[0, 1]} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRandomChoice.Rd b/man/PipeOpPreprocTorchAugmentRandomChoice.Rd new file mode 100644 index 00000000..f73d415f --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRandomChoice.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_random_choice} +\alias{mlr_pipeops_preproc_torch.augment_random_choice} +\alias{PipeOpPreprocTorchAugmentRandomChoice} +\title{PipeOpPreprocTorchAugmentRandomChoice} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_random_choice]{torchvision::transform_random_choice}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + transforms \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRandomCrop.Rd b/man/PipeOpPreprocTorchAugmentRandomCrop.Rd new file mode 100644 index 00000000..c07d5c90 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRandomCrop.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_random_crop} +\alias{mlr_pipeops_preproc_torch.augment_random_crop} +\alias{PipeOpPreprocTorchAugmentRandomCrop} +\title{PipeOpPreprocTorchAugmentRandomCrop} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_random_crop]{torchvision::transform_random_crop}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + size \tab untyped \tab - \tab \cr + padding \tab untyped \tab \tab \cr + pad_if_needed \tab logical \tab FALSE \tab TRUE, FALSE \cr + fill \tab untyped \tab 0 \tab \cr + padding_mode \tab character \tab constant \tab constant, edge, reflect, symmetric \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd b/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd new file mode 100644 index 00000000..49522bb6 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRandomHorizontalFlip.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_random_horizontal_flip} +\alias{mlr_pipeops_preproc_torch.augment_random_horizontal_flip} +\alias{PipeOpPreprocTorchAugmentRandomHorizontalFlip} +\title{PipeOpPreprocTorchAugmentRandomHorizontalFlip} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_random_horizontal_flip]{torchvision::transform_random_horizontal_flip}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + p \tab numeric \tab 0.5 \tab \tab \eqn{[0, 1]}{[0, 1]} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRandomOrder.Rd b/man/PipeOpPreprocTorchAugmentRandomOrder.Rd new file mode 100644 index 00000000..ed629317 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRandomOrder.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_random_order} +\alias{mlr_pipeops_preproc_torch.augment_random_order} +\alias{PipeOpPreprocTorchAugmentRandomOrder} +\title{PipeOpPreprocTorchAugmentRandomOrder} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_random_order]{torchvision::transform_random_order}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + transforms \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd b/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd new file mode 100644 index 00000000..a5f74d63 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRandomResizedCrop.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_random_resized_crop} +\alias{mlr_pipeops_preproc_torch.augment_random_resized_crop} +\alias{PipeOpPreprocTorchAugmentRandomResizedCrop} +\title{PipeOpPreprocTorchAugmentRandomResizedCrop} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_random_resized_crop]{torchvision::transform_random_resized_crop}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + size \tab untyped \tab - \tab \tab - \cr + scale \tab untyped \tab c , 0.08, 1 \tab \tab - \cr + ratio \tab untyped \tab c , 3/4, 4/3 \tab \tab - \cr + interpolation \tab integer \tab 2 \tab \tab \eqn{[0, 3]}{[0, 3]} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd b/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd new file mode 100644 index 00000000..5781cfba --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRandomVerticalFlip.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_random_vertical_flip} +\alias{mlr_pipeops_preproc_torch.augment_random_vertical_flip} +\alias{PipeOpPreprocTorchAugmentRandomVerticalFlip} +\title{PipeOpPreprocTorchAugmentRandomVerticalFlip} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_random_vertical_flip]{torchvision::transform_random_vertical_flip}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + p \tab numeric \tab 0.5 \tab \tab \eqn{[0, 1]}{[0, 1]} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentResizedCrop.Rd b/man/PipeOpPreprocTorchAugmentResizedCrop.Rd new file mode 100644 index 00000000..799dbc10 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentResizedCrop.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_resized_crop} +\alias{mlr_pipeops_preproc_torch.augment_resized_crop} +\alias{PipeOpPreprocTorchAugmentResizedCrop} +\title{PipeOpPreprocTorchAugmentResizedCrop} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_resized_crop]{torchvision::transform_resized_crop}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + top \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + left \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + height \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + width \tab integer \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + size \tab untyped \tab - \tab \tab - \cr + interpolation \tab integer \tab 2 \tab \tab \eqn{[0, 3]}{[0, 3]} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentRotate.Rd b/man/PipeOpPreprocTorchAugmentRotate.Rd new file mode 100644 index 00000000..6508b070 --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentRotate.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_rotate} +\alias{mlr_pipeops_preproc_torch.augment_rotate} +\alias{PipeOpPreprocTorchAugmentRotate} +\title{PipeOpPreprocTorchAugmentRotate} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_rotate]{torchvision::transform_rotate}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + angle \tab untyped \tab - \tab \tab - \cr + resample \tab integer \tab 0 \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + expand \tab logical \tab FALSE \tab TRUE, FALSE \tab - \cr + center \tab untyped \tab \tab \tab - \cr + fill \tab untyped \tab \tab \tab - \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr +} +} + diff --git a/man/PipeOpPreprocTorchAugmentVflip.Rd b/man/PipeOpPreprocTorchAugmentVflip.Rd new file mode 100644 index 00000000..36c15cfe --- /dev/null +++ b/man/PipeOpPreprocTorchAugmentVflip.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.augment_vflip} +\alias{mlr_pipeops_preproc_torch.augment_vflip} +\alias{PipeOpPreprocTorchAugmentVflip} +\title{PipeOpPreprocTorchAugmentVflip} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_vflip]{torchvision::transform_vflip}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd b/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd new file mode 100644 index 00000000..fe636d29 --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoAdjustBrightness.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_adjust_brightness} +\alias{mlr_pipeops_preproc_torch.trafo_adjust_brightness} +\alias{PipeOpPreprocTorchTrafoAdjustBrightness} +\title{PipeOpPreprocTorchTrafoAdjustBrightness} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_adjust_brightness]{torchvision::transform_adjust_brightness}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + brightness_factor \tab numeric \tab - \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd b/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd new file mode 100644 index 00000000..a2bcef11 --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoAdjustGamma.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_adjust_gamma} +\alias{mlr_pipeops_preproc_torch.trafo_adjust_gamma} +\alias{PipeOpPreprocTorchTrafoAdjustGamma} +\title{PipeOpPreprocTorchTrafoAdjustGamma} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_adjust_gamma]{torchvision::transform_adjust_gamma}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + gamma \tab numeric \tab - \tab \tab \eqn{[0, \infty)}{[0, Inf)} \cr + gain \tab numeric \tab 1 \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoAdjustHue.Rd b/man/PipeOpPreprocTorchTrafoAdjustHue.Rd new file mode 100644 index 00000000..1cc75a96 --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoAdjustHue.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_adjust_hue} +\alias{mlr_pipeops_preproc_torch.trafo_adjust_hue} +\alias{PipeOpPreprocTorchTrafoAdjustHue} +\title{PipeOpPreprocTorchTrafoAdjustHue} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_adjust_hue]{torchvision::transform_adjust_hue}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + hue_factor \tab numeric \tab - \tab \tab \eqn{[-0.5, 0.5]}{[-0.5, 0.5]} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd b/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd new file mode 100644 index 00000000..ced93824 --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoAdjustSaturation.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_adjust_saturation} +\alias{mlr_pipeops_preproc_torch.trafo_adjust_saturation} +\alias{PipeOpPreprocTorchTrafoAdjustSaturation} +\title{PipeOpPreprocTorchTrafoAdjustSaturation} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_adjust_saturation]{torchvision::transform_adjust_saturation}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + saturation_factor \tab numeric \tab - \tab \tab \eqn{(-\infty, \infty)}{(-Inf, Inf)} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoGrayscale.Rd b/man/PipeOpPreprocTorchTrafoGrayscale.Rd new file mode 100644 index 00000000..014d8fee --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoGrayscale.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_grayscale} +\alias{mlr_pipeops_preproc_torch.trafo_grayscale} +\alias{PipeOpPreprocTorchTrafoGrayscale} +\title{PipeOpPreprocTorchTrafoGrayscale} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_grayscale]{torchvision::transform_grayscale}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{lllll}{ + Id \tab Type \tab Default \tab Levels \tab Range \cr + num_output_channels \tab integer \tab - \tab \tab \eqn{[1, 3]}{[1, 3]} \cr + stages \tab character \tab - \tab train, predict, both \tab - \cr + affect_columns \tab untyped \tab selector_all \tab \tab - \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoNop.Rd b/man/PipeOpPreprocTorchTrafoNop.Rd new file mode 100644 index 00000000..1d8eb892 --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoNop.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_nop} +\alias{mlr_pipeops_preproc_torch.trafo_nop} +\alias{PipeOpPreprocTorchTrafoNop} +\title{PipeOpPreprocTorchTrafoNop} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Does nothing. +} diff --git a/man/PipeOpPreprocTorchTrafoNormalize.Rd b/man/PipeOpPreprocTorchTrafoNormalize.Rd new file mode 100644 index 00000000..a802514b --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoNormalize.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_normalize} +\alias{mlr_pipeops_preproc_torch.trafo_normalize} +\alias{PipeOpPreprocTorchTrafoNormalize} +\title{PipeOpPreprocTorchTrafoNormalize} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_normalize]{torchvision::transform_normalize}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + mean \tab untyped \tab - \tab \cr + std \tab untyped \tab - \tab \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoPad.Rd b/man/PipeOpPreprocTorchTrafoPad.Rd new file mode 100644 index 00000000..b9c7f1ca --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoPad.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_pad} +\alias{mlr_pipeops_preproc_torch.trafo_pad} +\alias{PipeOpPreprocTorchTrafoPad} +\title{PipeOpPreprocTorchTrafoPad} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_pad]{torchvision::transform_pad}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + padding \tab untyped \tab - \tab \cr + fill \tab untyped \tab 0 \tab \cr + padding_mode \tab character \tab constant \tab constant, edge, reflect, symmetric \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoResize.Rd b/man/PipeOpPreprocTorchTrafoResize.Rd new file mode 100644 index 00000000..b031940b --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoResize.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_resize} +\alias{mlr_pipeops_preproc_torch.trafo_resize} +\alias{PipeOpPreprocTorchTrafoResize} +\title{PipeOpPreprocTorchTrafoResize} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_resize]{torchvision::transform_resize}}, +see there for more information on the parameters. +The preprocessing is applied to the whole batch. +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + size \tab untyped \tab - \tab \cr + interpolation \tab character \tab 2 \tab Undefined, Bartlett, Blackman, Bohman, Box, Catrom, Cosine, Cubic, Gaussian, Hamming, \link{...} \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd b/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd new file mode 100644 index 00000000..10a89e1a --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoRgbToGrayscale.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_rgb_to_grayscale} +\alias{mlr_pipeops_preproc_torch.trafo_rgb_to_grayscale} +\alias{PipeOpPreprocTorchTrafoRgbToGrayscale} +\title{PipeOpPreprocTorchTrafoRgbToGrayscale} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Calls \code{\link[torchvision:transform_rgb_to_grayscale]{torchvision::transform_rgb_to_grayscale}}, +see there for more information on the parameters. +The preprocessing is applied row wise (no batch dimension). +} +\section{Parameters}{ +\tabular{llll}{ + Id \tab Type \tab Default \tab Levels \cr + stages \tab character \tab - \tab train, predict, both \cr + affect_columns \tab untyped \tab selector_all \tab \cr +} +} + diff --git a/man/PipeOpPreprocTorchTrafoScale.Rd b/man/PipeOpPreprocTorchTrafoScale.Rd new file mode 100644 index 00000000..0a3cac68 --- /dev/null +++ b/man/PipeOpPreprocTorchTrafoScale.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/preprocess.R +\name{mlr_pipeops_preproc_torch.trafo_scale} +\alias{mlr_pipeops_preproc_torch.trafo_scale} +\alias{PipeOpPreprocTorchTrafoScale} +\title{PipeOpPreprocTorchTrafoNop} +\format{ +\code{\link{R6Class}} inheriting from \code{\link{PipeOpTaskPreprocTorch}}. +} +\description{ +Applies \code{(x - mean) / sd} to a tensor \code{x}. +} diff --git a/man/TorchCallback.Rd b/man/TorchCallback.Rd new file mode 100644 index 00000000..9af6c561 --- /dev/null +++ b/man/TorchCallback.Rd @@ -0,0 +1,161 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TorchCallback.R +\name{TorchCallback} +\alias{TorchCallback} +\title{Torch Callback} +\description{ +This wraps a \code{\link{CallbackSet}} and annotates it with metadata, most importantly a \code{\link{ParamSet}}. +The callback is created for the given parameter values by calling the \verb{$generate()} method. + +This class is usually used to configure the callback of a torch learner, e.g. when constructing +a learner of in a \code{\link{ModelDescriptor}}. + +For a list of available callbacks, see \code{\link{mlr3torch_callbacks}}. +To conveniently retrieve a \code{\link{TorchCallback}}, use \code{\link[=t_clbk]{t_clbk()}}. +} +\section{Parameters}{ + +Defined by the constructor argument \code{param_set}. +If no parameter set is provided during construction, the parameter set is constructed by creating a parameter +for each argument of the wrapped loss function, where the parametes are then of type \code{\link{ParamUty}}. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Create a new torch callback from an existing callback set +torch_callback = TorchCallback$new(CallbackSetCheckpoint) +# The parameters are inferred +torch_callback$param_set + +# Retrieve a torch callback from the dictionary +torch_callback = t_clbk("checkpoint", + path = tempfile(), freq = 1 +) +torch_callback +torch_callback$label +torch_callback$id + +# open the help page of the wrapped callback set +# torch_callback$help() + +# Create the callback set +callback = torch_callback$generate() +callback +# is the same as +CallbackSetCheckpoint$new( + path = tempfile(), freq = 1 +) + +# Use in a learner +learner = lrn("regr.mlp", callbacks = t_clbk("checkpoint")) +# the parameters of the callback are added to the learner's parameter set +learner$param_set + +} +\seealso{ +Other Callback: +\code{\link{as_torch_callback}()}, +\code{\link{as_torch_callbacks}()}, +\code{\link{callback_set}()}, +\code{\link{mlr3torch_callbacks}}, +\code{\link{mlr_callback_set}}, +\code{\link{mlr_callback_set.checkpoint}}, +\code{\link{mlr_callback_set.progress}}, +\code{\link{mlr_context_torch}}, +\code{\link{t_clbk}()}, +\code{\link{torch_callback}()} + +Other Torch Descriptor: +\code{\link{TorchDescriptor}}, +\code{\link{TorchLoss}}, +\code{\link{TorchOptimizer}}, +\code{\link{as_torch_callbacks}()}, +\code{\link{as_torch_loss}()}, +\code{\link{as_torch_optimizer}()}, +\code{\link{mlr3torch_losses}}, +\code{\link{mlr3torch_optimizers}}, +\code{\link{t_clbk}()}, +\code{\link{t_loss}()}, +\code{\link{t_opt}()} +} +\concept{Callback} +\concept{Torch Descriptor} +\section{Super class}{ +\code{mlr3torch::TorchDescriptor} -> \code{TorchCallback} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-TorchCallback-new}{\code{TorchCallback$new()}} +\item \href{#method-TorchCallback-clone}{\code{TorchCallback$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TorchCallback-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{TorchCallback$new( + callback_generator, + param_set = NULL, + id = NULL, + label = NULL, + packages = NULL, + man = NULL +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{callback_generator}}{(\code{R6ClassGenerator})\cr +The class generator for the callback that is being wrapped.} + +\item{\code{param_set}}{(\code{ParamSet} or \code{NULL})\cr +The parameter set. If \code{NULL} (default) it is inferred from \code{callback_generator}.} + +\item{\code{id}}{(\code{character(1)})\cr +The id for of the new object.} + +\item{\code{label}}{(\code{character(1)})\cr +Label for the new instance.} + +\item{\code{packages}}{(\code{character()})\cr +The R packages this object depends on.} + +\item{\code{man}}{(\code{character(1)})\cr +String in the format \verb{[pkg]::[topic]} pointing to a manual page for this object. +The referenced help package can be opened via method \verb{$help()}.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TorchCallback-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{TorchCallback$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/TorchDescriptor.Rd b/man/TorchDescriptor.Rd new file mode 100644 index 00000000..aefa09f8 --- /dev/null +++ b/man/TorchDescriptor.Rd @@ -0,0 +1,172 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TorchDescriptor.R +\name{TorchDescriptor} +\alias{TorchDescriptor} +\title{Base Class for Torch Descriptors} +\description{ +Abstract Base Class from which \code{\link{TorchLoss}}, \code{\link{TorchOptimizer}}, and \code{\link{TorchCallback}} inherit. +This class wraps a generator (R6Class Generator or the torch version of such a generator) and annotates it +with metadata such as a \code{\link{ParamSet}}, a label, an ID, packages, or a manual page. + +The parameters are the construction arguments of the wrapped generator and the parameter \verb{$values} are passed +to the generator when calling the public method \verb{$generate()}. +} +\section{Parameters}{ + +Defined by the constructor argument \code{param_set}. +} + +\seealso{ +Other Torch Descriptor: +\code{\link{TorchCallback}}, +\code{\link{TorchLoss}}, +\code{\link{TorchOptimizer}}, +\code{\link{as_torch_callbacks}()}, +\code{\link{as_torch_loss}()}, +\code{\link{as_torch_optimizer}()}, +\code{\link{mlr3torch_losses}}, +\code{\link{mlr3torch_optimizers}}, +\code{\link{t_clbk}()}, +\code{\link{t_loss}()}, +\code{\link{t_opt}()} +} +\concept{Torch Descriptor} +\section{Public fields}{ +\if{html}{\out{
}} +\describe{ +\item{\code{label}}{(\code{character(1)})\cr +Label for this object. +Can be used in tables, plot and text output instead of the ID.} + +\item{\code{param_set}}{(\link[paradox:ParamSet]{paradox::ParamSet})\cr +Set of hyperparameters.} + +\item{\code{packages}}{(\code{character(1)})\cr +Set of required packages. +These packages are loaded, but not attached.} + +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the object. +Used in tables, plot and text output.} + +\item{\code{generator}}{The wrapped generator that is described.} + +\item{\code{man}}{(\code{character(1)})\cr +String in the format \verb{[pkg]::[topic]} pointing to a manual page for this object.} +} +\if{html}{\out{
}} +} +\section{Active bindings}{ +\if{html}{\out{
}} +\describe{ +\item{\code{phash}}{(\code{character(1)})\cr +Hash (unique identifier) for this partial object, excluding some components +which are varied systematically (e.g. the parameter values).} +} +\if{html}{\out{
}} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-TorchDescriptor-new}{\code{TorchDescriptor$new()}} +\item \href{#method-TorchDescriptor-print}{\code{TorchDescriptor$print()}} +\item \href{#method-TorchDescriptor-generate}{\code{TorchDescriptor$generate()}} +\item \href{#method-TorchDescriptor-help}{\code{TorchDescriptor$help()}} +\item \href{#method-TorchDescriptor-clone}{\code{TorchDescriptor$clone()}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TorchDescriptor-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{TorchDescriptor$new( + generator, + id = NULL, + param_set = NULL, + packages = NULL, + label = NULL, + man = NULL +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{generator}}{The wrapped generator that is described.} + +\item{\code{id}}{(\code{character(1)})\cr +The id for of the new object.} + +\item{\code{param_set}}{(\code{paradox::ParamSet})\cr +The parameter set.} + +\item{\code{packages}}{(\code{character()})\cr +The R packages this object depends on.} + +\item{\code{label}}{(\code{character(1)})\cr +Label for the new instance.} + +\item{\code{man}}{(\code{character(1)})\cr +String in the format \verb{[pkg]::[topic]} pointing to a manual page for this object. +The referenced help package can be opened via method \verb{$help()}.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TorchDescriptor-print}{}}} +\subsection{Method \code{print()}}{ +Prints the object +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{TorchDescriptor$print(...)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{...}}{any} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TorchDescriptor-generate}{}}} +\subsection{Method \code{generate()}}{ +Calls the generator with the given parameter values. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{TorchDescriptor$generate()}\if{html}{\out{
}} +} + +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TorchDescriptor-help}{}}} +\subsection{Method \code{help()}}{ +Displays the help file of the wrapped object. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{TorchDescriptor$help()}\if{html}{\out{
}} +} + +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TorchDescriptor-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{TorchDescriptor$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/TorchIngressToken.Rd b/man/TorchIngressToken.Rd new file mode 100644 index 00000000..a558462d --- /dev/null +++ b/man/TorchIngressToken.Rd @@ -0,0 +1,70 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchIngress.R +\name{TorchIngressToken} +\alias{TorchIngressToken} +\title{Torch Ingress Token} +\usage{ +TorchIngressToken(features, batchgetter, shape) +} +\arguments{ +\item{features}{(\code{character})\cr +Features on which the batchgetter will operate.} + +\item{batchgetter}{(\code{function})\cr +Function with two arguments: \code{data} and \code{device}. This function is given +the output of \code{Task$data(rows = batch_indices, cols = features)} +and it should produce a tensor of shape \code{shape_out}.} + +\item{shape}{(\code{integer})\cr +Shape that \code{batchgetter} will produce. Batch-dimension should be included as \code{NA}.} +} +\value{ +\code{TorchIngressToken} object. +} +\description{ +This function creates an S3 class of class \code{"TorchIngressToken"}, which is an internal data structure. +It contains the (meta-)information of how a batch is generated from a \code{\link{Task}} and fed into an entry point +of the neural network. It is stored as the \code{ingress} field in a \code{\link{ModelDescriptor}}. +} +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Define a task for which we want to define an ingress token +task = tsk("iris") + +# We create an ingress token for two feature Sepal.Length and Petal.Length: +# We have to specify the features, the batchgetter and the shape +features = c("Sepal.Length", "Petal.Length") +# As a batchgetter we use batchgetter_num + +batch_dt = task$data(rows = 1:10, cols =features) +batch_dt +batch_tensor = batchgetter_num(batch_dt, "cpu") +batch_tensor + +# The shape is unknown in the first dimension (batch dimension) + +ingress_token = TorchIngressToken( + features = features, + batchgetter = batchgetter_num, + shape = c(NA, 2) +) +ingress_token + +} +\seealso{ +Other Graph Network: +\code{\link{ModelDescriptor}()}, +\code{\link{mlr_learners_torch_model}}, +\code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{model_descriptor_to_learner}()}, +\code{\link{model_descriptor_to_module}()}, +\code{\link{model_descriptor_union}()}, +\code{\link{nn_graph}()} +} +\concept{Graph Network} diff --git a/man/TorchLoss.Rd b/man/TorchLoss.Rd new file mode 100644 index 00000000..2f3b3543 --- /dev/null +++ b/man/TorchLoss.Rd @@ -0,0 +1,176 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TorchLoss.R +\name{TorchLoss} +\alias{TorchLoss} +\title{Torch Loss} +\description{ +This wraps a \code{torch::nn_loss} and annotates it with metadata, most importantly a \code{\link{ParamSet}}. +The loss function is created for the given parameter values by calling the \verb{$generate()} method. + +This class is usually used to configure the loss function of a torch learner, e.g. +when construcing a learner or in a \code{\link{ModelDescriptor}}. + +For a list of available losses, see \code{\link{mlr3torch_losses}}. +Items from this dictionary can be retrieved using \code{\link[=t_loss]{t_loss()}}. +} +\section{Parameters}{ + +Defined by the constructor argument \code{param_set}. +If no parameter set is provided during construction, the parameter set is constructed by creating a parameter +for each argument of the wrapped loss function, where the parametes are then of type \code{\link{ParamUty}}. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Create a new torch loss +torch_loss = TorchLoss$new(torch_loss = nn_mse_loss, task_types = "regr") +torch_loss +# the parameters are inferred +torch_loss$param_set + +# Retrieve a loss from the dictionary: +torch_loss = t_loss("mse", reduction = "mean") +# is the same as +torch_loss +torch_loss$param_set +torch_loss$label +torch_loss$task_types +torch_loss$id + +# Create the loss function +loss_fn = torch_loss$generate() +loss_fn +# Is the same as +nn_mse_loss(reduction = "mean") + +# open the help page of the wrapped loss function +# torch_loss$help() + +# Use in a learner +learner = lrn("regr.mlp", loss = t_loss("mse")) +# The parameters of the loss are added to the learner's parameter set +learner$param_set +} +\seealso{ +Other Torch Descriptor: +\code{\link{TorchCallback}}, +\code{\link{TorchDescriptor}}, +\code{\link{TorchOptimizer}}, +\code{\link{as_torch_callbacks}()}, +\code{\link{as_torch_loss}()}, +\code{\link{as_torch_optimizer}()}, +\code{\link{mlr3torch_losses}}, +\code{\link{mlr3torch_optimizers}}, +\code{\link{t_clbk}()}, +\code{\link{t_loss}()}, +\code{\link{t_opt}()} +} +\concept{Torch Descriptor} +\section{Super class}{ +\code{mlr3torch::TorchDescriptor} -> \code{TorchLoss} +} +\section{Public fields}{ +\if{html}{\out{
}} +\describe{ +\item{\code{task_types}}{(\code{character()})\cr +The task types this loss supports.} +} +\if{html}{\out{
}} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-TorchLoss-new}{\code{TorchLoss$new()}} +\item \href{#method-TorchLoss-print}{\code{TorchLoss$print()}} +\item \href{#method-TorchLoss-clone}{\code{TorchLoss$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TorchLoss-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{TorchLoss$new( + torch_loss, + task_types, + param_set = NULL, + id = NULL, + label = NULL, + packages = NULL, + man = NULL +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{torch_loss}}{(\code{nn_loss})\cr +The loss module.} + +\item{\code{task_types}}{(\code{character()})\cr +The task types supported by this loss.} + +\item{\code{param_set}}{(\code{\link{ParamSet}} or \code{NULL})\cr +The parameter set. If \code{NULL} (default) it is inferred from \code{torch_loss}.} + +\item{\code{id}}{(\code{character(1)})\cr +The id for of the new object.} + +\item{\code{label}}{(\code{character(1)})\cr +Label for the new instance.} + +\item{\code{packages}}{(\code{character()})\cr +The R packages this object depends on.} + +\item{\code{man}}{(\code{character(1)})\cr +String in the format \verb{[pkg]::[topic]} pointing to a manual page for this object. +The referenced help package can be opened via method \verb{$help()}.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TorchLoss-print}{}}} +\subsection{Method \code{print()}}{ +Prints the object +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{TorchLoss$print(...)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{...}}{any} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TorchLoss-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{TorchLoss$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/TorchOptimizer.Rd b/man/TorchOptimizer.Rd new file mode 100644 index 00000000..544359a7 --- /dev/null +++ b/man/TorchOptimizer.Rd @@ -0,0 +1,167 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TorchOptimizer.R +\name{TorchOptimizer} +\alias{TorchOptimizer} +\title{Torch Optimizer} +\description{ +This wraps a \code{torch::torch_optimizer_generator}a and annotates it with metadata, most importantly a \code{\link{ParamSet}}. +The optimizer is created for the given parameter values by calling the \verb{$generate()} method. + +This class is usually used to configure the optimizer of a torch learner, e.g. +when construcing a learner or in a \code{\link{ModelDescriptor}}. + +For a list of available optimizers, see \code{\link{mlr3torch_optimizers}}. +Items from this dictionary can be retrieved using \code{\link[=t_opt]{t_opt()}}. +} +\section{Parameters}{ + +Defined by the constructor argument \code{param_set}. +If no parameter set is provided during construction, the parameter set is constructed by creating a parameter +for each argument of the wrapped loss function, where the parametes are then of type \code{\link{ParamUty}}. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Create a new torch loss +torch_opt = TorchOptimizer$new(optim_adam, label = "adam") +torch_opt +# If the param set is not specified, parameters are inferred but are of class ParamUty +torch_opt$param_set + +# open the help page of the wrapped optimizer +# torch_opt$help() + +# Retrieve an optimizer from the dictionary +torch_opt = t_opt("sgd", lr = 0.1) +torch_opt +torch_opt$param_set +torch_opt$label +torch_opt$id + +# Create the optimizer for a network +net = nn_linear(10, 1) +opt = torch_opt$generate(net$parameters) + +# is the same as +optim_sgd(net$parameters, lr = 0.1) + +# Use in a learner +learner = lrn("regr.mlp", optimizer = t_opt("sgd")) +# The parameters of the optimizer are added to the learner's parameter set +learner$param_set +} +\seealso{ +Other Torch Descriptor: +\code{\link{TorchCallback}}, +\code{\link{TorchDescriptor}}, +\code{\link{TorchLoss}}, +\code{\link{as_torch_callbacks}()}, +\code{\link{as_torch_loss}()}, +\code{\link{as_torch_optimizer}()}, +\code{\link{mlr3torch_losses}}, +\code{\link{mlr3torch_optimizers}}, +\code{\link{t_clbk}()}, +\code{\link{t_loss}()}, +\code{\link{t_opt}()} +} +\concept{Torch Descriptor} +\section{Super class}{ +\code{mlr3torch::TorchDescriptor} -> \code{TorchOptimizer} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-TorchOptimizer-new}{\code{TorchOptimizer$new()}} +\item \href{#method-TorchOptimizer-generate}{\code{TorchOptimizer$generate()}} +\item \href{#method-TorchOptimizer-clone}{\code{TorchOptimizer$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TorchOptimizer-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{TorchOptimizer$new( + torch_optimizer, + param_set = NULL, + id = NULL, + label = NULL, + packages = NULL, + man = NULL +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{torch_optimizer}}{(\code{torch_optimizer_generator})\cr +The torch optimizer.} + +\item{\code{param_set}}{(\code{ParamSet} or \code{NULL})\cr +The parameter set. If \code{NULL} (default) it is inferred from \code{torch_optimizer}.} + +\item{\code{id}}{(\code{character(1)})\cr +The id for of the new object.} + +\item{\code{label}}{(\code{character(1)})\cr +Label for the new instance.} + +\item{\code{packages}}{(\code{character()})\cr +The R packages this object depends on.} + +\item{\code{man}}{(\code{character(1)})\cr +String in the format \verb{[pkg]::[topic]} pointing to a manual page for this object. +The referenced help package can be opened via method \verb{$help()}.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TorchOptimizer-generate}{}}} +\subsection{Method \code{generate()}}{ +Instantiates the optimizer. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{TorchOptimizer$generate(params)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{params}}{(named \code{list()} of \code{\link{torch_tensor}}s)\cr +The parameters of the network.} +} +\if{html}{\out{
}} +} +\subsection{Returns}{ +\code{torch_optimizer} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TorchOptimizer-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{TorchOptimizer$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/as_lazy_tensor.Rd b/man/as_lazy_tensor.Rd new file mode 100644 index 00000000..5452ab75 --- /dev/null +++ b/man/as_lazy_tensor.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lazy_tensor.R +\name{as_lazy_tensor} +\alias{as_lazy_tensor} +\title{Convert to lazy tensor} +\usage{ +as_lazy_tensor(x, ...) +} +\arguments{ +\item{x}{(any)\cr +Object to convert to a \code{\link{lazy_tensor}}} + +\item{...}{(any)\cr +Additional arguments passed to the method.} +} +\description{ +Convert a object to a \code{\link{lazy_tensor}}. +} diff --git a/man/as_torch_callback.Rd b/man/as_torch_callback.Rd new file mode 100644 index 00000000..db5feeb8 --- /dev/null +++ b/man/as_torch_callback.Rd @@ -0,0 +1,38 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TorchCallback.R +\name{as_torch_callback} +\alias{as_torch_callback} +\title{Convert to a TorchCallback} +\usage{ +as_torch_callback(x, clone = FALSE, ...) +} +\arguments{ +\item{x}{(any)\cr +Object to be converted.} + +\item{clone}{(\code{logical(1)})\cr +Whether to make a deep clone.} + +\item{...}{(any)\cr +Additional arguments} +} +\value{ +\code{\link{TorchCallback}}. +} +\description{ +Converts an object to a \code{\link{TorchCallback}}. +} +\seealso{ +Other Callback: +\code{\link{TorchCallback}}, +\code{\link{as_torch_callbacks}()}, +\code{\link{callback_set}()}, +\code{\link{mlr3torch_callbacks}}, +\code{\link{mlr_callback_set}}, +\code{\link{mlr_callback_set.checkpoint}}, +\code{\link{mlr_callback_set.progress}}, +\code{\link{mlr_context_torch}}, +\code{\link{t_clbk}()}, +\code{\link{torch_callback}()} +} +\concept{Callback} diff --git a/man/as_torch_callbacks.Rd b/man/as_torch_callbacks.Rd new file mode 100644 index 00000000..563a4251 --- /dev/null +++ b/man/as_torch_callbacks.Rd @@ -0,0 +1,52 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TorchCallback.R +\name{as_torch_callbacks} +\alias{as_torch_callbacks} +\title{Convert to a list of Torch Callbacks} +\usage{ +as_torch_callbacks(x, clone, ...) +} +\arguments{ +\item{x}{(any)\cr +Object to convert.} + +\item{clone}{(\code{logical(1)})\cr +Whether to create a deep clone.} + +\item{...}{(any)\cr +Additional arguments.} +} +\value{ +\code{list()} of \code{\link{TorchCallback}}s +} +\description{ +Converts an object to a list of \code{\link{TorchCallback}}. +} +\seealso{ +Other Callback: +\code{\link{TorchCallback}}, +\code{\link{as_torch_callback}()}, +\code{\link{callback_set}()}, +\code{\link{mlr3torch_callbacks}}, +\code{\link{mlr_callback_set}}, +\code{\link{mlr_callback_set.checkpoint}}, +\code{\link{mlr_callback_set.progress}}, +\code{\link{mlr_context_torch}}, +\code{\link{t_clbk}()}, +\code{\link{torch_callback}()} + +Other Torch Descriptor: +\code{\link{TorchCallback}}, +\code{\link{TorchDescriptor}}, +\code{\link{TorchLoss}}, +\code{\link{TorchOptimizer}}, +\code{\link{as_torch_loss}()}, +\code{\link{as_torch_optimizer}()}, +\code{\link{mlr3torch_losses}}, +\code{\link{mlr3torch_optimizers}}, +\code{\link{t_clbk}()}, +\code{\link{t_loss}()}, +\code{\link{t_opt}()} +} +\concept{Callback} +\concept{Torch Descriptor} diff --git a/man/as_torch_loss.Rd b/man/as_torch_loss.Rd new file mode 100644 index 00000000..42317b61 --- /dev/null +++ b/man/as_torch_loss.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TorchLoss.R +\name{as_torch_loss} +\alias{as_torch_loss} +\title{Convert to TorchLoss} +\usage{ +as_torch_loss(x, clone = FALSE, ...) +} +\arguments{ +\item{x}{(any)\cr +Object to convert to a \code{\link{TorchLoss}}.} + +\item{clone}{(\code{logical(1)})\cr +Whether to make a deep clone.} + +\item{...}{(any)\cr +Additional arguments. +Currently used to pass additional constructor arguments to \code{\link{TorchLoss}} for objects of type \code{nn_loss}.} +} +\value{ +\code{\link{TorchLoss}}. +} +\description{ +Converts an object to a \code{\link{TorchLoss}}. +} +\seealso{ +Other Torch Descriptor: +\code{\link{TorchCallback}}, +\code{\link{TorchDescriptor}}, +\code{\link{TorchLoss}}, +\code{\link{TorchOptimizer}}, +\code{\link{as_torch_callbacks}()}, +\code{\link{as_torch_optimizer}()}, +\code{\link{mlr3torch_losses}}, +\code{\link{mlr3torch_optimizers}}, +\code{\link{t_clbk}()}, +\code{\link{t_loss}()}, +\code{\link{t_opt}()} +} +\concept{Torch Descriptor} diff --git a/man/as_torch_optimizer.Rd b/man/as_torch_optimizer.Rd new file mode 100644 index 00000000..2722bea0 --- /dev/null +++ b/man/as_torch_optimizer.Rd @@ -0,0 +1,41 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TorchOptimizer.R +\name{as_torch_optimizer} +\alias{as_torch_optimizer} +\title{Convert to TorchOptimizer} +\usage{ +as_torch_optimizer(x, clone = FALSE, ...) +} +\arguments{ +\item{x}{(any)\cr +Object to convert to a \code{\link{TorchOptimizer}}.} + +\item{clone}{(\code{logical(1)})\cr +Whether to make a deep clone. Default is \code{FALSE}.} + +\item{...}{(any)\cr +Additional arguments. +Currently used to pass additional constructor arguments to \code{\link{TorchOptimizer}} for objects of type +\code{torch_optimizer_generator}.} +} +\value{ +\code{\link{TorchOptimizer}} +} +\description{ +Converts an object to a \code{\link{TorchOptimizer}}. +} +\seealso{ +Other Torch Descriptor: +\code{\link{TorchCallback}}, +\code{\link{TorchDescriptor}}, +\code{\link{TorchLoss}}, +\code{\link{TorchOptimizer}}, +\code{\link{as_torch_callbacks}()}, +\code{\link{as_torch_loss}()}, +\code{\link{mlr3torch_losses}}, +\code{\link{mlr3torch_optimizers}}, +\code{\link{t_clbk}()}, +\code{\link{t_loss}()}, +\code{\link{t_opt}()} +} +\concept{Torch Descriptor} diff --git a/man/assert_lazy_tensor.Rd b/man/assert_lazy_tensor.Rd new file mode 100644 index 00000000..77945f09 --- /dev/null +++ b/man/assert_lazy_tensor.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lazy_tensor.R +\name{assert_lazy_tensor} +\alias{assert_lazy_tensor} +\title{Assert Lazy Tensor} +\usage{ +assert_lazy_tensor(x) +} +\arguments{ +\item{x}{(any)\cr +Object to check.} +} +\description{ +Asserts whether something is a lazy tensor. +} diff --git a/man/auto_device.Rd b/man/auto_device.Rd new file mode 100644 index 00000000..6599990a --- /dev/null +++ b/man/auto_device.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{auto_device} +\alias{auto_device} +\title{Auto Device} +\usage{ +auto_device(device = NULL) +} +\arguments{ +\item{device}{(\code{character(1)})\cr +The device. If not \code{NULL}, is returned as is.} +} +\description{ +First tries cuda, then cpu. +} diff --git a/man/batchgetter_categ.Rd b/man/batchgetter_categ.Rd new file mode 100644 index 00000000..7a721561 --- /dev/null +++ b/man/batchgetter_categ.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/task_dataset.R +\name{batchgetter_categ} +\alias{batchgetter_categ} +\title{Batchgetter for Categorical data} +\usage{ +batchgetter_categ(data, device, ...) +} +\arguments{ +\item{data}{(\code{data.table})\cr +\code{data.table} to be converted to a \code{tensor}.} + +\item{device}{(\code{character(1)})\cr +The device.} + +\item{...}{(any)\cr +Unused.} +} +\description{ +Converts a data frame of categorical data into a long tensor by converting the data to integers. +No input checks are performed. +} diff --git a/man/batchgetter_num.Rd b/man/batchgetter_num.Rd new file mode 100644 index 00000000..4b8ffa84 --- /dev/null +++ b/man/batchgetter_num.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/task_dataset.R +\name{batchgetter_num} +\alias{batchgetter_num} +\title{Batchgetter for Numeric Data} +\usage{ +batchgetter_num(data, device, ...) +} +\arguments{ +\item{data}{(\code{data.table()})\cr +\code{data.table} to be converted to a \code{tensor}.} + +\item{device}{(\code{character(1)})\cr +The device on which the tensor should be created.} + +\item{...}{(any)\cr +Unused.} +} +\description{ +Converts a data frame of numeric data into a float tensor by calling \code{as.matrix()}. +No input checks are performed +} diff --git a/man/callback_set.Rd b/man/callback_set.Rd new file mode 100644 index 00000000..60bd5db7 --- /dev/null +++ b/man/callback_set.Rd @@ -0,0 +1,77 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/CallbackSet.R +\name{callback_set} +\alias{callback_set} +\title{Create a Set of Callbacks for Torch} +\usage{ +callback_set( + classname, + on_begin = NULL, + on_end = NULL, + on_epoch_begin = NULL, + on_before_valid = NULL, + on_epoch_end = NULL, + on_batch_begin = NULL, + on_batch_end = NULL, + on_after_backward = NULL, + on_batch_valid_begin = NULL, + on_batch_valid_end = NULL, + initialize = NULL, + public = NULL, + private = NULL, + active = NULL, + parent_env = parent.frame(), + inherit = CallbackSet, + lock_objects = FALSE +) +} +\arguments{ +\item{classname}{(\code{character(1)})\cr +The class name.} + +\item{on_begin, on_end, on_epoch_begin, on_before_valid, on_epoch_end, on_batch_begin, on_batch_end, on_after_backward, on_batch_valid_begin, on_batch_valid_end}{(\code{function})\cr +Function to execute at the given stage, see section \emph{Stages}.} + +\item{initialize}{(\verb{function()})\cr +The initialization method of the callback.} + +\item{public, private, active}{(\code{list()})\cr +Additional public, private, and active fields to add to the callback.} + +\item{parent_env}{(\code{environment()})\cr +The parent environment for the \code{\link{R6Class}}.} + +\item{inherit}{(\code{R6ClassGenerator})\cr +From which class to inherit. +This class must either be \code{\link{CallbackSet}} (default) or inherit from it.} + +\item{lock_objects}{(\code{logical(1)})\cr +Whether to lock the objects of the resulting \code{\link{R6Class}}. +If \code{FALSE} (default), values can be freely assigned to \code{self} without declaring them in the +class definition.} +} +\value{ +\code{\link{CallbackSet}} +} +\description{ +Creates an \code{R6ClassGenerator} inheriting from \code{\link{CallbackSet}}. +Additionally performs checks such as that the stages are not accidentally misspelled. +To create a \code{\link{TorchCallback}} use \code{\link[=torch_callback]{torch_callback()}}. + +In order for the resulting class to be cloneable, the private method \verb{$deep_clone()} must be +provided. +} +\seealso{ +Other Callback: +\code{\link{TorchCallback}}, +\code{\link{as_torch_callback}()}, +\code{\link{as_torch_callbacks}()}, +\code{\link{mlr3torch_callbacks}}, +\code{\link{mlr_callback_set}}, +\code{\link{mlr_callback_set.checkpoint}}, +\code{\link{mlr_callback_set.progress}}, +\code{\link{mlr_context_torch}}, +\code{\link{t_clbk}()}, +\code{\link{torch_callback}()} +} +\concept{Callback} diff --git a/man/equals-.lazy_tensor.Rd b/man/equals-.lazy_tensor.Rd new file mode 100644 index 00000000..9be38b0c --- /dev/null +++ b/man/equals-.lazy_tensor.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lazy_tensor.R +\name{==.lazy_tensor} +\alias{==.lazy_tensor} +\title{Compare lazy tensors} +\usage{ +\method{==}{lazy_tensor}(x, y) +} +\arguments{ +\item{x, y}{(\code{\link{lazy_tensor}})\cr +Values to compare.} +} +\description{ +Compares lazy tensors using their indices and the data descriptor's hash. +This means that if two \code{\link{lazy_tensor}}s: +\itemize{ +\item are equal: they will mateterialize to the same tensors. +\item are unequal: they might materialize to the same tensors. +} +} diff --git a/man/hash_input.lazy_tensor.Rd b/man/hash_input.lazy_tensor.Rd new file mode 100644 index 00000000..2af04c6f --- /dev/null +++ b/man/hash_input.lazy_tensor.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lazy_tensor.R +\name{hash_input.lazy_tensor} +\alias{hash_input.lazy_tensor} +\title{Hash Input for Lazy Tensor} +\usage{ +\method{hash_input}{lazy_tensor}(x) +} +\arguments{ +\item{x}{(any)\cr +Object for which to retrieve hash input.} +} +\description{ +Returns the a list containing the IDs and the data descriprot's hash. +} diff --git a/man/is_lazy_tensor.Rd b/man/is_lazy_tensor.Rd new file mode 100644 index 00000000..02e5e216 --- /dev/null +++ b/man/is_lazy_tensor.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lazy_tensor.R +\name{is_lazy_tensor} +\alias{is_lazy_tensor} +\title{Check for lazy tensor} +\usage{ +is_lazy_tensor(x) +} +\arguments{ +\item{x}{(any)\cr +Object to check.} +} +\description{ +Checks whether an object is a lazy tensor. +} diff --git a/man/lazy_tensor.Rd b/man/lazy_tensor.Rd new file mode 100644 index 00000000..556439ae --- /dev/null +++ b/man/lazy_tensor.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lazy_tensor.R +\name{lazy_tensor} +\alias{lazy_tensor} +\title{Create a lazy tesornsor} +\usage{ +lazy_tensor(data_descriptor = NULL, ids = NULL) +} +\arguments{ +\item{data_descriptor}{(\code{\link{DataDescriptor}} or \code{NULL})\cr +The data descriptor or \code{NULL} for a lazy tensor of length 0.} + +\item{ids}{(\code{integer()})\cr +The elements of the \code{data_descriptor} to be included in the lazy tensor.} +} +\description{ +Create a lazy tensor. +} diff --git a/man/materialize.Rd b/man/materialize.Rd new file mode 100644 index 00000000..b8847683 --- /dev/null +++ b/man/materialize.Rd @@ -0,0 +1,69 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/materialize.R +\name{materialize} +\alias{materialize} +\alias{materialize.list} +\title{Materialize Lazy Tensor Columns} +\usage{ +materialize(x, device = "cpu", rbind = FALSE, ...) + +\method{materialize}{list}(x, device = "cpu", rbind = FALSE, cache = "auto", ...) +} +\arguments{ +\item{x}{(any)\cr +The object to materialize. +Either a \code{\link{lazy_tensor}} or a \code{list()} / \code{data.frame()} containing \code{\link{lazy_tensor}} columns.} + +\item{device}{(\code{character(1)})\cr +The torch device.} + +\item{rbind}{(\code{logical(1)})\cr +Whether to rbind the lazy tensor columns (\code{TRUE}) or return them as a list of tensors (\code{FALSE}). +In the second case, there is no batch dimension.} + +\item{...}{(any)\cr +Additional arguments.} + +\item{cache}{(\code{character(1)} or \code{environment()} or \code{NULL})\cr +Optional cache for (intermediate) materialization results. +Per default, caching will be enabled when the same dataset or data descriptor (with different output pointer) +is used for more than one lazy tensor column.} +} +\value{ +(\code{list()} of \code{\link{lazy_tensor}}s or a \code{\link{lazy_tensor}}) +} +\description{ +This will materialize a \code{\link[=lazy_tensor]{lazy_tensor()}} or a \code{data.frame()} / \code{list()} containing -- among other things -- +\code{\link[=lazy_tensor]{lazy_tensor()}} columns. +I.e. the data described in the underlying \code{\link{DataDescriptor}}s is loaded for the indices in the \code{\link[=lazy_tensor]{lazy_tensor()}}, +is preprocessed and then put unto the specified device. +Because not all elements in a lazy tensor must have the same shape, a list of tensors is returned by default. +If all elements have the same shape, these tensors can also be rbinded into a single tensor (parameter \code{rbind}). +} +\details{ +Materializing a lazy tensor consists of: +\enumerate{ +\item Loading the data from the internal dataset of the \code{\link{DataDescriptor}}. +\item Processing these batches in the preprocessing \code{\link{Graph}}s. +\item Returning the result of the \code{\link{PipeOp}} pointed to by the \code{\link{DataDescriptor}} (\code{pointer}). +} + +With multiple \code{\link{lazy_tensor}} columns we can benefit from caching because: +a) Output(s) from the dataset might be input to multiple graphs. +b) Different lazy tensors might be outputs from the same graph. + +For this reason it is possible to provide a cache environment. +The hash key for a) is the hash of the indices and the dataset. +The hash key for b) is the hash of the indices, dataset and preprocessing graph. +} +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +lt1 = as_lazy_tensor(torch_randn(10, 3)) +materialize(lt1, rbind = TRUE) +materialize(lt1, rbind = FALSE) +lt2 = as_lazy_tensor(torch_randn(10, 4)) +d = data.table::data.table(lt1 = lt1, lt2 = lt2) +materialize(d, rbind = TRUE) +materialize(d, rbind = FALSE) +} diff --git a/man/materialize_internal.Rd b/man/materialize_internal.Rd new file mode 100644 index 00000000..65390e21 --- /dev/null +++ b/man/materialize_internal.Rd @@ -0,0 +1,46 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/materialize.R +\name{materialize_internal} +\alias{materialize_internal} +\title{Materialize a Lazy Tensor} +\usage{ +materialize_internal(x, device = "cpu", cache = NULL, rbind) +} +\arguments{ +\item{x}{(\code{\link[=lazy_tensor]{lazy_tensor()}})\cr +The lazy tensor to materialize.} + +\item{device}{(\code{character(1L)})\cr +The device to put the materialized tensor on (after running the preprocessing graph).} + +\item{cache}{(\code{NULL} or \code{environment()})\cr +Whether to cache the (intermediate) results of the materialization. +This can make data loading faster when multiple \code{lazy_tensor}s reference the same dataset or graph.} + +\item{rbind}{(\code{logical(1)})\cr +Whtether to rbind the resulting tensors (\code{TRUE}) or return them as a list of tensors (\code{FALSE}).} +} +\value{ +\code{\link[=lazy_tensor]{lazy_tensor()}} +} +\description{ +Convert a \code{\link{lazy_tensor}} to a \code{\link{torch_tensor}}. +} +\details{ +Materializing a lazy tensor consists of: +\enumerate{ +\item Loading the data from the internal dataset of the \code{\link{DataDescriptor}}. +\item Processing these batches in the preprocessing \code{\link{Graph}}s. +\item Returning the result of the \code{\link{PipeOp}} pointed to by the \code{\link{DataDescriptor}} (\code{pointer}). +} + +When materializing multiple \code{\link{lazy_tensor}} columns, caching can be useful because: +a) Output(s) from the dataset might be input to multiple graphs. +(in task_dataset this is shoudl rarely be the case because because we try to merge them). +b) Different lazy tensors might be outputs from the same graph. + +For this reason it is possible to provide a cache environment. +The hash key for a) is the hash of the indices and the dataset. +The hash key for b) is the hash of the indices dataset and preprocessing graph. +} +\keyword{internal} diff --git a/man/mlr3torch-package.Rd b/man/mlr3torch-package.Rd new file mode 100644 index 00000000..809c1df8 --- /dev/null +++ b/man/mlr3torch-package.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/zzz.R +\docType{package} +\name{mlr3torch-package} +\alias{mlr3torch} +\alias{mlr3torch-package} +\title{mlr3torch: Deep Learning for 'mlr3'} +\description{ +Deep Learning library that extends the mlr3 framework by building upon the 'torch' package. It allows to conveniently build, train, and evaluate deep learning models without having to worry about low level details. Custom architectures can be created using the graph language defined in 'mlr3pipelines'. +} +\section{Options}{ + +\itemize{ +\item \code{mlr3torch.cache}: +Whether to cache the downloaded data (\code{TRUE}) or not (\code{FALSE}, default). +This can also be set to a specific folder on the file system to be used as the cache directory. +} +} + +\author{ +\strong{Maintainer}: Sebastian Fischer \email{sebf.fischer@gmail.com} (\href{https://orcid.org/0000-0002-9609-3197}{ORCID}) + +Authors: +\itemize{ + \item Martin Binder \email{mlr.developer@mb706.com} +} + +Other contributors: +\itemize{ + \item Bernd Bischl \email{bernd_bischl@gmx.net} (\href{https://orcid.org/0000-0001-6002-6980}{ORCID}) [contributor] + \item Lukas Burk \email{github@quantenbrot.de} (\href{https://orcid.org/0000-0001-7528-3795}{ORCID}) [contributor] + \item Florian Pfisterer \email{pfistererf@googlemail.com} (\href{https://orcid.org/0000-0001-8867-762X}{ORCID}) [contributor] +} + +} diff --git a/man/mlr3torch_callbacks.Rd b/man/mlr3torch_callbacks.Rd new file mode 100644 index 00000000..e12cd877 --- /dev/null +++ b/man/mlr3torch_callbacks.Rd @@ -0,0 +1,45 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TorchCallback.R +\docType{data} +\name{mlr3torch_callbacks} +\alias{mlr3torch_callbacks} +\title{Dictionary of Torch Callbacks} +\format{ +An object of class \code{DictionaryMlr3torchCallbacks} (inherits from \code{Dictionary}, \code{R6}) of length 13. +} +\usage{ +mlr3torch_callbacks +} +\description{ +A \code{\link[mlr3misc:Dictionary]{mlr3misc::Dictionary}} of torch callbacks. +Use \code{\link[=t_clbk]{t_clbk()}} to conveniently retrieve callbacks. +Can be converted to a \code{\link{data.table}} using \code{as.data.table}. +} +\examples{ +mlr3torch_callbacks$get("checkpoint") +# is the same as +t_clbk("checkpoint") +# convert to a data.table +as.data.table(mlr3torch_callbacks) +} +\seealso{ +Other Callback: +\code{\link{TorchCallback}}, +\code{\link{as_torch_callback}()}, +\code{\link{as_torch_callbacks}()}, +\code{\link{callback_set}()}, +\code{\link{mlr_callback_set}}, +\code{\link{mlr_callback_set.checkpoint}}, +\code{\link{mlr_callback_set.progress}}, +\code{\link{mlr_context_torch}}, +\code{\link{t_clbk}()}, +\code{\link{torch_callback}()} + +Other Dictionary: +\code{\link{mlr3torch_losses}}, +\code{\link{mlr3torch_optimizers}}, +\code{\link{t_opt}()} +} +\concept{Callback} +\concept{Dictionary} +\keyword{datasets} diff --git a/man/mlr3torch_losses.Rd b/man/mlr3torch_losses.Rd new file mode 100644 index 00000000..8fd0d0b0 --- /dev/null +++ b/man/mlr3torch_losses.Rd @@ -0,0 +1,51 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TorchLoss.R +\docType{data} +\name{mlr3torch_losses} +\alias{mlr3torch_losses} +\title{Loss Functions} +\format{ +An object of class \code{DictionaryMlr3torchLosses} (inherits from \code{Dictionary}, \code{R6}) of length 13. +} +\usage{ +mlr3torch_losses +} +\description{ +Dictionary of torch loss descriptors. +See \code{\link[=t_loss]{t_loss()}} for conveniently retrieving a loss function. +Can be converted to a \code{\link{data.table}} using \code{\link[=as.data.table]{as.data.table()}}. +} +\section{Available Loss Functions}{ + +cross_entropy, l1, mse +} + +\examples{ +mlr3torch_losses$get("mse") +# is equivalent to +t_loss("mse") +# convert to a data.table +as.data.table(mlr3torch_losses) +} +\seealso{ +Other Torch Descriptor: +\code{\link{TorchCallback}}, +\code{\link{TorchDescriptor}}, +\code{\link{TorchLoss}}, +\code{\link{TorchOptimizer}}, +\code{\link{as_torch_callbacks}()}, +\code{\link{as_torch_loss}()}, +\code{\link{as_torch_optimizer}()}, +\code{\link{mlr3torch_optimizers}}, +\code{\link{t_clbk}()}, +\code{\link{t_loss}()}, +\code{\link{t_opt}()} + +Other Dictionary: +\code{\link{mlr3torch_callbacks}}, +\code{\link{mlr3torch_optimizers}}, +\code{\link{t_opt}()} +} +\concept{Dictionary} +\concept{Torch Descriptor} +\keyword{datasets} diff --git a/man/mlr3torch_optimizers.Rd b/man/mlr3torch_optimizers.Rd new file mode 100644 index 00000000..e335637a --- /dev/null +++ b/man/mlr3torch_optimizers.Rd @@ -0,0 +1,53 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TorchOptimizer.R +\docType{data} +\name{mlr3torch_optimizers} +\alias{mlr3torch_optimizers} +\title{Optimizers} +\format{ +An object of class \code{DictionaryMlr3torchOptimizers} (inherits from \code{Dictionary}, \code{R6}) of length 13. +} +\usage{ +mlr3torch_optimizers +} +\description{ +Dictionary of torch optimizers. +Use \code{\link{t_opt}} for conveniently retrieving optimizers. +Can be converted to a \code{\link{data.table}} using \code{as.data.table}. +} +\section{Available Optimizers}{ + +adadelta, adagrad, adam, asgd, rmsprop, rprop, sgd +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +mlr3torch_optimizers$get("adam") +# is equivalent to +t_opt("adam") +# convert to a data.table +as.data.table(mlr3torch_optimizers) +} +\seealso{ +Other Torch Descriptor: +\code{\link{TorchCallback}}, +\code{\link{TorchDescriptor}}, +\code{\link{TorchLoss}}, +\code{\link{TorchOptimizer}}, +\code{\link{as_torch_callbacks}()}, +\code{\link{as_torch_loss}()}, +\code{\link{as_torch_optimizer}()}, +\code{\link{mlr3torch_losses}}, +\code{\link{t_clbk}()}, +\code{\link{t_loss}()}, +\code{\link{t_opt}()} + +Other Dictionary: +\code{\link{mlr3torch_callbacks}}, +\code{\link{mlr3torch_losses}}, +\code{\link{t_opt}()} +} +\concept{Dictionary} +\concept{Torch Descriptor} +\keyword{datasets} diff --git a/man/mlr_backends_lazy.Rd b/man/mlr_backends_lazy.Rd new file mode 100644 index 00000000..504a4c37 --- /dev/null +++ b/man/mlr_backends_lazy.Rd @@ -0,0 +1,271 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/DataBackendLazy.R +\name{mlr_backends_lazy} +\alias{mlr_backends_lazy} +\alias{DataBackendLazy} +\title{Lazy Data Backend} +\description{ +This lazy data backend wraps a constructor that lazily creates another backend, e.g. by downloading +(and caching) some data from the internet. +This backend should be used, when some metadata of the backend is known in advance and should be accessible +before downloading the actual data. +When the backend is first constructed, it is verified that the provided metadata was correct, otherwise +an informative error message is thrown. +After the construction of the lazily constructed backend, calls like \verb{$data()}, \verb{$missings()}, \verb{$distinct()}, +or \verb{$hash()} are redirected to it. + +Information that is available before the backend is constructed is: +\itemize{ +\item \code{nrow} - The number of rows (set as the length of the \code{rownames}). +\item \code{ncol} - The number of columns (provided via the \code{id} column of \code{col_info}). +\item \code{colnames} - The column names. +\item \code{rownames} - The row names. +\item \code{col_info} - The column information, which can be obtained via \code{\link[mlr3:col_info]{mlr3::col_info()}}. +} + +Beware that accessing the backend's hash also contructs the backend. + +Note that while in most cases the data contains \code{\link{lazy_tensor}} columns, this is not necessary and the naming +of this class has nothing to do with the \code{\link{lazy_tensor}} data type. + +\strong{Important} + +When the constructor generates \code{factor()} variables it is important that the ordering of the levels in data +corresponds to the ordering of the levels in the \code{col_info} argument. +} +\examples{ +# We first define a backend constructor +constructor = function(backend) { + cat("Data is constructed!\n") + DataBackendDataTable$new( + data.table(x = rnorm(10), y = rnorm(10), row_id = 1:10), + primary_key = "row_id" + ) +} + +# to wrap this backend constructor in a lazy backend, we need to provide the correct metadata for it +column_info = data.table( + id = c("x", "y", "row_id"), + type = c("numeric", "numeric", "integer"), + levels = list(NULL, NULL, NULL) +) +backend_lazy = DataBackendLazy$new( + constructor = constructor, + rownames = 1:10, + col_info = column_info, + data_formats = "data.table", + primary_key = "row_id" +) + +# Note that the constructor is not called for the calls below +# as they can be read from the metadata +backend_lazy$nrow +backend_lazy$rownames +backend_lazy$ncol +backend_lazy$colnames +col_info(backend_lazy) + +# Only now the backend is constructed +backend_lazy$data(1, "x") +# Is the same as: +backend_lazy$backend$data(1, "x") +} +\section{Super class}{ +\code{\link[mlr3:DataBackend]{mlr3::DataBackend}} -> \code{DataBackendLazy} +} +\section{Active bindings}{ +\if{html}{\out{
}} +\describe{ +\item{\code{backend}}{(\code{DataBackend})\cr +The wrapped backend that is lazily constructed when first accessed.} + +\item{\code{nrow}}{(\code{integer(1)})\cr +Number of rows (observations).} + +\item{\code{ncol}}{(\code{integer(1)})\cr +Number of columns (variables), including the primary key column.} + +\item{\code{rownames}}{(\code{integer()})\cr +Returns vector of all distinct row identifiers, i.e. the contents of the primary key column.} + +\item{\code{colnames}}{(\code{character()})\cr +Returns vector of all column names, including the primary key column.} + +\item{\code{is_constructed}}{(\code{logical(1)})\cr +Whether the backend has already been constructed.} +} +\if{html}{\out{
}} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-DataBackendLazy-new}{\code{DataBackendLazy$new()}} +\item \href{#method-DataBackendLazy-data}{\code{DataBackendLazy$data()}} +\item \href{#method-DataBackendLazy-head}{\code{DataBackendLazy$head()}} +\item \href{#method-DataBackendLazy-distinct}{\code{DataBackendLazy$distinct()}} +\item \href{#method-DataBackendLazy-missings}{\code{DataBackendLazy$missings()}} +\item \href{#method-DataBackendLazy-print}{\code{DataBackendLazy$print()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-DataBackendLazy-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{DataBackendLazy$new(constructor, rownames, col_info, primary_key, data_formats)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{constructor}}{(\code{function})\cr +A function with argument \code{backend} (the lazy backend), whose return value must be the actual backend. +This function is called the first time the field \verb{$backend} is accessed.} + +\item{\code{rownames}}{(\code{integer()})\cr +The row names. Must be a permutation of the rownames of the lazily constructed backend.} + +\item{\code{col_info}}{(\code{\link[data.table:data.table]{data.table::data.table()}})\cr +A data.table with columns \code{id}, \code{type} and \code{levels} containing the column id, type and levels. +Note that the levels must be provided in the correct order.} + +\item{\code{primary_key}}{(\code{character(1)})\cr +Name of the primary key column.} + +\item{\code{data_formats}}{(\code{character()})\cr +Set of supported data formats. E.g. \code{"data.table"}. +These must be a subset of the data formats of the lazily constructed backend.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-DataBackendLazy-data}{}}} +\subsection{Method \code{data()}}{ +Returns a slice of the data in the specified format. +The rows must be addressed as vector of primary key values, columns must be referred to via column names. +Queries for rows with no matching row id and queries for columns with no matching column name are silently ignored. +Rows are guaranteed to be returned in the same order as \code{rows}, columns may be returned in an arbitrary order. +Duplicated row ids result in duplicated rows, duplicated column names lead to an exception. + +Accessing the data triggers the construction of the backend. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{DataBackendLazy$data(rows, cols, data_format = "data.table")}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{rows}}{(\code{integer()})\cr +Row indices.} + +\item{\code{cols}}{(\code{character()})\cr +Column names.} + +\item{\code{data_format}}{(\code{character(1)})\cr +Desired data format, e.g. \code{"data.table"} or \code{"Matrix"}.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-DataBackendLazy-head}{}}} +\subsection{Method \code{head()}}{ +Retrieve the first \code{n} rows. +This triggers the construction of the backend. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{DataBackendLazy$head(n = 6L)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{n}}{(\code{integer(1)})\cr +Number of rows.} +} +\if{html}{\out{
}} +} +\subsection{Returns}{ +\code{\link[data.table:data.table]{data.table::data.table()}} of the first \code{n} rows. +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-DataBackendLazy-distinct}{}}} +\subsection{Method \code{distinct()}}{ +Returns a named list of vectors of distinct values for each column +specified. If \code{na_rm} is \code{TRUE}, missing values are removed from the +returned vectors of distinct values. Non-existing rows and columns are +silently ignored. + +This triggers the construction of the backend. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{DataBackendLazy$distinct(rows, cols, na_rm = TRUE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{rows}}{(\code{integer()})\cr +Row indices.} + +\item{\code{cols}}{(\code{character()})\cr +Column names.} + +\item{\code{na_rm}}{(\code{logical(1)})\cr +Whether to remove NAs or not.} +} +\if{html}{\out{
}} +} +\subsection{Returns}{ +Named \code{list()} of distinct values. +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-DataBackendLazy-missings}{}}} +\subsection{Method \code{missings()}}{ +Returns the number of missing values per column in the specified slice +of data. Non-existing rows and columns are silently ignored. + +This triggers the construction of the backend. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{DataBackendLazy$missings(rows, cols)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{rows}}{(\code{integer()})\cr +Row indices.} + +\item{\code{cols}}{(\code{character()})\cr +Column names.} +} +\if{html}{\out{
}} +} +\subsection{Returns}{ +Total of missing values per column (named \code{numeric()}). +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-DataBackendLazy-print}{}}} +\subsection{Method \code{print()}}{ +Printer. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{DataBackendLazy$print()}\if{html}{\out{
}} +} + +} +} diff --git a/man/mlr_context_torch.Rd b/man/mlr_context_torch.Rd new file mode 100644 index 00000000..01f43ee7 --- /dev/null +++ b/man/mlr_context_torch.Rd @@ -0,0 +1,167 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ContextTorch.R +\name{mlr_context_torch} +\alias{mlr_context_torch} +\alias{ContextTorch} +\title{Context for Torch Learner} +\description{ +Context for training a torch learner. +This is the - mostly read-only - information callbacks have access to through the argument \code{ctx}. +For more information on callbacks, see \code{\link{CallbackSet}}. +} +\seealso{ +Other Callback: +\code{\link{TorchCallback}}, +\code{\link{as_torch_callback}()}, +\code{\link{as_torch_callbacks}()}, +\code{\link{callback_set}()}, +\code{\link{mlr3torch_callbacks}}, +\code{\link{mlr_callback_set}}, +\code{\link{mlr_callback_set.checkpoint}}, +\code{\link{mlr_callback_set.progress}}, +\code{\link{t_clbk}()}, +\code{\link{torch_callback}()} +} +\concept{Callback} +\section{Public fields}{ +\if{html}{\out{
}} +\describe{ +\item{\code{learner}}{(\code{\link{Learner}})\cr +The torch learner.} + +\item{\code{task_train}}{(\code{\link{Task}})\cr +The training task.} + +\item{\code{task_valid}}{(\code{\link{Task}} or \code{NULL})\cr +The validation task.} + +\item{\code{loader_train}}{(\code{\link[torch:dataloader]{torch::dataloader}})\cr +The data loader for training.} + +\item{\code{loader_valid}}{(\code{\link[torch:dataloader]{torch::dataloader}})\cr +The data loader for validation.} + +\item{\code{measures_train}}{(\code{list()} of \code{\link{Measure}}s or \code{NULL})\cr +Measures used for training.} + +\item{\code{measures_valid}}{(\code{list()} of \code{\link{Measure}}s or \code{NULL})\cr +Measures used for validation.} + +\item{\code{network}}{(\code{\link[torch:nn_module]{torch::nn_module}})\cr +The torch network.} + +\item{\code{optimizer}}{(\code{\link[torch:optimizer]{torch::optimizer}})\cr +The optimizer.} + +\item{\code{loss_fn}}{(\code{\link[torch:nn_module]{torch::nn_module}})\cr +The loss function.} + +\item{\code{total_epochs}}{(\code{integer(1)})\cr +The total number of epochs the learner is trained for.} + +\item{\code{last_scores_train}}{(named \code{list()})\cr +The scores from the last training batch. Names are the ids of the training measures.} + +\item{\code{last_scores_valid}}{(\code{list()})\cr +The scores from the last validation batch. Names are the ids of the validation measures.} + +\item{\code{epoch}}{(\code{integer(1)})\cr +The current epoch.} + +\item{\code{batch}}{(\code{integer(1)})\cr +The current iteration of the batch.} + +\item{\code{prediction_encoder}}{(\verb{function()})\cr +The learner's prediction encoder.} +} +\if{html}{\out{
}} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-ContextTorch-new}{\code{ContextTorch$new()}} +\item \href{#method-ContextTorch-clone}{\code{ContextTorch$clone()}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-ContextTorch-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{ContextTorch$new( + learner, + task_train, + task_valid = NULL, + loader_train, + loader_valid = NULL, + measures_train = NULL, + measures_valid = NULL, + network, + optimizer, + loss_fn, + total_epochs, + prediction_encoder +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{learner}}{(\code{\link{Learner}})\cr +The torch learner.} + +\item{\code{task_train}}{(\code{\link{Task}})\cr +The training task.} + +\item{\code{task_valid}}{(\code{\link{Task}} or \code{NULL})\cr +The validation task.} + +\item{\code{loader_train}}{(\code{\link[torch:dataloader]{torch::dataloader}})\cr +The data loader for training.} + +\item{\code{loader_valid}}{(\code{\link[torch:dataloader]{torch::dataloader}} or \code{NULL})\cr +The data loader for validation.} + +\item{\code{measures_train}}{(\code{list()} of \code{\link{Measure}}s or \code{NULL})\cr +Measures used for training. Default is \code{NULL}.} + +\item{\code{measures_valid}}{(\code{list()} of \code{\link{Measure}}s or \code{NULL})\cr +Measures used for validation.} + +\item{\code{network}}{(\code{\link[torch:nn_module]{torch::nn_module}})\cr +The torch network.} + +\item{\code{optimizer}}{(\code{\link[torch:optimizer]{torch::optimizer}})\cr +The optimizer.} + +\item{\code{loss_fn}}{(\code{\link[torch:nn_module]{torch::nn_module}})\cr +The loss function.} + +\item{\code{total_epochs}}{(\code{integer(1)})\cr +The total number of epochs the learner is trained for.} + +\item{\code{prediction_encoder}}{(\verb{function()})\cr +The learner's prediction encoder.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-ContextTorch-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{ContextTorch$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_learners.alexnet.Rd b/man/mlr_learners.alexnet.Rd index 41e9b9b3..55a85bc9 100644 --- a/man/mlr_learners.alexnet.Rd +++ b/man/mlr_learners.alexnet.Rd @@ -78,13 +78,11 @@ Other Learner:
Inherited methods diff --git a/man/mlr_learners.mlp.Rd b/man/mlr_learners.mlp.Rd index fa186c99..30e45c16 100644 --- a/man/mlr_learners.mlp.Rd +++ b/man/mlr_learners.mlp.Rd @@ -65,6 +65,8 @@ Otherwise the input shape is inferred from the number of numeric features. } \examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} # Define the Learner and set parameter values learner = lrn("classif.mlp") learner$param_set$set_values( @@ -109,13 +111,11 @@ Other Learner:
Inherited methods diff --git a/man/mlr_learners.torch_featureless.Rd b/man/mlr_learners.torch_featureless.Rd index b53f2a1a..ad87873e 100644 --- a/man/mlr_learners.torch_featureless.Rd +++ b/man/mlr_learners.torch_featureless.Rd @@ -51,6 +51,8 @@ Only those from \code{\link{LearnerTorch}}. } \examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} # Define the Learner and set parameter values learner = lrn("classif.torch_featureless") learner$param_set$set_values( @@ -95,13 +97,11 @@ Other Learner:
Inherited methods diff --git a/man/mlr_learners_torch.Rd b/man/mlr_learners_torch.Rd index 971ddf78..3b18b5f0 100644 --- a/man/mlr_learners_torch.Rd +++ b/man/mlr_learners_torch.Rd @@ -135,13 +135,11 @@ Shortcut for \code{learner$model$callbacks$history}.}
Inherited methods
}} diff --git a/man/mlr_learners_torch_image.Rd b/man/mlr_learners_torch_image.Rd index 8f25dc20..b956d708 100644 --- a/man/mlr_learners_torch_image.Rd +++ b/man/mlr_learners_torch_image.Rd @@ -55,13 +55,11 @@ Other Learner:
Inherited methods diff --git a/man/mlr_learners_torch_model.Rd b/man/mlr_learners_torch_model.Rd index 1c0c50ce..af40d4db 100644 --- a/man/mlr_learners_torch_model.Rd +++ b/man/mlr_learners_torch_model.Rd @@ -13,6 +13,8 @@ For classification, the output of the network must be the scores (before the sof } \examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} # We show the learner using a classification task # The iris task has 4 features and 3 classes @@ -78,13 +80,11 @@ Other Graph Network:
Inherited methods diff --git a/man/mlr_pipeops_module.Rd b/man/mlr_pipeops_module.Rd new file mode 100644 index 00000000..7ccaa091 --- /dev/null +++ b/man/mlr_pipeops_module.Rd @@ -0,0 +1,187 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpModule.R +\name{mlr_pipeops_module} +\alias{mlr_pipeops_module} +\alias{PipeOpModule} +\title{Class for Torch Module Wrappers} +\description{ +\code{PipeOpModule} wraps an \code{\link{nn_module}} or \code{function} that is being called during the \code{train} phase of this +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}}. By doing so, this allows to assemble \code{PipeOpModule}s in a computational +\code{\link[mlr3pipelines:Graph]{mlr3pipelines::Graph}} that represents either a neural network or a preprocessing graph of a \code{\link{lazy_tensor}}. +In most cases it is easier to create such a network by creating a graph that generates this graph. + +In most cases it is easier to create such a network by creating a structurally related graph consisting +of nodes of class \code{\link{PipeOpTorchIngress}} and \code{\link{PipeOpTorch}}. This graph will then generate the graph consisting +of \code{PipeOpModule}s as part of the \code{\link{ModelDescriptor}}. +} +\section{Input and Output Channels}{ + +The number and names of the input and output channels can be set during construction. They input and output +\code{"torch_tensor"} during training, and \code{NULL} during prediction as the prediction phase currently serves no +meaningful purpose. +} + +\section{State}{ + +The state is the value calculated by the public method \code{shapes_out()}. +} + +\section{Parameters}{ + +No parameters. +} + +\section{Internals}{ + +During training, the wrapped \code{\link{nn_module}} / \code{function} is called with the provided inputs in the order in which +the channels are defined. Arguments are \strong{not} matched by name. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +## creating an PipeOpModule manually + +# one input and output channel +po_module = po("module", + id = "linear", + module = torch::nn_linear(10, 20), + inname = "input", + outname = "output" +) +x = torch::torch_randn(16, 10) +# This calls the forward function of the wrapped module. +y = po_module$train(list(input = x)) +str(y) + +# multiple input and output channels +nn_custom = torch::nn_module("nn_custom", + initialize = function(in_features, out_features) { + self$lin1 = torch::nn_linear(in_features, out_features) + self$lin2 = torch::nn_linear(in_features, out_features) + }, + forward = function(x, z) { + list(out1 = self$lin1(x), out2 = torch::nnf_relu(self$lin2(z))) + } +) + +module = nn_custom(3, 2) +po_module = po("module", + id = "custom", + module = module, + inname = c("x", "z"), + outname = c("out1", "out2") +) +x = torch::torch_randn(1, 3) +z = torch::torch_randn(1, 3) +out = po_module$train(list(x = x, z = z)) +str(out) + +# How such a PipeOpModule is usually generated +graph = po("torch_ingress_num") \%>>\% po("nn_linear", out_features = 10L) +result = graph$train(tsk("iris")) +# The PipeOpTorchLinear generates a PipeOpModule and adds it to a new (module) graph +result[[1]]$graph +linear_module = result[[1L]]$graph$pipeops$nn_linear +linear_module +formalArgs(linear_module$module) +linear_module$input$name + +# Constructing a PipeOpModule using a simple function +po_add1 = po("module", + id = "add_one", + module = function(x) x + 1 +) +input = list(torch_tensor(1)) +po_add1$train(input)$output +} +\seealso{ +Other Graph Network: +\code{\link{ModelDescriptor}()}, +\code{\link{TorchIngressToken}()}, +\code{\link{mlr_learners_torch_model}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{model_descriptor_to_learner}()}, +\code{\link{model_descriptor_to_module}()}, +\code{\link{model_descriptor_union}()}, +\code{\link{nn_graph}()} + +Other PipeOp: +\code{\link{mlr_pipeops_torch_callbacks}}, +\code{\link{mlr_pipeops_torch_optimizer}} +} +\concept{Graph Network} +\concept{PipeOp} +\section{Super class}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{PipeOpModule} +} +\section{Public fields}{ +\if{html}{\out{
}} +\describe{ +\item{\code{module}}{(\code{\link{nn_module}})\cr +The torch module that is called during the training phase.} +} +\if{html}{\out{
}} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpModule-new}{\code{PipeOpModule$new()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpModule-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpModule$new( + id = "module", + module = nn_identity(), + inname = "input", + outname = "output", + param_vals = list(), + packages = character(0) +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +The id for of the new object.} + +\item{\code{module}}{(\code{\link{nn_module}} or \verb{function()})\cr +The torch module or function that is being wrapped.} + +\item{\code{inname}}{(\code{character()})\cr +The names of the input channels.} + +\item{\code{outname}}{(\code{character()})\cr +The names of the output channels. If this parameter has length 1, the parameter \link[torch:nn_module]{module} must +return a \link[torch:torch_tensor]{tensor}. Otherwise it must return a \code{list()} of tensors of corresponding length.} + +\item{\code{param_vals}}{(named \code{list()})\cr +Parameter values to be set after construction.} + +\item{\code{packages}}{(\code{character()})\cr +The R packages this object depends on.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_avg_pool1d.Rd b/man/mlr_pipeops_nn_avg_pool1d.Rd new file mode 100644 index 00000000..0178bac5 --- /dev/null +++ b/man/mlr_pipeops_nn_avg_pool1d.Rd @@ -0,0 +1,179 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchAvgPool.R +\name{mlr_pipeops_nn_avg_pool1d} +\alias{mlr_pipeops_nn_avg_pool1d} +\alias{PipeOpTorchAvgPool1D} +\title{1D Average Pooling} +\description{ +Applies a 1D adaptive average pooling over an input signal composed of +several input planes. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{kernel_size} :: (\code{integer()})\cr +The size of the window. Can be a single number or a vector. +\item \code{stride} :: \code{integer()}\cr +The stride of the window. Can be a single number or a vector. Default: \code{kernel_size}. +\item \code{padding} :: \code{integer()}\cr +Implicit zero paddings on both sides of the input. Can be a single number or a vector. Default: 0. +\item \code{ceil_mode} :: \code{integer()}\cr +When \code{TRUE}, will use ceil instead of floor to compute the output shape. Default: \code{FALSE}. +\item \code{count_include_pad} :: \code{logical(1)}\cr +When \code{TRUE}, will include the zero-padding in the averaging calculation. Default: \code{TRUE}. +\item \code{divisor_override} :: \code{logical(1)}\cr +If specified, it will be used as divisor, otherwise size of the pooling region will be used. Default: NULL. +Only available for dimension greater than 1. +} +} + +\section{Internals}{ + +Calls \code{\link[=nn_avg_pool1d]{nn_avg_pool1d()}} during training. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_avg_pool1d") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchAvgPool} -> \code{PipeOpTorchAvgPool1D} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchAvgPool1D-new}{\code{PipeOpTorchAvgPool1D$new()}} +\item \href{#method-PipeOpTorchAvgPool1D-clone}{\code{PipeOpTorchAvgPool1D$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchAvgPool1D-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchAvgPool1D$new(id = "nn_avg_pool1d", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchAvgPool1D-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchAvgPool1D$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_avg_pool2d.Rd b/man/mlr_pipeops_nn_avg_pool2d.Rd new file mode 100644 index 00000000..00101b72 --- /dev/null +++ b/man/mlr_pipeops_nn_avg_pool2d.Rd @@ -0,0 +1,179 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchAvgPool.R +\name{mlr_pipeops_nn_avg_pool2d} +\alias{mlr_pipeops_nn_avg_pool2d} +\alias{PipeOpTorchAvgPool2D} +\title{2D Average Pooling} +\description{ +Applies a 2D adaptive average pooling over an input signal composed of +several input planes. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Internals}{ + +Calls \code{\link[=nn_avg_pool2d]{nn_avg_pool2d()}} during training. +} + +\section{Parameters}{ + +\itemize{ +\item \code{kernel_size} :: (\code{integer()})\cr +The size of the window. Can be a single number or a vector. +\item \code{stride} :: \code{integer()}\cr +The stride of the window. Can be a single number or a vector. Default: \code{kernel_size}. +\item \code{padding} :: \code{integer()}\cr +Implicit zero paddings on both sides of the input. Can be a single number or a vector. Default: 0. +\item \code{ceil_mode} :: \code{integer()}\cr +When \code{TRUE}, will use ceil instead of floor to compute the output shape. Default: \code{FALSE}. +\item \code{count_include_pad} :: \code{logical(1)}\cr +When \code{TRUE}, will include the zero-padding in the averaging calculation. Default: \code{TRUE}. +\item \code{divisor_override} :: \code{logical(1)}\cr +If specified, it will be used as divisor, otherwise size of the pooling region will be used. Default: NULL. +Only available for dimension greater than 1. +} +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_avg_pool2d") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchAvgPool} -> \code{PipeOpTorchAvgPool2D} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchAvgPool2D-new}{\code{PipeOpTorchAvgPool2D$new()}} +\item \href{#method-PipeOpTorchAvgPool2D-clone}{\code{PipeOpTorchAvgPool2D$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchAvgPool2D-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchAvgPool2D$new(id = "nn_avg_pool2d", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchAvgPool2D-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchAvgPool2D$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_avg_pool3d.Rd b/man/mlr_pipeops_nn_avg_pool3d.Rd new file mode 100644 index 00000000..cf25eb17 --- /dev/null +++ b/man/mlr_pipeops_nn_avg_pool3d.Rd @@ -0,0 +1,179 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchAvgPool.R +\name{mlr_pipeops_nn_avg_pool3d} +\alias{mlr_pipeops_nn_avg_pool3d} +\alias{PipeOpTorchAvgPool3D} +\title{3D Average Pooling} +\description{ +Applies a 3D adaptive average pooling over an input signal composed of +several input planes. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Internals}{ + +Calls \code{\link[=nn_avg_pool3d]{nn_avg_pool3d()}} during training. +} + +\section{Parameters}{ + +\itemize{ +\item \code{kernel_size} :: (\code{integer()})\cr +The size of the window. Can be a single number or a vector. +\item \code{stride} :: \code{integer()}\cr +The stride of the window. Can be a single number or a vector. Default: \code{kernel_size}. +\item \code{padding} :: \code{integer()}\cr +Implicit zero paddings on both sides of the input. Can be a single number or a vector. Default: 0. +\item \code{ceil_mode} :: \code{integer()}\cr +When \code{TRUE}, will use ceil instead of floor to compute the output shape. Default: \code{FALSE}. +\item \code{count_include_pad} :: \code{logical(1)}\cr +When \code{TRUE}, will include the zero-padding in the averaging calculation. Default: \code{TRUE}. +\item \code{divisor_override} :: \code{logical(1)}\cr +If specified, it will be used as divisor, otherwise size of the pooling region will be used. Default: NULL. +Only available for dimension greater than 1. +} +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_avg_pool3d") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchAvgPool} -> \code{PipeOpTorchAvgPool3D} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchAvgPool3D-new}{\code{PipeOpTorchAvgPool3D$new()}} +\item \href{#method-PipeOpTorchAvgPool3D-clone}{\code{PipeOpTorchAvgPool3D$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchAvgPool3D-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchAvgPool3D$new(id = "nn_avg_pool3d", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchAvgPool3D-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchAvgPool3D$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_batch_norm1d.Rd b/man/mlr_pipeops_nn_batch_norm1d.Rd new file mode 100644 index 00000000..b6abc70c --- /dev/null +++ b/man/mlr_pipeops_nn_batch_norm1d.Rd @@ -0,0 +1,177 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchBatchNorm.R +\name{mlr_pipeops_nn_batch_norm1d} +\alias{mlr_pipeops_nn_batch_norm1d} +\alias{PipeOpTorchBatchNorm1D} +\title{1D Batch Normalization} +\description{ +Applies Batch Normalization for each channel across a batch of data. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{eps} :: \code{numeric(1)}\cr +A value added to the denominator for numerical stability. Default: \code{1e-5}. +\item \code{momentum} :: \code{numeric(1)}\cr +The value used for the running_mean and running_var computation. Can be set to \code{NULL} for cumulative moving average +(i.e. simple average). Default: 0.1 +\item \code{affine} :: \code{logical(1)}\cr +a boolean value that when set to \code{TRUE}, this module has learnable affine parameters. Default: \code{TRUE} +\item \code{track_running_stats} :: \code{logical(1)}\cr +a boolean value that when set to \code{TRUE}, this module tracks the running mean and variance, and when set to \code{FALSE}, +this module does not track such statistics and always uses batch statistics in both training and eval modes. +Default: \code{TRUE} +} +} + +\section{Internals}{ + +Calls \code{\link[torch:nn_batch_norm1d]{torch::nn_batch_norm1d()}}. +The parameter \code{num_features} is inferred as the second dimension of the input shape. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_batch_norm1d") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchBatchNorm} -> \code{PipeOpTorchBatchNorm1D} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchBatchNorm1D-new}{\code{PipeOpTorchBatchNorm1D$new()}} +\item \href{#method-PipeOpTorchBatchNorm1D-clone}{\code{PipeOpTorchBatchNorm1D$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchBatchNorm1D-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchBatchNorm1D$new(id = "nn_batch_norm1d", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchBatchNorm1D-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchBatchNorm1D$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_batch_norm2d.Rd b/man/mlr_pipeops_nn_batch_norm2d.Rd new file mode 100644 index 00000000..9898911f --- /dev/null +++ b/man/mlr_pipeops_nn_batch_norm2d.Rd @@ -0,0 +1,177 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchBatchNorm.R +\name{mlr_pipeops_nn_batch_norm2d} +\alias{mlr_pipeops_nn_batch_norm2d} +\alias{PipeOpTorchBatchNorm2D} +\title{2D Batch Normalization} +\description{ +Applies Batch Normalization for each channel across a batch of data. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Internals}{ + +Calls \code{\link[torch:nn_batch_norm2d]{torch::nn_batch_norm2d()}}. +The parameter \code{num_features} is inferred as the second dimension of the input shape. +} + +\section{Parameters}{ + +\itemize{ +\item \code{eps} :: \code{numeric(1)}\cr +A value added to the denominator for numerical stability. Default: \code{1e-5}. +\item \code{momentum} :: \code{numeric(1)}\cr +The value used for the running_mean and running_var computation. Can be set to \code{NULL} for cumulative moving average +(i.e. simple average). Default: 0.1 +\item \code{affine} :: \code{logical(1)}\cr +a boolean value that when set to \code{TRUE}, this module has learnable affine parameters. Default: \code{TRUE} +\item \code{track_running_stats} :: \code{logical(1)}\cr +a boolean value that when set to \code{TRUE}, this module tracks the running mean and variance, and when set to \code{FALSE}, +this module does not track such statistics and always uses batch statistics in both training and eval modes. +Default: \code{TRUE} +} +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_batch_norm2d") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchBatchNorm} -> \code{PipeOpTorchBatchNorm2D} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchBatchNorm2D-new}{\code{PipeOpTorchBatchNorm2D$new()}} +\item \href{#method-PipeOpTorchBatchNorm2D-clone}{\code{PipeOpTorchBatchNorm2D$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchBatchNorm2D-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchBatchNorm2D$new(id = "nn_batch_norm2d", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchBatchNorm2D-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchBatchNorm2D$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_batch_norm3d.Rd b/man/mlr_pipeops_nn_batch_norm3d.Rd new file mode 100644 index 00000000..0c881b80 --- /dev/null +++ b/man/mlr_pipeops_nn_batch_norm3d.Rd @@ -0,0 +1,177 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchBatchNorm.R +\name{mlr_pipeops_nn_batch_norm3d} +\alias{mlr_pipeops_nn_batch_norm3d} +\alias{PipeOpTorchBatchNorm3D} +\title{3D Batch Normalization} +\description{ +Applies Batch Normalization for each channel across a batch of data. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Internals}{ + +Calls \code{\link[torch:nn_batch_norm3d]{torch::nn_batch_norm3d()}}. +The parameter \code{num_features} is inferred as the second dimension of the input shape. +} + +\section{Parameters}{ + +\itemize{ +\item \code{eps} :: \code{numeric(1)}\cr +A value added to the denominator for numerical stability. Default: \code{1e-5}. +\item \code{momentum} :: \code{numeric(1)}\cr +The value used for the running_mean and running_var computation. Can be set to \code{NULL} for cumulative moving average +(i.e. simple average). Default: 0.1 +\item \code{affine} :: \code{logical(1)}\cr +a boolean value that when set to \code{TRUE}, this module has learnable affine parameters. Default: \code{TRUE} +\item \code{track_running_stats} :: \code{logical(1)}\cr +a boolean value that when set to \code{TRUE}, this module tracks the running mean and variance, and when set to \code{FALSE}, +this module does not track such statistics and always uses batch statistics in both training and eval modes. +Default: \code{TRUE} +} +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_batch_norm3d") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchBatchNorm} -> \code{PipeOpTorchBatchNorm3D} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchBatchNorm3D-new}{\code{PipeOpTorchBatchNorm3D$new()}} +\item \href{#method-PipeOpTorchBatchNorm3D-clone}{\code{PipeOpTorchBatchNorm3D$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchBatchNorm3D-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchBatchNorm3D$new(id = "nn_batch_norm3d", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchBatchNorm3D-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchBatchNorm3D$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_celu.Rd b/man/mlr_pipeops_nn_celu.Rd new file mode 100644 index 00000000..b72be474 --- /dev/null +++ b/man/mlr_pipeops_nn_celu.Rd @@ -0,0 +1,168 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_celu} +\alias{mlr_pipeops_nn_celu} +\alias{PipeOpTorchCELU} +\title{CELU Activation Function} +\description{ +Applies element-wise, \eqn{CELU(x) = max(0,x) + min(0, \alpha * (exp(x \alpha) - 1))}. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{alpha} :: \code{numeric(1)}\cr +The alpha value for the ELU formulation. Default: 1.0 +\item \code{inplace} :: \code{logical(1)}\cr +Whether to do the operation in-place. Default: \code{FALSE}. +} +} + +\section{Internals}{ + Calls \code{\link[torch:nn_celu]{torch::nn_celu()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_celu") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchCELU} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchCELU-new}{\code{PipeOpTorchCELU$new()}} +\item \href{#method-PipeOpTorchCELU-clone}{\code{PipeOpTorchCELU$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchCELU-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchCELU$new(id = "nn_celu", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchCELU-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchCELU$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_conv1d.Rd b/man/mlr_pipeops_nn_conv1d.Rd new file mode 100644 index 00000000..e84c6cdc --- /dev/null +++ b/man/mlr_pipeops_nn_conv1d.Rd @@ -0,0 +1,183 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchConv.R +\name{mlr_pipeops_nn_conv1d} +\alias{mlr_pipeops_nn_conv1d} +\alias{PipeOpTorchConv1D} +\title{1D Convolution} +\description{ +Applies a 1D convolution over an input signal composed of several input +planes. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{out_channels} :: \code{integer(1)}\cr +Number of channels produced by the convolution. +\item \code{kernel_size} :: \code{integer()}\cr +Size of the convolving kernel. +\item \code{stride} :: \code{integer()}\cr +Stride of the convolution. The default is 1. +\item \code{padding} :: \code{integer()}\cr +‘dilation * (kernel_size - 1) - padding’ zero-padding will be added to both sides of the input. Default: 0. +\item \code{groups} :: \code{integer()}\cr +Number of blocked connections from input channels to output channels. Default: 1 +\item \code{bias} :: \code{logical(1)}\cr +If ‘TRUE’, adds a learnable bias to the output. Default: ‘TRUE’. +\item \code{dilation} :: \code{integer()}\cr +Spacing between kernel elements. Default: 1. +\item \code{padding_mode} :: \code{character(1)}\cr +The padding mode. One of \code{"zeros"}, \code{"reflect"}, \code{"replicate"}, or \code{"circular"}. Default is \code{"zeros"}. +} +} + +\section{Internals}{ + +Calls \code{\link[torch:nn_conv1d]{torch::nn_conv1d()}} when trained. +The paramter \code{in_channels} is inferred from the second dimension of the input tensor. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_conv1d", kernel_size = 10, out_channels = 1) +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchConv} -> \code{PipeOpTorchConv1D} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchConv1D-new}{\code{PipeOpTorchConv1D$new()}} +\item \href{#method-PipeOpTorchConv1D-clone}{\code{PipeOpTorchConv1D$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchConv1D-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchConv1D$new(id = "nn_conv1d", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchConv1D-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchConv1D$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_conv2d.Rd b/man/mlr_pipeops_nn_conv2d.Rd new file mode 100644 index 00000000..4ccbfede --- /dev/null +++ b/man/mlr_pipeops_nn_conv2d.Rd @@ -0,0 +1,183 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchConv.R +\name{mlr_pipeops_nn_conv2d} +\alias{mlr_pipeops_nn_conv2d} +\alias{PipeOpTorchConv2D} +\title{2D Convolution} +\description{ +Applies a 2D convolution over an input image composed of several input +planes. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Internals}{ + +Calls \code{\link[torch:nn_conv2d]{torch::nn_conv2d()}} when trained. +The paramter \code{in_channels} is inferred from the second dimension of the input tensor. +} + +\section{Parameters}{ + +\itemize{ +\item \code{out_channels} :: \code{integer(1)}\cr +Number of channels produced by the convolution. +\item \code{kernel_size} :: \code{integer()}\cr +Size of the convolving kernel. +\item \code{stride} :: \code{integer()}\cr +Stride of the convolution. The default is 1. +\item \code{padding} :: \code{integer()}\cr +‘dilation * (kernel_size - 1) - padding’ zero-padding will be added to both sides of the input. Default: 0. +\item \code{groups} :: \code{integer()}\cr +Number of blocked connections from input channels to output channels. Default: 1 +\item \code{bias} :: \code{logical(1)}\cr +If ‘TRUE’, adds a learnable bias to the output. Default: ‘TRUE’. +\item \code{dilation} :: \code{integer()}\cr +Spacing between kernel elements. Default: 1. +\item \code{padding_mode} :: \code{character(1)}\cr +The padding mode. One of \code{"zeros"}, \code{"reflect"}, \code{"replicate"}, or \code{"circular"}. Default is \code{"zeros"}. +} +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_conv2d", kernel_size = 10, out_channels = 1) +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchConv} -> \code{PipeOpTorchConv2D} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchConv2D-new}{\code{PipeOpTorchConv2D$new()}} +\item \href{#method-PipeOpTorchConv2D-clone}{\code{PipeOpTorchConv2D$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchConv2D-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchConv2D$new(id = "nn_conv2d", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchConv2D-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchConv2D$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_conv3d.Rd b/man/mlr_pipeops_nn_conv3d.Rd new file mode 100644 index 00000000..f3838ed0 --- /dev/null +++ b/man/mlr_pipeops_nn_conv3d.Rd @@ -0,0 +1,183 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchConv.R +\name{mlr_pipeops_nn_conv3d} +\alias{mlr_pipeops_nn_conv3d} +\alias{PipeOpTorchConv3D} +\title{3D Convolution} +\description{ +Applies a 3D convolution over an input image composed of several input +planes. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Internals}{ + +Calls \code{\link[torch:nn_conv3d]{torch::nn_conv3d()}} when trained. +The paramter \code{in_channels} is inferred from the second dimension of the input tensor. +} + +\section{Parameters}{ + +\itemize{ +\item \code{out_channels} :: \code{integer(1)}\cr +Number of channels produced by the convolution. +\item \code{kernel_size} :: \code{integer()}\cr +Size of the convolving kernel. +\item \code{stride} :: \code{integer()}\cr +Stride of the convolution. The default is 1. +\item \code{padding} :: \code{integer()}\cr +‘dilation * (kernel_size - 1) - padding’ zero-padding will be added to both sides of the input. Default: 0. +\item \code{groups} :: \code{integer()}\cr +Number of blocked connections from input channels to output channels. Default: 1 +\item \code{bias} :: \code{logical(1)}\cr +If ‘TRUE’, adds a learnable bias to the output. Default: ‘TRUE’. +\item \code{dilation} :: \code{integer()}\cr +Spacing between kernel elements. Default: 1. +\item \code{padding_mode} :: \code{character(1)}\cr +The padding mode. One of \code{"zeros"}, \code{"reflect"}, \code{"replicate"}, or \code{"circular"}. Default is \code{"zeros"}. +} +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_conv3d", kernel_size = 10, out_channels = 1) +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchConv} -> \code{PipeOpTorchConv3D} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchConv3D-new}{\code{PipeOpTorchConv3D$new()}} +\item \href{#method-PipeOpTorchConv3D-clone}{\code{PipeOpTorchConv3D$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchConv3D-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchConv3D$new(id = "nn_conv3d", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchConv3D-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchConv3D$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_conv_transpose1d.Rd b/man/mlr_pipeops_nn_conv_transpose1d.Rd new file mode 100644 index 00000000..8ec2499b --- /dev/null +++ b/man/mlr_pipeops_nn_conv_transpose1d.Rd @@ -0,0 +1,186 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchConvTranspose.R +\name{mlr_pipeops_nn_conv_transpose1d} +\alias{mlr_pipeops_nn_conv_transpose1d} +\alias{PipeOpTorchConvTranspose1D} +\title{Transpose 1D Convolution} +\description{ +Transpose 1D Convolution + +Transpose 1D Convolution +} +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{out_channels} :: \code{integer(1)}\cr +Number of output channels produce by the convolution. +\item \code{kernel_size} :: \code{integer()}\cr +Size of the convolving kernel. +\item \code{stride} :: \code{integer()}\cr +Stride of the convolution. Default: 1. +\item \code{padding} :: \verb{ }integer()`\cr +‘dilation * (kernel_size - 1) - padding’ zero-padding will be added to both sides of the input. Default: 0. +\item \code{output_padding} ::\code{integer()}\cr +Additional size added to one side of the output shape. Default: 0. +\item \code{groups} :: \code{integer()}\cr +Number of blocked connections from input channels to output channels. Default: 1 +\item \code{bias} :: \code{logical(1)}\cr +If ‘True’, adds a learnable bias to the output. Default: ‘TRUE’. +\item \code{dilation} :: \code{integer()}\cr +Spacing between kernel elements. Default: 1. +\item \code{padding_mode} :: \code{character(1)}\cr +The padding mode. One of \code{"zeros"}, \code{"reflect"}, \code{"replicate"}, or \code{"circular"}. Default is \code{"zeros"}. +} +} + +\section{Internals}{ + +Calls \code{\link{nn_conv_transpose1d}}. +The parameter \code{in_channels} is inferred as the second dimension of the input tensor. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_conv_transpose1d", kernel_size = 3, out_channels = 2) +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchConvTranspose} -> \code{PipeOpTorchConvTranspose1D} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchConvTranspose1D-new}{\code{PipeOpTorchConvTranspose1D$new()}} +\item \href{#method-PipeOpTorchConvTranspose1D-clone}{\code{PipeOpTorchConvTranspose1D$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchConvTranspose1D-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchConvTranspose1D$new(id = "nn_conv_transpose1d", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchConvTranspose1D-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchConvTranspose1D$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_conv_transpose2d.Rd b/man/mlr_pipeops_nn_conv_transpose2d.Rd new file mode 100644 index 00000000..f68e61c3 --- /dev/null +++ b/man/mlr_pipeops_nn_conv_transpose2d.Rd @@ -0,0 +1,185 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchConvTranspose.R +\name{mlr_pipeops_nn_conv_transpose2d} +\alias{mlr_pipeops_nn_conv_transpose2d} +\alias{PipeOpTorchConvTranspose2D} +\title{Transpose 2D Convolution} +\description{ +Applies a 2D transposed convolution operator over an input image +composed of several input planes, sometimes also called "deconvolution". +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Internals}{ + +Calls \code{\link{nn_conv_transpose2d}}. +The parameter \code{in_channels} is inferred as the second dimension of the input tensor. +} + +\section{Parameters}{ + +\itemize{ +\item \code{out_channels} :: \code{integer(1)}\cr +Number of output channels produce by the convolution. +\item \code{kernel_size} :: \code{integer()}\cr +Size of the convolving kernel. +\item \code{stride} :: \code{integer()}\cr +Stride of the convolution. Default: 1. +\item \code{padding} :: \verb{ }integer()`\cr +‘dilation * (kernel_size - 1) - padding’ zero-padding will be added to both sides of the input. Default: 0. +\item \code{output_padding} ::\code{integer()}\cr +Additional size added to one side of the output shape. Default: 0. +\item \code{groups} :: \code{integer()}\cr +Number of blocked connections from input channels to output channels. Default: 1 +\item \code{bias} :: \code{logical(1)}\cr +If ‘True’, adds a learnable bias to the output. Default: ‘TRUE’. +\item \code{dilation} :: \code{integer()}\cr +Spacing between kernel elements. Default: 1. +\item \code{padding_mode} :: \code{character(1)}\cr +The padding mode. One of \code{"zeros"}, \code{"reflect"}, \code{"replicate"}, or \code{"circular"}. Default is \code{"zeros"}. +} +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_conv_transpose2d", kernel_size = 3, out_channels = 2) +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchConvTranspose} -> \code{PipeOpTorchConvTranspose2D} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchConvTranspose2D-new}{\code{PipeOpTorchConvTranspose2D$new()}} +\item \href{#method-PipeOpTorchConvTranspose2D-clone}{\code{PipeOpTorchConvTranspose2D$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchConvTranspose2D-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchConvTranspose2D$new(id = "nn_conv_transpose2d", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchConvTranspose2D-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchConvTranspose2D$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_conv_transpose3d.Rd b/man/mlr_pipeops_nn_conv_transpose3d.Rd new file mode 100644 index 00000000..20ecbf99 --- /dev/null +++ b/man/mlr_pipeops_nn_conv_transpose3d.Rd @@ -0,0 +1,185 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchConvTranspose.R +\name{mlr_pipeops_nn_conv_transpose3d} +\alias{mlr_pipeops_nn_conv_transpose3d} +\alias{PipeOpTorchConvTranspose3D} +\title{Transpose 3D Convolution} +\description{ +Applies a 3D transposed convolution operator over an input image +composed of several input planes, sometimes also called "deconvolution" +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Internals}{ + +Calls \code{\link{nn_conv_transpose3d}}. +The parameter \code{in_channels} is inferred as the second dimension of the input tensor. +} + +\section{Parameters}{ + +\itemize{ +\item \code{out_channels} :: \code{integer(1)}\cr +Number of output channels produce by the convolution. +\item \code{kernel_size} :: \code{integer()}\cr +Size of the convolving kernel. +\item \code{stride} :: \code{integer()}\cr +Stride of the convolution. Default: 1. +\item \code{padding} :: \verb{ }integer()`\cr +‘dilation * (kernel_size - 1) - padding’ zero-padding will be added to both sides of the input. Default: 0. +\item \code{output_padding} ::\code{integer()}\cr +Additional size added to one side of the output shape. Default: 0. +\item \code{groups} :: \code{integer()}\cr +Number of blocked connections from input channels to output channels. Default: 1 +\item \code{bias} :: \code{logical(1)}\cr +If ‘True’, adds a learnable bias to the output. Default: ‘TRUE’. +\item \code{dilation} :: \code{integer()}\cr +Spacing between kernel elements. Default: 1. +\item \code{padding_mode} :: \code{character(1)}\cr +The padding mode. One of \code{"zeros"}, \code{"reflect"}, \code{"replicate"}, or \code{"circular"}. Default is \code{"zeros"}. +} +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_conv_transpose3d", kernel_size = 3, out_channels = 2) +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchConvTranspose} -> \code{PipeOpTorchConvTranspose3D} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchConvTranspose3D-new}{\code{PipeOpTorchConvTranspose3D$new()}} +\item \href{#method-PipeOpTorchConvTranspose3D-clone}{\code{PipeOpTorchConvTranspose3D$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchConvTranspose3D-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchConvTranspose3D$new(id = "nn_conv_transpose3d", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchConvTranspose3D-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchConvTranspose3D$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_dropout.Rd b/man/mlr_pipeops_nn_dropout.Rd new file mode 100644 index 00000000..e9b06965 --- /dev/null +++ b/man/mlr_pipeops_nn_dropout.Rd @@ -0,0 +1,171 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchDropout.R +\name{mlr_pipeops_nn_dropout} +\alias{mlr_pipeops_nn_dropout} +\alias{PipeOpTorchDropout} +\title{Dropout} +\description{ +During training, randomly zeroes some of the elements of the input +tensor with probability \code{p} using samples from a Bernoulli +distribution. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{p} :: \code{numeric(1)}\cr +Probability of an element to be zeroed. Default: 0.5 inplace +\item \code{inplace} :: \code{logical(1)}\cr +If set to \code{TRUE}, will do this operation in-place. Default: \code{FALSE}. +} +} + +\section{Internals}{ + +Calls \code{\link[torch:nn_dropout]{torch::nn_dropout()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_dropout") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchDropout} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchDropout-new}{\code{PipeOpTorchDropout$new()}} +\item \href{#method-PipeOpTorchDropout-clone}{\code{PipeOpTorchDropout$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchDropout-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchDropout$new(id = "nn_dropout", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchDropout-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchDropout$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_elu.Rd b/man/mlr_pipeops_nn_elu.Rd new file mode 100644 index 00000000..254646b7 --- /dev/null +++ b/man/mlr_pipeops_nn_elu.Rd @@ -0,0 +1,169 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_elu} +\alias{mlr_pipeops_nn_elu} +\alias{PipeOpTorchELU} +\title{ELU Activation Function} +\description{ +Applies element-wise, +\deqn{ELU(x) = max(0,x) + min(0, \alpha * (exp(x) - 1))}. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{alpha} :: \code{numeric(1)}\cr +The alpha value for the ELU formulation. Default: 1.0 +\item \code{inplace} :: \code{logical(1)}\cr +Whether to do the operation in-place. Default: \code{FALSE}. +} +} + +\section{Internals}{ + Calls \code{\link[torch:nn_elu]{torch::nn_elu()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_elu") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchELU} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchELU-new}{\code{PipeOpTorchELU$new()}} +\item \href{#method-PipeOpTorchELU-clone}{\code{PipeOpTorchELU$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchELU-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchELU$new(id = "nn_elu", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchELU-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchELU$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_flatten.Rd b/man/mlr_pipeops_nn_flatten.Rd new file mode 100644 index 00000000..557ef863 --- /dev/null +++ b/man/mlr_pipeops_nn_flatten.Rd @@ -0,0 +1,167 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchReshape.R +\name{mlr_pipeops_nn_flatten} +\alias{mlr_pipeops_nn_flatten} +\alias{PipeOpTorchFlatten} +\title{Flattens a Tensor} +\description{ +For use with \link[torch]{nn_sequential}. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\code{start_dim} :: \code{integer(1)}\cr +At wich dimension to start flattening. Default is 2. +\code{end_dim} :: \code{integer(1)}\cr +At wich dimension to stop flattening. Default is -1. +} + +\section{Internals}{ + +Calls \code{\link[torch:nn_flatten]{torch::nn_flatten()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_flatten") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchFlatten} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchFlatten-new}{\code{PipeOpTorchFlatten$new()}} +\item \href{#method-PipeOpTorchFlatten-clone}{\code{PipeOpTorchFlatten$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchFlatten-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchFlatten$new(id = "nn_flatten", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchFlatten-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchFlatten$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_gelu.Rd b/man/mlr_pipeops_nn_gelu.Rd new file mode 100644 index 00000000..109fefb1 --- /dev/null +++ b/man/mlr_pipeops_nn_gelu.Rd @@ -0,0 +1,166 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_gelu} +\alias{mlr_pipeops_nn_gelu} +\alias{PipeOpTorchGELU} +\title{GELU Activation Function} +\description{ +Gelu +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{approximate} :: \code{character(1)}\cr +Whether to use an approximation algorithm. Default is \code{"none"}. +} +} + +\section{Internals}{ + Calls \code{\link[torch:nn_gelu]{torch::nn_gelu()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_gelu") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchGELU} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchGELU-new}{\code{PipeOpTorchGELU$new()}} +\item \href{#method-PipeOpTorchGELU-clone}{\code{PipeOpTorchGELU$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchGELU-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchGELU$new(id = "nn_gelu", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchGELU-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchGELU$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_glu.Rd b/man/mlr_pipeops_nn_glu.Rd new file mode 100644 index 00000000..cf1d9e24 --- /dev/null +++ b/man/mlr_pipeops_nn_glu.Rd @@ -0,0 +1,166 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_glu} +\alias{mlr_pipeops_nn_glu} +\alias{PipeOpTorchGLU} +\title{GLU Activation Function} +\description{ +The gated linear unit. Computes: +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{dim} :: \code{integer(1)}\cr +Dimension on which to split the input. Default: -1 +} +} + +\section{Internals}{ + Calls \code{\link[torch:nn_glu]{torch::nn_glu()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_glu") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchGLU} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchGLU-new}{\code{PipeOpTorchGLU$new()}} +\item \href{#method-PipeOpTorchGLU-clone}{\code{PipeOpTorchGLU$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchGLU-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchGLU$new(id = "nn_glu", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchGLU-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchGLU$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_hardshrink.Rd b/man/mlr_pipeops_nn_hardshrink.Rd new file mode 100644 index 00000000..a66d425f --- /dev/null +++ b/man/mlr_pipeops_nn_hardshrink.Rd @@ -0,0 +1,166 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_hardshrink} +\alias{mlr_pipeops_nn_hardshrink} +\alias{PipeOpTorchHardShrink} +\title{Hard Shrink Activation Function} +\description{ +Applies the hard shrinkage function element-wise +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{lambd} :: \code{numeric(1)}\cr +The lambda value for the Hardshrink formulation formulation. Default 0.5. +} +} + +\section{Internals}{ + Calls \code{\link[torch:nn_hardshrink]{torch::nn_hardshrink()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_hardshrink") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchHardShrink} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchHardShrink-new}{\code{PipeOpTorchHardShrink$new()}} +\item \href{#method-PipeOpTorchHardShrink-clone}{\code{PipeOpTorchHardShrink$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchHardShrink-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchHardShrink$new(id = "nn_hardshrink", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchHardShrink-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchHardShrink$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_hardsigmoid.Rd b/man/mlr_pipeops_nn_hardsigmoid.Rd new file mode 100644 index 00000000..290660e8 --- /dev/null +++ b/man/mlr_pipeops_nn_hardsigmoid.Rd @@ -0,0 +1,163 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_hardsigmoid} +\alias{mlr_pipeops_nn_hardsigmoid} +\alias{PipeOpTorchHardSigmoid} +\title{Hard Sigmoid Activation Function} +\description{ +Applies the element-wise function \eqn{\mbox{Hardsigmoid}(x) = \frac{ReLU6(x + 3)}{6}} +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +No parameters. +} + +\section{Internals}{ + Calls \code{\link[torch:nn_hardsigmoid]{torch::nn_hardsigmoid()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_hardsigmoid") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchHardSigmoid} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchHardSigmoid-new}{\code{PipeOpTorchHardSigmoid$new()}} +\item \href{#method-PipeOpTorchHardSigmoid-clone}{\code{PipeOpTorchHardSigmoid$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchHardSigmoid-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchHardSigmoid$new(id = "nn_hardsigmoid", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchHardSigmoid-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchHardSigmoid$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_hardtanh.Rd b/man/mlr_pipeops_nn_hardtanh.Rd new file mode 100644 index 00000000..b0162737 --- /dev/null +++ b/man/mlr_pipeops_nn_hardtanh.Rd @@ -0,0 +1,164 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_hardtanh} +\alias{mlr_pipeops_nn_hardtanh} +\alias{PipeOpTorchHardTanh} +\title{Hard Tanh Activation Function} +\description{ +Applies the HardTanh function element-wise. +} +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{min_val} :: \code{numeric(1)}\cr +Minimum value of the linear region range. Default: -1. +\item \code{max_val} :: \code{numeric(1)}\cr +Maximum value of the linear region range. Default: 1. +\item \code{inplace} :: \code{logical(1)}\cr +Can optionally do the operation in-place. Default: \code{FALSE}. +} +} + +\section{Internals}{ + Calls \code{\link[torch:nn_hardtanh]{torch::nn_hardtanh()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_hardtanh") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchHardTanh} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchHardTanh-new}{\code{PipeOpTorchHardTanh$new()}} +\item \href{#method-PipeOpTorchHardTanh-clone}{\code{PipeOpTorchHardTanh$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchHardTanh-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchHardTanh$new(id = "nn_hardtanh", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchHardTanh-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchHardTanh$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_head.Rd b/man/mlr_pipeops_nn_head.Rd new file mode 100644 index 00000000..1588dfcc --- /dev/null +++ b/man/mlr_pipeops_nn_head.Rd @@ -0,0 +1,171 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchHead.R +\name{mlr_pipeops_nn_head} +\alias{mlr_pipeops_nn_head} +\alias{PipeOpTorchHead} +\title{Output Head} +\description{ +Output head for classification and regresssion. + +\strong{NOTE} +Because the method \verb{$shapes_out()} does not have access to the task, it returns \code{c(NA, NA)}. +When this \code{\link{PipeOp}} is trained however, the model descriptor has the correct output shape. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{bias} :: \code{logical(1)}\cr +Whether to use a bias. Default is \code{TRUE}. +} +} + +\section{Internals}{ + +Calls \code{\link[torch:nn_linear]{torch::nn_linear()}} with the input and output features inferred from the input shape / task. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_head") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchHead} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchHead-new}{\code{PipeOpTorchHead$new()}} +\item \href{#method-PipeOpTorchHead-clone}{\code{PipeOpTorchHead$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchHead-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchHead$new(id = "nn_head", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchHead-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchHead$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_layer_norm.Rd b/man/mlr_pipeops_nn_layer_norm.Rd new file mode 100644 index 00000000..22ef12cd --- /dev/null +++ b/man/mlr_pipeops_nn_layer_norm.Rd @@ -0,0 +1,173 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchLayerNorm.R +\name{mlr_pipeops_nn_layer_norm} +\alias{mlr_pipeops_nn_layer_norm} +\alias{PipeOpTorchLayerNorm} +\title{Layer Normalization} +\description{ +Applies Layer Normalization for last certain number of dimensions. +} +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{dims} :: \code{integer(1)}\cr +The number of dimensions over which will be normalized (starting from the last dimension). +\item \code{elementwise_affine} :: \code{logical(1)}\cr +Whether to learn affine-linear parameters initialized to \code{1} for weights and to \code{0} for biases. +The default is \code{TRUE}. +\item \code{eps} :: \code{numeric(1)}\cr +A value added to the denominator for numerical stability. +} +} + +\section{Internals}{ + +Calls \code{\link[torch:nn_layer_norm]{torch::nn_layer_norm()}} when trained. +The parameter \code{normalized_shape} is inferred as the dimensions of the last \code{dims} dimensions of the input shape. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_layer_norm", dims = 1) +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchLayerNorm} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchLayerNorm-new}{\code{PipeOpTorchLayerNorm$new()}} +\item \href{#method-PipeOpTorchLayerNorm-clone}{\code{PipeOpTorchLayerNorm$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchLayerNorm-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchLayerNorm$new(id = "nn_layer_norm", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchLayerNorm-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchLayerNorm$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_leaky_relu.Rd b/man/mlr_pipeops_nn_leaky_relu.Rd new file mode 100644 index 00000000..43a8127c --- /dev/null +++ b/man/mlr_pipeops_nn_leaky_relu.Rd @@ -0,0 +1,169 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_leaky_relu} +\alias{mlr_pipeops_nn_leaky_relu} +\alias{PipeOpTorchLeakyReLU} +\title{Leaky ReLU Activation Function} +\description{ +Applies element-wise, +\eqn{LeakyReLU(x) = max(0, x) + negative_slope * min(0, x)} +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{negative_slope} :: \code{numeric(1)}\cr +Controls the angle of the negative slope. Default: 1e-2. +\item \code{inplace} :: \code{logical(1)}\cr +Can optionally do the operation in-place. Default: ‘FALSE’. +} +} + +\section{Internals}{ + Calls \code{\link[torch:nn_hardswish]{torch::nn_hardswish()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_leaky_relu") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchLeakyReLU} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchLeakyReLU-new}{\code{PipeOpTorchLeakyReLU$new()}} +\item \href{#method-PipeOpTorchLeakyReLU-clone}{\code{PipeOpTorchLeakyReLU$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchLeakyReLU-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchLeakyReLU$new(id = "nn_leaky_relu", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchLeakyReLU-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchLeakyReLU$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_linear.Rd b/man/mlr_pipeops_nn_linear.Rd new file mode 100644 index 00000000..d96eec84 --- /dev/null +++ b/man/mlr_pipeops_nn_linear.Rd @@ -0,0 +1,171 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchLinear.R +\name{mlr_pipeops_nn_linear} +\alias{mlr_pipeops_nn_linear} +\alias{PipeOpTorchLinear} +\title{Linear Layer} +\description{ +Applies a linear transformation to the incoming data: \eqn{y = xA^T + b}. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{out_features} :: \code{integer(1)}\cr +The output features of the linear layer. +\item \code{bias} :: \code{logical(1)}\cr +Whether to use a bias. +Default is \code{TRUE}. +} +} + +\section{Internals}{ + +Calls \code{\link[torch:nn_linear]{torch::nn_linear()}} when trained where the parameter \code{in_features} is inferred as the second +to last dimension of the input tensor. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_linear", out_features = 10) +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchLinear} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchLinear-new}{\code{PipeOpTorchLinear$new()}} +\item \href{#method-PipeOpTorchLinear-clone}{\code{PipeOpTorchLinear$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchLinear-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchLinear$new(id = "nn_linear", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchLinear-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchLinear$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_log_sigmoid.Rd b/man/mlr_pipeops_nn_log_sigmoid.Rd new file mode 100644 index 00000000..a91b3934 --- /dev/null +++ b/man/mlr_pipeops_nn_log_sigmoid.Rd @@ -0,0 +1,163 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_log_sigmoid} +\alias{mlr_pipeops_nn_log_sigmoid} +\alias{PipeOpTorchLogSigmoid} +\title{Log Sigmoid Activation Function} +\description{ +Applies element-wise \eqn{LogSigmoid(x_i) = log(\frac{1}{1 + exp(-x_i)})} +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +No parameters. +} + +\section{Internals}{ + Calls \code{\link[torch:nn_log_sigmoid]{torch::nn_log_sigmoid()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_log_sigmoid") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchLogSigmoid} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchLogSigmoid-new}{\code{PipeOpTorchLogSigmoid$new()}} +\item \href{#method-PipeOpTorchLogSigmoid-clone}{\code{PipeOpTorchLogSigmoid$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchLogSigmoid-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchLogSigmoid$new(id = "nn_log_sigmoid", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchLogSigmoid-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchLogSigmoid$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_max_pool1d.Rd b/man/mlr_pipeops_nn_max_pool1d.Rd new file mode 100644 index 00000000..bf7efb71 --- /dev/null +++ b/man/mlr_pipeops_nn_max_pool1d.Rd @@ -0,0 +1,185 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchMaxPool.R +\name{mlr_pipeops_nn_max_pool1d} +\alias{mlr_pipeops_nn_max_pool1d} +\alias{PipeOpTorchMaxPool1D} +\title{1D Max Pooling} +\description{ +Applies a 1D max pooling over an input signal composed of several input +planes. +} +\section{Input and Output Channels}{ + +If \code{return_indices} is \code{FALSE} during construction, there is one input channel 'input' and one output channel 'output'. +If \code{return_indices} is \code{TRUE}, there are two output channels 'output' and 'indices'. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{kernel_size} :: \code{integer()}\cr +The size of the window. Can be single number or a vector. +\item \code{stride} :: (\verb{integer(1))}\cr +The stride of the window. Can be a single number or a vector. Default: \code{kernel_size} +\item \code{padding} :: \code{integer()}\cr +Implicit zero paddings on both sides of the input. Can be a single number or a tuple (padW,). Default: 0 +\item \code{dilation} :: \code{integer()}\cr +Controls the spacing between the kernel points; also known as the à trous algorithm. Default: 1 +\item \code{ceil_mode} :: \code{logical(1)}\cr +When True, will use ceil instead of floor to compute the output shape. Default: \code{FALSE} +} +} + +\section{Internals}{ + +Calls \code{\link[torch:nn_max_pool1d]{torch::nn_max_pool1d()}} during training. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_max_pool1d") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchMaxPool} -> \code{PipeOpTorchMaxPool1D} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchMaxPool1D-new}{\code{PipeOpTorchMaxPool1D$new()}} +\item \href{#method-PipeOpTorchMaxPool1D-clone}{\code{PipeOpTorchMaxPool1D$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchMaxPool1D-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchMaxPool1D$new( + id = "nn_max_pool1d", + return_indices = FALSE, + param_vals = list() +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{return_indices}}{(\code{logical(1)})\cr +Whether to return the indices. +If this is \code{TRUE}, there are two output channels \code{"output"} and \code{"indices"}.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchMaxPool1D-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchMaxPool1D$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_max_pool2d.Rd b/man/mlr_pipeops_nn_max_pool2d.Rd new file mode 100644 index 00000000..e2072247 --- /dev/null +++ b/man/mlr_pipeops_nn_max_pool2d.Rd @@ -0,0 +1,185 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchMaxPool.R +\name{mlr_pipeops_nn_max_pool2d} +\alias{mlr_pipeops_nn_max_pool2d} +\alias{PipeOpTorchMaxPool2D} +\title{2D Max Pooling} +\description{ +Applies a 2D max pooling over an input signal composed of several input +planes. +} +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Internals}{ + +Calls \code{\link[torch:nn_max_pool2d]{torch::nn_max_pool2d()}} during training. +} + +\section{Input and Output Channels}{ + +If \code{return_indices} is \code{FALSE} during construction, there is one input channel 'input' and one output channel 'output'. +If \code{return_indices} is \code{TRUE}, there are two output channels 'output' and 'indices'. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{kernel_size} :: \code{integer()}\cr +The size of the window. Can be single number or a vector. +\item \code{stride} :: (\verb{integer(1))}\cr +The stride of the window. Can be a single number or a vector. Default: \code{kernel_size} +\item \code{padding} :: \code{integer()}\cr +Implicit zero paddings on both sides of the input. Can be a single number or a tuple (padW,). Default: 0 +\item \code{dilation} :: \code{integer()}\cr +Controls the spacing between the kernel points; also known as the à trous algorithm. Default: 1 +\item \code{ceil_mode} :: \code{logical(1)}\cr +When True, will use ceil instead of floor to compute the output shape. Default: \code{FALSE} +} +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_max_pool2d") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchMaxPool} -> \code{PipeOpTorchMaxPool2D} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchMaxPool2D-new}{\code{PipeOpTorchMaxPool2D$new()}} +\item \href{#method-PipeOpTorchMaxPool2D-clone}{\code{PipeOpTorchMaxPool2D$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchMaxPool2D-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchMaxPool2D$new( + id = "nn_max_pool2d", + return_indices = FALSE, + param_vals = list() +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{return_indices}}{(\code{logical(1)})\cr +Whether to return the indices. +If this is \code{TRUE}, there are two output channels \code{"output"} and \code{"indices"}.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchMaxPool2D-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchMaxPool2D$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_max_pool3d.Rd b/man/mlr_pipeops_nn_max_pool3d.Rd new file mode 100644 index 00000000..0aa38a5d --- /dev/null +++ b/man/mlr_pipeops_nn_max_pool3d.Rd @@ -0,0 +1,185 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchMaxPool.R +\name{mlr_pipeops_nn_max_pool3d} +\alias{mlr_pipeops_nn_max_pool3d} +\alias{PipeOpTorchMaxPool3D} +\title{3D Max Pooling} +\description{ +Applies a 3D max pooling over an input signal composed of several input +planes. +} +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Internals}{ + +Calls \code{\link[torch:nn_max_pool3d]{torch::nn_max_pool3d()}} during training. +} + +\section{Input and Output Channels}{ + +If \code{return_indices} is \code{FALSE} during construction, there is one input channel 'input' and one output channel 'output'. +If \code{return_indices} is \code{TRUE}, there are two output channels 'output' and 'indices'. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{kernel_size} :: \code{integer()}\cr +The size of the window. Can be single number or a vector. +\item \code{stride} :: (\verb{integer(1))}\cr +The stride of the window. Can be a single number or a vector. Default: \code{kernel_size} +\item \code{padding} :: \code{integer()}\cr +Implicit zero paddings on both sides of the input. Can be a single number or a tuple (padW,). Default: 0 +\item \code{dilation} :: \code{integer()}\cr +Controls the spacing between the kernel points; also known as the à trous algorithm. Default: 1 +\item \code{ceil_mode} :: \code{logical(1)}\cr +When True, will use ceil instead of floor to compute the output shape. Default: \code{FALSE} +} +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_max_pool3d") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchMaxPool} -> \code{PipeOpTorchMaxPool3D} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchMaxPool3D-new}{\code{PipeOpTorchMaxPool3D$new()}} +\item \href{#method-PipeOpTorchMaxPool3D-clone}{\code{PipeOpTorchMaxPool3D$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchMaxPool3D-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchMaxPool3D$new( + id = "nn_max_pool3d", + return_indices = FALSE, + param_vals = list() +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{return_indices}}{(\code{logical(1)})\cr +Whether to return the indices. +If this is \code{TRUE}, there are two output channels \code{"output"} and \code{"indices"}.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchMaxPool3D-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchMaxPool3D$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_merge.Rd b/man/mlr_pipeops_nn_merge.Rd new file mode 100644 index 00000000..08574250 --- /dev/null +++ b/man/mlr_pipeops_nn_merge.Rd @@ -0,0 +1,172 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchMerge.R +\name{mlr_pipeops_nn_merge} +\alias{mlr_pipeops_nn_merge} +\alias{PipeOpTorchMerge} +\title{Merge Operation} +\description{ +Base class for merge operations such as addition (\code{\link{PipeOpTorchMergeSum}}), multiplication +(\code{\link{PipeOpTorchMergeProd}} or concatenation (\code{\link{PipeOpTorchMergeCat}}). +} +\section{State}{ + +The state is the value calculated by the public method \code{shapes_out()}. +} + +\section{Input and Output Channels}{ + +\code{PipeOpTorchMerge}s has either a \emph{vararg} input channel if the constructor argument \code{innum} is not set, or +input channels \code{"input1"}, ..., \code{"input"}. There is one output channel \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{Parameters}{ + See the respective child class. +} + +\section{Internals}{ + +Per default, the \code{private$.shapes_out()} method outputs the broadcasted tensors. There are two things to be aware: +\enumerate{ +\item \code{NA}s are assumed to batch (this should almost always be the batch size in the first dimension). +\item Tensors are expected to have the same number of dimensions, i.e. missing dimensions are not filled with 1s. +The reason is that again that the first dimension should be the batch dimension. +This private method can be overwritten by \code{\link{PipeOpTorch}}s inheriting from this class. +} +} + +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchMerge} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchMerge-new}{\code{PipeOpTorchMerge$new()}} +\item \href{#method-PipeOpTorchMerge-clone}{\code{PipeOpTorchMerge$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchMerge-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchMerge$new( + id, + module_generator, + param_set = ps(), + innum = 0, + param_vals = list() +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{module_generator}}{(\code{nn_module_generator})\cr +The torch module generator.} + +\item{\code{param_set}}{(\code{paradox::ParamSet})\cr +The parameter set.} + +\item{\code{innum}}{(\code{integer(1)})\cr +The number of inputs. Default is 0 which means there is one \emph{vararg} input channel.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchMerge-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchMerge$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_merge_cat.Rd b/man/mlr_pipeops_nn_merge_cat.Rd new file mode 100644 index 00000000..e7d9dac7 --- /dev/null +++ b/man/mlr_pipeops_nn_merge_cat.Rd @@ -0,0 +1,187 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchMerge.R +\name{mlr_pipeops_nn_merge_cat} +\alias{mlr_pipeops_nn_merge_cat} +\alias{PipeOpTorchMergeCat} +\title{Merge by Concatenation} +\description{ +Concatenates multiple tensors on a given dimension. +No broadcasting rules are applied here, you must reshape the tensors before to have the same shape. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. + + +\code{PipeOpTorchMerge}s has either a \emph{vararg} input channel if the constructor argument \code{innum} is not set, or +input channels \code{"input1"}, ..., \code{"input"}. There is one output channel \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{dim} :: \code{integer(1)}\cr +The dimension along which to concatenate the tensors. +} +} + +\section{Internals}{ + +Calls \code{\link[=nn_merge_cat]{nn_merge_cat()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_merge_cat") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchMerge} -> \code{PipeOpTorchMergeCat} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchMergeCat-new}{\code{PipeOpTorchMergeCat$new()}} +\item \href{#method-PipeOpTorchMergeCat-speak}{\code{PipeOpTorchMergeCat$speak()}} +\item \href{#method-PipeOpTorchMergeCat-clone}{\code{PipeOpTorchMergeCat$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchMergeCat-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchMergeCat$new(id = "nn_merge_cat", innum = 0, param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{innum}}{(\code{integer(1)})\cr +The number of inputs. Default is 0 which means there is one \emph{vararg} input channel.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchMergeCat-speak}{}}} +\subsection{Method \code{speak()}}{ +What does the cat say? +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchMergeCat$speak()}\if{html}{\out{
}} +} + +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchMergeCat-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchMergeCat$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_merge_prod.Rd b/man/mlr_pipeops_nn_merge_prod.Rd new file mode 100644 index 00000000..8fba4199 --- /dev/null +++ b/man/mlr_pipeops_nn_merge_prod.Rd @@ -0,0 +1,172 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchMerge.R +\name{mlr_pipeops_nn_merge_prod} +\alias{mlr_pipeops_nn_merge_prod} +\alias{PipeOpTorchMergeProd} +\title{Merge by Product} +\description{ +Calculates the product of all input tensors. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. + + +\code{PipeOpTorchMerge}s has either a \emph{vararg} input channel if the constructor argument \code{innum} is not set, or +input channels \code{"input1"}, ..., \code{"input"}. There is one output channel \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +No parameters. +} + +\section{Internals}{ + +Calls \code{\link[=nn_merge_prod]{nn_merge_prod()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_merge_prod") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchMerge} -> \code{PipeOpTorchMergeProd} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchMergeProd-new}{\code{PipeOpTorchMergeProd$new()}} +\item \href{#method-PipeOpTorchMergeProd-clone}{\code{PipeOpTorchMergeProd$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchMergeProd-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchMergeProd$new(id = "nn_merge_prod", innum = 0, param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{innum}}{(\code{integer(1)})\cr +The number of inputs. Default is 0 which means there is one \emph{vararg} input channel.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchMergeProd-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchMergeProd$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_merge_sum.Rd b/man/mlr_pipeops_nn_merge_sum.Rd new file mode 100644 index 00000000..25218e61 --- /dev/null +++ b/man/mlr_pipeops_nn_merge_sum.Rd @@ -0,0 +1,229 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchMerge.R +\name{mlr_pipeops_nn_merge_sum} +\alias{mlr_pipeops_nn_merge_sum} +\alias{PipeOpTorchMergeSum} +\title{Merge by Summation} +\description{ +Calculates the sum of all input tensors. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. + + +\code{PipeOpTorchMerge}s has either a \emph{vararg} input channel if the constructor argument \code{innum} is not set, or +input channels \code{"input1"}, ..., \code{"input"}. There is one output channel \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +No parameters. +} + +\section{Internals}{ + +Calls \code{\link[=nn_merge_sum]{nn_merge_sum()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_merge_sum") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} + +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{mlr3torch::PipeOpTorchMerge} -> \code{PipeOpTorchMergeSum} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchMergeSum-new}{\code{PipeOpTorchMergeSum$new()}} +\item \href{#method-PipeOpTorchMergeSum-clone}{\code{PipeOpTorchMergeSum$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchMergeSum-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchMergeSum$new(id = "nn_merge_sum", innum = 0, param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{innum}}{(\code{integer(1)})\cr +The number of inputs. Default is 0 which means there is one \emph{vararg} input channel.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchMergeSum-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchMergeSum$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_prelu.Rd b/man/mlr_pipeops_nn_prelu.Rd new file mode 100644 index 00000000..ab8cc9bf --- /dev/null +++ b/man/mlr_pipeops_nn_prelu.Rd @@ -0,0 +1,171 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_prelu} +\alias{mlr_pipeops_nn_prelu} +\alias{PipeOpTorchPReLU} +\title{PReLU Activation Function} +\description{ +Applies element-wise the function +\eqn{PReLU(x) = max(0,x) + weight * min(0,x)} +where weight is a learnable parameter. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{num_parameters} :: \code{integer(1)}: +Number of a to learn. Although it takes an int as input, there is only two values are legitimate: 1, or the +number of channels at input. Default: 1. +\item \code{init} :: \code{numeric(1)}\cr T +The initial value of a. Default: 0.25. +} +} + +\section{Internals}{ + Calls \code{\link[torch:nn_prelu]{torch::nn_prelu()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_prelu") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchPReLU} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchPReLU-new}{\code{PipeOpTorchPReLU$new()}} +\item \href{#method-PipeOpTorchPReLU-clone}{\code{PipeOpTorchPReLU$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchPReLU-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchPReLU$new(id = "nn_prelu", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchPReLU-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchPReLU$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_relu.Rd b/man/mlr_pipeops_nn_relu.Rd new file mode 100644 index 00000000..9c865f56 --- /dev/null +++ b/man/mlr_pipeops_nn_relu.Rd @@ -0,0 +1,166 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_relu} +\alias{mlr_pipeops_nn_relu} +\alias{PipeOpTorchReLU} +\title{ReLU Activation Function} +\description{ +Applies the rectified linear unit function element-wise. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{inplace} :: \code{logical(1)}\cr +Whether to do the operation in-place. Default: \code{FALSE}. +} +} + +\section{Internals}{ + Calls \code{\link[torch:nn_relu]{torch::nn_relu()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_relu") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchReLU} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchReLU-new}{\code{PipeOpTorchReLU$new()}} +\item \href{#method-PipeOpTorchReLU-clone}{\code{PipeOpTorchReLU$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchReLU-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchReLU$new(id = "nn_relu", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchReLU-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchReLU$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_relu6.Rd b/man/mlr_pipeops_nn_relu6.Rd new file mode 100644 index 00000000..3d4d1867 --- /dev/null +++ b/man/mlr_pipeops_nn_relu6.Rd @@ -0,0 +1,166 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_relu6} +\alias{mlr_pipeops_nn_relu6} +\alias{PipeOpTorchReLU6} +\title{ReLU6 Activation Function} +\description{ +Applies the element-wise function \eqn{ReLU6(x) = min(max(0,x), 6)}. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{inplace} :: \code{logical(1)}\cr +Whether to do the operation in-place. Default: \code{FALSE}. +} +} + +\section{Internals}{ + Calls \code{\link[torch:nn_relu6]{torch::nn_relu6()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_relu6") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchReLU6} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchReLU6-new}{\code{PipeOpTorchReLU6$new()}} +\item \href{#method-PipeOpTorchReLU6-clone}{\code{PipeOpTorchReLU6$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchReLU6-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchReLU6$new(id = "nn_relu6", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchReLU6-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchReLU6$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_reshape.Rd b/man/mlr_pipeops_nn_reshape.Rd new file mode 100644 index 00000000..6549fefd --- /dev/null +++ b/man/mlr_pipeops_nn_reshape.Rd @@ -0,0 +1,168 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchReshape.R +\name{mlr_pipeops_nn_reshape} +\alias{mlr_pipeops_nn_reshape} +\alias{PipeOpTorchReshape} +\title{Reshape a Tensor} +\description{ +Reshape a tensor to the given shape. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{shape} :: \code{integer(1)}\cr +The desired output shape. Unknown dimension (one at most) can either be specified as \code{-1} or \code{NA}. +} +} + +\section{Internals}{ + +Calls \code{\link[=nn_reshape]{nn_reshape()}} when trained. +This internally calls \code{\link[torch:torch_reshape]{torch::torch_reshape()}} with the given \code{shape}. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_reshape") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchReshape} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchReshape-new}{\code{PipeOpTorchReshape$new()}} +\item \href{#method-PipeOpTorchReshape-clone}{\code{PipeOpTorchReshape$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchReshape-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchReshape$new(id = "nn_reshape", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchReshape-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchReshape$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_rrelu.Rd b/man/mlr_pipeops_nn_rrelu.Rd new file mode 100644 index 00000000..6ad9af41 --- /dev/null +++ b/man/mlr_pipeops_nn_rrelu.Rd @@ -0,0 +1,170 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_rrelu} +\alias{mlr_pipeops_nn_rrelu} +\alias{PipeOpTorchRReLU} +\title{RReLU Activation Function} +\description{ +Randomized leaky ReLU. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{lower}:: \code{numeric(1)}\cr +Lower bound of the uniform distribution. Default: 1/8. +\item \code{upper}:: \code{numeric(1)}\cr +Upper bound of the uniform distribution. Default: 1/3. +\item \code{inplace} :: \code{logical(1)}\cr +Whether to do the operation in-place. Default: \code{FALSE}. +} +} + +\section{Internals}{ + Calls \code{\link[torch:nn_rrelu]{torch::nn_rrelu()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_rrelu") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchRReLU} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchRReLU-new}{\code{PipeOpTorchRReLU$new()}} +\item \href{#method-PipeOpTorchRReLU-clone}{\code{PipeOpTorchRReLU$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchRReLU-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchRReLU$new(id = "nn_rrelu", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchRReLU-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchRReLU$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_selu.Rd b/man/mlr_pipeops_nn_selu.Rd new file mode 100644 index 00000000..6e96b937 --- /dev/null +++ b/man/mlr_pipeops_nn_selu.Rd @@ -0,0 +1,169 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_selu} +\alias{mlr_pipeops_nn_selu} +\alias{PipeOpTorchSELU} +\title{SELU Activation Function} +\description{ +Applies element-wise, +\deqn{SELU(x) = scale * (max(0,x) + min(0, \alpha * (exp(x) - 1)))}, +with \eqn{\alpha=1.6732632423543772848170429916717} and +\eqn{scale=1.0507009873554804934193349852946}. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{inplace} :: \code{logical(1)}\cr +Whether to do the operation in-place. Default: \code{FALSE}. +} +} + +\section{Internals}{ + Calls \code{\link[torch:nn_selu]{torch::nn_selu()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_selu") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchSELU} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchSELU-new}{\code{PipeOpTorchSELU$new()}} +\item \href{#method-PipeOpTorchSELU-clone}{\code{PipeOpTorchSELU$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchSELU-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchSELU$new(id = "nn_selu", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchSELU-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchSELU$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_sigmoid.Rd b/man/mlr_pipeops_nn_sigmoid.Rd new file mode 100644 index 00000000..7f057aa4 --- /dev/null +++ b/man/mlr_pipeops_nn_sigmoid.Rd @@ -0,0 +1,163 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_sigmoid} +\alias{mlr_pipeops_nn_sigmoid} +\alias{PipeOpTorchSigmoid} +\title{Sigmoid Activation Function} +\description{ +Applies element-wise \eqn{Sigmoid(x_i) = \frac{1}{1 + exp(-x_i)}} +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +No parameters. +} + +\section{Internals}{ + Calls \code{\link[torch:nn_sigmoid]{torch::nn_sigmoid()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_sigmoid") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchSigmoid} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchSigmoid-new}{\code{PipeOpTorchSigmoid$new()}} +\item \href{#method-PipeOpTorchSigmoid-clone}{\code{PipeOpTorchSigmoid$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchSigmoid-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchSigmoid$new(id = "nn_sigmoid", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchSigmoid-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchSigmoid$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_softmax.Rd b/man/mlr_pipeops_nn_softmax.Rd new file mode 100644 index 00000000..80d38cea --- /dev/null +++ b/man/mlr_pipeops_nn_softmax.Rd @@ -0,0 +1,167 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchSoftmax.R +\name{mlr_pipeops_nn_softmax} +\alias{mlr_pipeops_nn_softmax} +\alias{PipeOpTorchSoftmax} +\title{Softmax} +\description{ +Applies a softmax function. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{dim} :: \code{integer(1)}\cr +A dimension along which Softmax will be computed (so every slice along dim will sum to 1). +} +} + +\section{Internals}{ + +Calls \code{\link[torch:nn_softmax]{torch::nn_softmax()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_softmax") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchSoftmax} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchSoftmax-new}{\code{PipeOpTorchSoftmax$new()}} +\item \href{#method-PipeOpTorchSoftmax-clone}{\code{PipeOpTorchSoftmax$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchSoftmax-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchSoftmax$new(id = "nn_softmax", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchSoftmax-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchSoftmax$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_softplus.Rd b/man/mlr_pipeops_nn_softplus.Rd new file mode 100644 index 00000000..3056866c --- /dev/null +++ b/man/mlr_pipeops_nn_softplus.Rd @@ -0,0 +1,168 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_softplus} +\alias{mlr_pipeops_nn_softplus} +\alias{PipeOpTorchSoftPlus} +\title{SoftPlus Activation Function} +\description{ +Applies element-wise, the function \eqn{Softplus(x) = 1/\beta * log(1 + exp(\beta * x))}. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{beta} :: \code{numeric(1)}\cr +The beta value for the Softplus formulation. Default: 1 +\item \code{threshold} :: \code{numeric(1)}\cr +Values above this revert to a linear function. Default: 20 +} +} + +\section{Internals}{ + Calls \code{\link[torch:nn_softplus]{torch::nn_softplus()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_softplus") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchSoftPlus} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchSoftPlus-new}{\code{PipeOpTorchSoftPlus$new()}} +\item \href{#method-PipeOpTorchSoftPlus-clone}{\code{PipeOpTorchSoftPlus$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchSoftPlus-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchSoftPlus$new(id = "nn_softplus", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchSoftPlus-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchSoftPlus$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_softshrink.Rd b/man/mlr_pipeops_nn_softshrink.Rd new file mode 100644 index 00000000..3ec4ad76 --- /dev/null +++ b/man/mlr_pipeops_nn_softshrink.Rd @@ -0,0 +1,166 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_softshrink} +\alias{mlr_pipeops_nn_softshrink} +\alias{PipeOpTorchSoftShrink} +\title{Soft Shrink Activation Function} +\description{ +Applies the soft shrinkage function elementwise +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{lamd} :: \code{numeric(1)}\cr +The lambda (must be no less than zero) value for the Softshrink formulation. Default: 0.5 +} +} + +\section{Internals}{ + Calls \code{\link[torch:nn_softshrink]{torch::nn_softshrink()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_softshrink") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchSoftShrink} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchSoftShrink-new}{\code{PipeOpTorchSoftShrink$new()}} +\item \href{#method-PipeOpTorchSoftShrink-clone}{\code{PipeOpTorchSoftShrink$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchSoftShrink-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchSoftShrink$new(id = "nn_softshrink", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchSoftShrink-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchSoftShrink$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_softsign.Rd b/man/mlr_pipeops_nn_softsign.Rd new file mode 100644 index 00000000..44e3c276 --- /dev/null +++ b/man/mlr_pipeops_nn_softsign.Rd @@ -0,0 +1,163 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_softsign} +\alias{mlr_pipeops_nn_softsign} +\alias{PipeOpTorchSoftSign} +\title{SoftSign Activation Function} +\description{ +Applies element-wise, the function \eqn{SoftSign(x) = x/(1 + |x|} +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +No parameters. +} + +\section{Internals}{ + Calls \code{\link[torch:nn_softsign]{torch::nn_softsign()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_softsign") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchSoftSign} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchSoftSign-new}{\code{PipeOpTorchSoftSign$new()}} +\item \href{#method-PipeOpTorchSoftSign-clone}{\code{PipeOpTorchSoftSign$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchSoftSign-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchSoftSign$new(id = "nn_softsign", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchSoftSign-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchSoftSign$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_squeeze.Rd b/man/mlr_pipeops_nn_squeeze.Rd new file mode 100644 index 00000000..4e9a71de --- /dev/null +++ b/man/mlr_pipeops_nn_squeeze.Rd @@ -0,0 +1,314 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchReshape.R +\name{mlr_pipeops_nn_squeeze} +\alias{mlr_pipeops_nn_squeeze} +\alias{PipeOpTorchSqueeze} +\alias{PipeOpTorchUnsqueeze} +\title{Squeeze a Tensor} +\description{ +Squeezes a tensor by calling \code{\link[torch:torch_squeeze]{torch::torch_squeeze()}} with the given dimension \code{dim}. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. + + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. + + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. + + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{dim} :: \code{integer(1)}\cr +The dimension to squeeze. If \code{NULL}, all dimensions of size 1 will be squeezed. +Negative values are interpreted downwards from the last dimension. +} + + +\itemize{ +\item \code{dim} :: \code{integer(1)}\cr +The dimension which to unsqueeze. Negative values are interpreted downwards from the last dimension. +} +} + +\section{Internals}{ + +Calls \code{\link[=nn_squeeze]{nn_squeeze()}} when trained. + + +Calls \code{\link[=nn_unsqueeze]{nn_unsqueeze()}} when trained. +This internally calls \code{\link[torch:torch_unsqueeze]{torch::torch_unsqueeze()}}. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_squeeze") +pipeop +# The available parameters +pipeop$param_set +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_squeeze") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} + +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchSqueeze} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchSqueeze-new}{\code{PipeOpTorchSqueeze$new()}} +\item \href{#method-PipeOpTorchSqueeze-clone}{\code{PipeOpTorchSqueeze$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchSqueeze-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchSqueeze$new(id = "nn_squeeze", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchSqueeze-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchSqueeze$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchUnsqueeze} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchUnsqueeze-new}{\code{PipeOpTorchUnsqueeze$new()}} +\item \href{#method-PipeOpTorchUnsqueeze-clone}{\code{PipeOpTorchUnsqueeze$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchUnsqueeze-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchUnsqueeze$new(id = "nn_unsqueeze", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchUnsqueeze-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchUnsqueeze$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_tanh.Rd b/man/mlr_pipeops_nn_tanh.Rd new file mode 100644 index 00000000..0d6727b0 --- /dev/null +++ b/man/mlr_pipeops_nn_tanh.Rd @@ -0,0 +1,163 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_tanh} +\alias{mlr_pipeops_nn_tanh} +\alias{PipeOpTorchTanh} +\title{Tanh Activation Function} +\description{ +Applies the element-wise function: +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +No parameters. +} + +\section{Internals}{ + Calls \code{\link[torch:nn_tanh]{torch::nn_tanh()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_tanh") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchTanh} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchTanh-new}{\code{PipeOpTorchTanh$new()}} +\item \href{#method-PipeOpTorchTanh-clone}{\code{PipeOpTorchTanh$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchTanh-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchTanh$new(id = "nn_tanh", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchTanh-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchTanh$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_tanhshrink.Rd b/man/mlr_pipeops_nn_tanhshrink.Rd new file mode 100644 index 00000000..f793e1ce --- /dev/null +++ b/man/mlr_pipeops_nn_tanhshrink.Rd @@ -0,0 +1,163 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_tanhshrink} +\alias{mlr_pipeops_nn_tanhshrink} +\alias{PipeOpTorchTanhShrink} +\title{Tanh Shrink Activation Function} +\description{ +Applies element-wise, \eqn{Tanhshrink(x) = x - Tanh(x)} +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +No parameters. +} + +\section{Internals}{ + Calls \code{\link[torch:nn_tanhshrink]{torch::nn_tanhshrink()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_tanhshrink") +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchTanhShrink} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchTanhShrink-new}{\code{PipeOpTorchTanhShrink$new()}} +\item \href{#method-PipeOpTorchTanhShrink-clone}{\code{PipeOpTorchTanhShrink$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchTanhShrink-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchTanhShrink$new(id = "nn_tanhshrink", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchTanhShrink-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchTanhShrink$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_nn_threshold.Rd b/man/mlr_pipeops_nn_threshold.Rd new file mode 100644 index 00000000..2f777169 --- /dev/null +++ b/man/mlr_pipeops_nn_threshold.Rd @@ -0,0 +1,170 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchActivation.R +\name{mlr_pipeops_nn_threshold} +\alias{mlr_pipeops_nn_threshold} +\alias{PipeOpTorchThreshold} +\title{Treshold Activation Function} +\description{ +Thresholds each element of the input Tensor. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \verb{$shapes_out()}. +} + +\section{Credit}{ + +Part of this documentation have been copied or adapted from the documentation of \CRANpkg{torch}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{threshold} :: \code{numeric(1)}\cr +The value to threshold at. +\item \code{value} :: \code{numeric(1)}\cr +The value to replace with. +\item \code{inplace} :: \code{logical(1)}\cr +Can optionally do the operation in-place. Default: ‘FALSE’. +} +} + +\section{Internals}{ + Calls \code{\link[torch:nn_threshold]{torch::nn_threshold()}} when trained. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Construct the PipeOp +pipeop = po("nn_threshold", threshold = 1, value = 2) +pipeop +# The available parameters +pipeop$param_set +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorch} -> \code{PipeOpTorchThreshold} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchThreshold-new}{\code{PipeOpTorchThreshold$new()}} +\item \href{#method-PipeOpTorchThreshold-clone}{\code{PipeOpTorchThreshold$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchThreshold-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchThreshold$new(id = "nn_threshold", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchThreshold-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchThreshold$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_preproc_torch.Rd b/man/mlr_pipeops_preproc_torch.Rd new file mode 100644 index 00000000..aa4378ee --- /dev/null +++ b/man/mlr_pipeops_preproc_torch.Rd @@ -0,0 +1,304 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTaskPreprocTorch.R +\name{mlr_pipeops_preproc_torch} +\alias{mlr_pipeops_preproc_torch} +\alias{PipeOpTaskPreprocTorch} +\title{Base Class for Lazy Tensor Preprocessing} +\description{ +This \code{PipeOp} can be used to preprocess (one or more) \code{\link{lazy_tensor}} columns contained in an \code{\link[mlr3:Task]{mlr3::Task}}. +The preprocessing function is specified as construction argument \code{fn} and additional arguments to this +function can be defined through the \code{PipeOp}'s parameter set. +The preprocessing is done per column, i.e. the number of lazy tensor output columns is equal +to the number of lazy tensor input columns. + +To create custom preprocessing \code{PipeOp}s you can use \code{\link{pipeop_preproc_torch}}. +} +\section{Inheriting}{ + +In addition to specifying the construction arguments, you can overwrite the private \code{.shapes_out()} method. +If you don't overwrite it, the output shapes are assumed to be unknown (\code{NULL}). +\itemize{ +\item \code{.shapes_out(shapes_in, param_vals, task)}\cr +(\code{list()}, \verb{list(), }Task\code{or}NULL\verb{) -> }list()\verb{\\cr This private method calculates the output shapes of the lazy tensor columns that are created from applying the preprocessing function with the provided parameter values (}param_vals\verb{). The }task\verb{is very rarely needed, but if it is it should be checked that it is not}NULL`. + +This private method only has the responsibility to calculate the output shapes for one input column, i.e. the +input \code{shapes_in} can be assumed to have exactly one shape vector for which it must calculate the output shapes +and return it as a \code{list()} of length 1. +It can also be assumed that the shape is not \code{NULL} (i.e. unknown). +Also, the first dimension can be \code{NA}, i.e. is unknown (as for the batch dimension). +} +} + +\section{Input and Output Channels}{ + +See \code{\link{PipeOpTaskPreproc}}. +} + +\section{State}{ + +In addition to state elements from \code{\link{PipeOpTaskPreprocSimple}}, the state also contains the \verb{$param_vals} that +were set during training. +} + +\section{Parameters}{ + +In addition to the parameters inherited from \code{\link{PipeOpTaskPreproc}} as well as those specified during construction +as the argument \code{param_set} there are the following parameters: +\itemize{ +\item \code{stages} :: \code{character(1)}\cr +The stages during which to apply the preprocessing. +Can be one of \code{"train"}, \code{"predict"} or \code{"both"}. +The initial value of this parameter is set to \code{"train"} when the \code{PipeOp}'s id starts with \code{"augment_"} and +to \code{"both"} otherwise. +Note that the preprocessing that is applied during \verb{$predict()} uses the parameters that were set during +\verb{$train()} and not those that are set when performing the prediction. +} +} + +\section{Internals}{ + +During \verb{$train()} / \verb{$predict()}, a \code{\link{PipeOpModule}} with one input and one output channel is created. +The pipeop applies the function \code{fn} to the input tensor while additionally +passing the parameter values (minus \code{stages} and \code{affect_columns}) to \code{fn}. +The preprocessing graph of the lazy tensor columns is shallowly cloned and the \code{PipeOpModule} is added. +This is done to avoid modifying user input and means that identical \code{PipeOpModule}s can be part of different +preprocessing graphs. This is only possible, because the created \code{PipeOpModule} is stateless. + +At a later point in the graph, preprocessing graphs will be merged if possible to avoid unnecessary computation. +This is best illustrated by example: +One lazy tensor column's preprocessing graph is \code{A -> B}. +Then, two branches are created \code{B -> C} and \code{B -> D}, creating two preprocessing graphs +\code{A -> B -> C} and \code{A -> B -> D}. When loading the data, we want to run the preprocessing only once, i.e. we don't +want to run the \code{A -> B} part twice. For this reason, \code{\link[=task_dataset]{task_dataset()}} will try to merge graphs and cache +results from graphs. However, only graphs using the same dataset can currently be merged. + +Also, the shapes created during \verb{$train()} and \verb{$predict()} might differ. +To avoid the creation of graphs where the predict shapes are incompatible with the train shapes, +the hypothetical predict shapes are already calculated during \verb{$train()} (this is why the parameters that are set +during train are also used during predict) and the \code{\link{PipeOpTorchModel}} will check the train and predict shapes for +compatibility before starting the training. + +Otherwise, this mechanism is very similar to the \code{\link{ModelDescriptor}} construct. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# Creating a simple task +d = data.table( + x1 = as_lazy_tensor(rnorm(10)), + x2 = as_lazy_tensor(rnorm(10)), + x3 = as_lazy_tensor(as.double(1:10)), + y = rnorm(10) +) + +taskin = as_task_regr(d, target = "y") + +# Creating a simple preprocessing pipeop +po_simple = po("preproc_torch", + # get rid of environment baggage + fn = mlr3misc::crate(function(x, a) x + a), + param_set = paradox::ps(a = paradox::p_int(tags = c("train", "required"))) +) + +po_simple$param_set$set_values( + a = 100, + affect_columns = selector_name(c("x1", "x2")), + stages = "both" # use during train and predict +) + +taskout_train = po_simple$train(list(taskin))[[1L]] +materialize(taskout_train$data(cols = c("x1", "x2")), rbind = TRUE) + +taskout_predict_noaug = po_simple$predict(list(taskin))[[1L]] +materialize(taskout_predict_noaug$data(cols = c("x1", "x2")), rbind = TRUE) + +po_simple$param_set$set_values( + stages = "train" +) + +# transformation is not applied +taskout_predict_aug = po_simple$predict(list(taskin))[[1L]] +materialize(taskout_predict_aug$data(cols = c("x1", "x2")), rbind = TRUE) + +# Creating a more complex preprocessing PipeOp +PipeOpPreprocTorchPoly = R6::R6Class("PipeOpPreprocTorchPoly", + inherit = PipeOpTaskPreprocTorch, + public = list( + initialize = function(id = "preproc_poly", param_vals = list()) { + param_set = paradox::ps( + n_degree = paradox::p_int(lower = 1L, tags = c("train", "required")) + ) + param_set$set_values( + n_degree = 1L + ) + fn = mlr3misc::crate(function(x, n_degree) { + torch::torch_cat( + lapply(seq_len(n_degree), function(d) torch_pow(x, d)), + dim = 2L + ) + }) + + super$initialize( + fn = fn, + id = id, + packages = character(0), + param_vals = param_vals, + param_set = param_set, + stages_init = "both" + ) + } + ), + private = list( + .shapes_out = function(shapes_in, param_vals, task) { + # shapes_in is a list of length 1 containing the shapes + checkmate::assert_true(length(shapes_in[[1L]]) == 2L) + if (shapes_in[[1L]][2L] != 1L) { + stop("Input shape must be (NA, 1)") + } + list(c(NA, param_vals$n_degree)) + } + ) +) + +po_poly = PipeOpPreprocTorchPoly$new( + param_vals = list(n_degree = 3L, affect_columns = selector_name("x3")) +) + +po_poly$shapes_out(list(c(NA, 1L)), stage = "train") + +taskout = po_poly$train(list(taskin))[[1L]] +materialize(taskout$data(cols = "x3"), rbind = TRUE) +} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{\link[mlr3pipelines:PipeOpTaskPreproc]{mlr3pipelines::PipeOpTaskPreproc}} -> \code{PipeOpTaskPreprocTorch} +} +\section{Active bindings}{ +\if{html}{\out{
}} +\describe{ +\item{\code{fn}}{The preprocessing function.} + +\item{\code{rowwise}}{Whether the preprocessing is applied rowwise.} +} +\if{html}{\out{
}} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTaskPreprocTorch-new}{\code{PipeOpTaskPreprocTorch$new()}} +\item \href{#method-PipeOpTaskPreprocTorch-shapes_out}{\code{PipeOpTaskPreprocTorch$shapes_out()}} +\item \href{#method-PipeOpTaskPreprocTorch-clone}{\code{PipeOpTaskPreprocTorch$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTaskPreprocTorch-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \code{\link[R6:R6Class]{R6}} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTaskPreprocTorch$new( + fn, + id = "preproc_torch", + param_vals = list(), + param_set = ps(), + packages = character(0), + rowwise = FALSE, + stages_init = NULL, + tags = NULL +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{fn}}{(\code{function} or \code{character(2)})\cr +The preprocessing function. Must not modify its input in-place. +If it is a \code{character(2)}, the first element should be the namespace and the second element the name.} + +\item{\code{id}}{(\code{character(1)})\cr +The id for of the new object.} + +\item{\code{param_vals}}{(named \code{list()})\cr +Parameter values to be set after construction.} + +\item{\code{param_set}}{(\code{\link{ParamSet}})\cr +In case the function \code{fn} takes additional parameter besides a \code{\link{torch_tensor}} they can be +specfied as parameters. None of the parameters can have the \code{"predict"} tag. +All tags should include \code{"train"}.} + +\item{\code{packages}}{(\code{character()})\cr +The packages the preprocessing function depends on.} + +\item{\code{rowwise}}{(\code{logical(1)})\cr +Whether the preprocessing function is applied rowwise (and then concatenated by row) or directly to the whole +tensor. In the first case there is no batch dimension.} + +\item{\code{stages_init}}{(\code{character(1)})\cr +Initial value for the \code{stages} parameter.} + +\item{\code{tags}}{(\code{character()})\cr +Tags for the pipeop.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTaskPreprocTorch-shapes_out}{}}} +\subsection{Method \code{shapes_out()}}{ +Calculates the output shapes that would result in applying the preprocessing to one or more +lazy tensor columns with the provided shape. +Names are ignored and only order matters. +It uses the parameter values that are currently set. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTaskPreprocTorch$shapes_out(shapes_in, stage = NULL, task = NULL)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{shapes_in}}{(\code{list()} of (\code{integer()} or \code{NULL}))\cr +The input input shapes of the lazy tensors. +\code{NULL} indicates that the shape is unknown. +First dimension must be \code{NA} (if it is not \code{NULL}).} + +\item{\code{stage}}{(\code{character(1)})\cr +The stage: either \code{"train"} or \code{"predict"}.} + +\item{\code{task}}{(\code{\link{Task}} or \code{NULL})\cr +The task, which is very rarely needed.} +} +\if{html}{\out{
}} +} +\subsection{Returns}{ +\code{list()} of (\code{integer()} or \code{NULL}) +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTaskPreprocTorch-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTaskPreprocTorch$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_torch.Rd b/man/mlr_pipeops_torch.Rd new file mode 100644 index 00000000..d6fe9cd1 --- /dev/null +++ b/man/mlr_pipeops_torch.Rd @@ -0,0 +1,365 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorch.R +\name{mlr_pipeops_torch} +\alias{mlr_pipeops_torch} +\alias{PipeOpTorch} +\title{Base Class for Torch Module Constructor Wrappers} +\description{ +\code{PipeOpTorch} is the base class for all \code{\link{PipeOp}}s that represent neural network layers in a \code{\link{Graph}}. +During \strong{training}, it generates a \code{\link{PipeOpModule}} that wraps an \code{\link[torch:nn_module]{nn_module}} and attaches it +to the architecture, which is also represented as a \code{\link{Graph}} consisting mostly of \code{\link{PipeOpModule}}s +an \code{\link{PipeOpNOP}}s. + +While the former \code{\link{Graph}} operates on \code{\link{ModelDescriptor}}s, the latter operates on \link[=torch_tensor]{tensors}. + +The relationship between a \code{PipeOpTorch} and a \code{\link{PipeOpModule}} is similar to the +relationshop between a \code{nn_module_generator} (like \code{\link[torch:nn_linear]{nn_linear}}) and a +\code{\link[torch:nn_module]{nn_module}} (like the output of \code{nn_linear(...)}). +A crucial difference is that the \code{PipeOpTorch} infers auxiliary parameters (like \code{in_features} for +\code{nn_linear}) automatically from the intermediate tensor shapes that are being communicated through the +\code{\link{ModelDescriptor}}. + +During \strong{prediction}, \code{PipeOpTorch} takes in a \code{\link[mlr3:Task]{Task}} in each channel and outputs the same new +\code{\link[mlr3:Task]{Task}} resulting from their \link[=PipeOpFeatureUnion]{feature union} in each channel. +If there is only one input and output channel, the task is simply piped through. +} +\section{Inheriting}{ + +When inheriting from this class, one should overload either the \code{private$.shapes_out()} and the +\code{private$.shape_dependent_params()} methods, or overload \code{private$.make_module()}. +\itemize{ +\item \code{.make_module(shapes_in, param_vals, task)}\cr +(\code{list()}, \code{list()}) -> \code{nn_module}\cr +This private method is called to generated the \code{nn_module} that is passed as argument \code{module} to +\code{\link{PipeOpModule}}. It must be overwritten, when no \code{module_generator} is provided. +If left as is, it calls the provided \code{module_generator} with the arguments obtained by +the private method \code{.shape_dependent_params()}. +\item \code{.shapes_out(shapes_in, param_vals, task)}\cr +(\code{list()}, \code{list()}, \code{Task} or \code{NULL}) -> named \code{list()}\cr +This private method gets a list of \code{numeric} vectors (\code{shapes_in}), the parameter values (\code{param_vals}), +as well as an (optional) \code{\link{Task}}. +The \code{shapes_in} can be assumed to be in the same order as the input names of the \code{PipeOp}. +The output shapes must be in the same order as the output names of the \code{PipeOp}. +In case the output shapes depends on the task (as is the case for \code{\link{PipeOpTorchHead}}), the function should return +valid output shapes (possibly containing \code{NA}s) if the \code{task} argument is provided or not. +\item \code{.shape_dependent_params(shapes_in, param_vals, task)}\cr +(\code{list()}, \code{list()}) -> named \code{list()}\cr +This private method has the same inputs as \code{.shapes_out}. +If \code{.make_module()} is not overwritten, it constructs the arguments passed to \code{module_generator}. +Usually this means that it must infer the auxiliary parameters that can be inferred from the input shapes +and add it to the user-supplied parameter values (\code{param_vals}). +} +} + +\section{Input and Output Channels}{ + +During \emph{training}, all inputs and outputs are of class \code{\link{ModelDescriptor}}. +During \emph{prediction}, all input and output channels are of class \code{\link{Task}}. +} + +\section{State}{ + +The state is the value calculated by the public method \code{shapes_out()}. +} + +\section{Parameters}{ + +The \code{\link[paradox:ParamSet]{ParamSet}} is specified by the child class inheriting from \code{\link{PipeOpTorch}}. +Usually the parameters are the arguments of the wrapped \code{\link{nn_module}} minus the auxiliary parameter that can +be automatically inferred from the shapes of the input tensors. +} + +\section{Internals}{ + +During training, the \code{PipeOpTorch} creates a \code{\link{PipeOpModule}} for the given parameter specification and the +input shapes from the incoming \href{s}{\code{ModelDescriptor}} using the private method \code{.make_module()}. +The input shapes are provided by the slot \code{pointer_shape} of the incoming \code{\link{ModelDescriptor}}s. +The channel names of this \code{\link{PipeOpModule}} are identical to the channel names of the generating \code{\link{PipeOpTorch}}. + +A \link[=model_descriptor_union]{model descriptor union} of all incoming \code{\link{ModelDescriptor}}s is then created. +Note that this modifies the \code{\link[=Graph]{graph}} of the first \code{\link{ModelDescriptor}} \strong{in place} for efficiency. +The \code{\link{PipeOpModule}} is added to the \code{\link[=Graph]{graph}} slot of this union and the the edges that connect the +sending \code{PipeOpModule}s to the input channel of this \code{PipeOpModule} are addeded to the graph. +This is possible because every incoming \code{\link{ModelDescriptor}} contains the information about the +\code{id} and the \code{channel} name of the sending \code{PipeOp} in the slot \code{pointer}. + +The new graph in the \code{\link{model_descriptor_union}} represents the current state of the neural network +architecture. It is structurally similar to the subgraph that consists of all pipeops of class \code{PipeOpTorch} and +\code{\link{PipeOpTorchIngress}} that are ancestors of this \code{PipeOpTorch}. + +For the output, a shallow copy of the \code{\link{ModelDescriptor}} is created and the \code{pointer} and +\code{pointer_shape} are updated accordingly. The shallow copy means that all \code{\link{ModelDescriptor}}s point to the same +\code{\link{Graph}} which allows the graph to be modified by-reference in different parts of the code. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +## Creating a neural network +# In torch + +task = tsk("iris") + +network_generator = torch::nn_module( + initialize = function(task, d_hidden) { + d_in = length(task$feature_names) + self$linear = torch::nn_linear(d_in, d_hidden) + self$output = if (task$task_type == "regr") { + torch::nn_linear(d_hidden, 1) + } else if (task$task_type == "classif") { + torch::nn_linear(d_hidden, length(task$class_names)) + } + }, + forward = function(x) { + x = self$linear(x) + x = torch::nnf_relu(x) + self$output(x) + } +) + +network = network_generator(task, d_hidden = 50) +x = torch::torch_tensor(as.matrix(task$data(1, task$feature_names))) +y = torch::with_no_grad(network(x)) + + +# In mlr3torch +network_generator = po("torch_ingress_num") \%>>\% + po("nn_linear", out_features = 50) \%>>\% + po("nn_head") +md = network_generator$train(task)[[1L]] +network = model_descriptor_to_module(md) +y = torch::with_no_grad(network(torch_ingress_num.input = x)) + + + +## Implementing a custom PipeOpTorch + +# defining a custom module +nn_custom = nn_module("nn_custom", + initialize = function(d_in1, d_in2, d_out1, d_out2, bias = TRUE) { + self$linear1 = nn_linear(d_in1, d_out1, bias) + self$linear2 = nn_linear(d_in2, d_out2, bias) + }, + forward = function(input1, input2) { + output1 = self$linear1(input1) + output2 = self$linear1(input2) + + list(output1 = output1, output2 = output2) + } +) + +# wrapping the module into a custom PipeOpTorch + +library(paradox) + +PipeOpTorchCustom = R6::R6Class("PipeOpTorchCustom", + inherit = PipeOpTorch, + public = list( + initialize = function(id = "nn_custom", param_vals = list()) { + param_set = ps( + d_out1 = p_int(lower = 1, tags = c("required", "train")), + d_out2 = p_int(lower = 1, tags = c("required", "train")), + bias = p_lgl(default = TRUE, tags = "train") + ) + super$initialize( + id = id, + param_vals = param_vals, + param_set = param_set, + inname = c("input1", "input2"), + outname = c("output1", "output2"), + module_generator = nn_custom + ) + } + ), + private = list( + .shape_dependent_params = function(shapes_in, param_vals, task) { + c(param_vals, + list(d_in1 = tail(shapes_in[["input1"]], 1)), d_in2 = tail(shapes_in[["input2"]], 1) + ) + }, + .shapes_out = function(shapes_in, param_vals, task) { + list( + input1 = c(head(shapes_in[["input1"]], -1), param_vals$d_out1), + input2 = c(head(shapes_in[["input2"]], -1), param_vals$d_out2) + ) + } + ) +) + +## Training + +# generate input +task = tsk("iris") +task1 = task$clone()$select(paste0("Sepal.", c("Length", "Width"))) +task2 = task$clone()$select(paste0("Petal.", c("Length", "Width"))) +graph = gunion(list(po("torch_ingress_num_1"), po("torch_ingress_num_2"))) +mds_in = graph$train(list(task1, task2), single_input = FALSE) + +mds_in[[1L]][c("graph", "task", "ingress", "pointer", "pointer_shape")] +mds_in[[2L]][c("graph", "task", "ingress", "pointer", "pointer_shape")] + +# creating the PipeOpTorch and training it +po_torch = PipeOpTorchCustom$new() +po_torch$param_set$values = list(d_out1 = 10, d_out2 = 20) +train_input = list(input1 = mds_in[[1L]], input2 = mds_in[[2L]]) +mds_out = do.call(po_torch$train, args = list(input = train_input)) +po_torch$state + +# the new model descriptors + +# the resulting graphs are identical +identical(mds_out[[1L]]$graph, mds_out[[2L]]$graph) +# not that as a side-effect, also one of the input graphs is modified in-place for efficiency +mds_in[[1L]]$graph$edges + +# The new task has both Sepal and Petal features +identical(mds_out[[1L]]$task, mds_out[[2L]]$task) +mds_out[[2L]]$task + +# The new ingress slot contains all ingressors +identical(mds_out[[1L]]$ingress, mds_out[[2L]]$ingress) +mds_out[[1L]]$ingress + +# The pointer and pointer_shape slots are different +mds_out[[1L]]$pointer +mds_out[[2L]]$pointer + +mds_out[[1L]]$pointer_shape +mds_out[[2L]]$pointer_shape + +## Prediction +predict_input = list(input1 = task1, input2 = task2) +tasks_out = do.call(po_torch$predict, args = list(input = predict_input)) +identical(tasks_out[[1L]], tasks_out[[2L]]) +} +\seealso{ +Other Graph Network: +\code{\link{ModelDescriptor}()}, +\code{\link{TorchIngressToken}()}, +\code{\link{mlr_learners_torch_model}}, +\code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{model_descriptor_to_learner}()}, +\code{\link{model_descriptor_to_module}()}, +\code{\link{model_descriptor_union}()}, +\code{\link{nn_graph}()} +} +\concept{Graph Network} +\section{Super class}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{PipeOpTorch} +} +\section{Public fields}{ +\if{html}{\out{
}} +\describe{ +\item{\code{module_generator}}{(\code{nn_module_generator} or \code{NULL})\cr +The module generator wrapped by this \code{PipeOpTorch}. If \code{NULL}, the private method +\code{private$.make_module(shapes_in, param_vals)} must be overwritte, see section 'Inheriting'. +Do not change this after construction.} +} +\if{html}{\out{
}} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorch-new}{\code{PipeOpTorch$new()}} +\item \href{#method-PipeOpTorch-shapes_out}{\code{PipeOpTorch$shapes_out()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorch-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorch$new( + id, + module_generator, + param_set = ps(), + param_vals = list(), + inname = "input", + outname = "output", + packages = "torch", + tags = NULL +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{module_generator}}{(\code{nn_module_generator})\cr +The torch module generator.} + +\item{\code{param_set}}{(\code{paradox::ParamSet})\cr +The parameter set.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} + +\item{\code{inname}}{(\code{character()})\cr +The names of the \code{\link{PipeOp}}'s input channels. These will be the input channels of the generated \code{\link{PipeOpModule}}. +Unless the wrapped \code{module_generator}'s forward method (if present) has the argument \code{...}, \code{inname} must be +identical to those argument names in order to avoid any ambiguity.\cr +If the forward method has the argument \code{...}, the order of the input channels determines how the tensors +will be passed to the wrapped \code{nn_module}.\cr +If left as \code{NULL} (default), the argument \code{module_generator} must be given and the argument names of the +\code{modue_generator}'s forward function are set as \code{inname}.} + +\item{\code{outname}}{(\code{character()}) \cr +The names of the output channels channels. These will be the ouput channels of the generated \code{\link{PipeOpModule}} +and therefore also the names of the list returned by its \verb{$train()}. +In case there is more than one output channel, the \code{nn_module} that is constructed by this +\code{\link{PipeOp}} during training must return a named \code{list()}, where the names of the list are the +names out the output channels. The default is \code{"output"}.} + +\item{\code{packages}}{(\code{character()})\cr +The R packages this object depends on.} + +\item{\code{tags}}{(\code{character()})\cr +The tags of the \code{\link{PipeOp}}. The tags \code{"torch"} is always added.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorch-shapes_out}{}}} +\subsection{Method \code{shapes_out()}}{ +Calculates the output shapes for the given input shapes, parameters and task. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorch$shapes_out(shapes_in, task = NULL)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{shapes_in}}{(\code{list()} of \code{integer()})\cr +The input input shapes, which must be in the same order as the input channel names of the \code{PipeOp}.} + +\item{\code{task}}{(\code{\link{Task}} or \code{NULL})\cr +The task, which is very rarely used (default is \code{NULL}). An exception is \code{\link{PipeOpTorchHead}}.} +} +\if{html}{\out{
}} +} +\subsection{Returns}{ +A named \code{list()} containing the output shapes. The names are the names of the output channels of +the \code{PipeOp}. +} +} +} diff --git a/man/mlr_pipeops_torch_callbacks.Rd b/man/mlr_pipeops_torch_callbacks.Rd new file mode 100644 index 00000000..60e2aa1f --- /dev/null +++ b/man/mlr_pipeops_torch_callbacks.Rd @@ -0,0 +1,128 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchCallbacks.R +\name{mlr_pipeops_torch_callbacks} +\alias{mlr_pipeops_torch_callbacks} +\alias{PipeOpTorchCallbacks} +\title{Callback Configuration} +\description{ +Configures the callbacks of a deep learning model. +} +\section{Input and Output Channels}{ + +There is one input channel \code{"input"} and one output channel \code{"output"}. +During \emph{training}, the channels are of class \code{\link{ModelDescriptor}}. +During \emph{prediction}, the channels are of class \code{\link{Task}}. +} + +\section{State}{ + +The state is the value calculated by the public method \code{shapes_out()}. +} + +\section{Parameters}{ + +The parameters are defined dynamically from the callbacks, where the id of the respective callbacks is the +respective set id. +} + +\section{Internals}{ + +During training the callbacks are cloned and added to the \code{\link{ModelDescriptor}}. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +po_cb = po("torch_callbacks", "checkpoint") +po_cb$param_set +mdin = po("torch_ingress_num")$train(list(tsk("iris"))) +mdin[[1L]]$callbacks +mdout = po_cb$train(mdin)[[1L]] +mdout$callbacks +# Can be called again +po_cb1 = po("torch_callbacks", t_clbk("progress")) +mdout1 = po_cb1$train(list(mdout))[[1L]] +mdout1$callbacks +} +\seealso{ +Other Model Configuration: +\code{\link{ModelDescriptor}()}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_optimizer}}, +\code{\link{model_descriptor_union}()} + +Other PipeOp: +\code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch_optimizer}} +} +\concept{Model Configuration} +\concept{PipeOp} +\section{Super class}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{PipeOpTorchCallbacks} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchCallbacks-new}{\code{PipeOpTorchCallbacks$new()}} +\item \href{#method-PipeOpTorchCallbacks-clone}{\code{PipeOpTorchCallbacks$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchCallbacks-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchCallbacks$new( + callbacks = list(), + id = "torch_callbacks", + param_vals = list() +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{callbacks}}{(\code{list} of \code{\link{TorchCallback}}s) \cr +The callbacks (or something convertible via \code{\link[=as_torch_callbacks]{as_torch_callbacks()}}). +Must have unique ids. +All callbacks are cloned during construction.} + +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchCallbacks-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchCallbacks$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_torch_ingress.Rd b/man/mlr_pipeops_torch_ingress.Rd new file mode 100644 index 00000000..583ec51f --- /dev/null +++ b/man/mlr_pipeops_torch_ingress.Rd @@ -0,0 +1,192 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchIngress.R +\name{mlr_pipeops_torch_ingress} +\alias{mlr_pipeops_torch_ingress} +\alias{PipeOpTorchIngress} +\title{Entrypoint to Torch Network} +\description{ +Use this as entry-point to mlr3torch-networks. +Unless you are an advanced user, you should not need to use this directly but \code{\link{PipeOpTorchIngressNumeric}}, +\code{\link{PipeOpTorchIngressCategorical}} or \code{\link{PipeOpTorchIngressLazyTensor}}. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is set to the input shape. +} + +\section{Parameters}{ + +Defined by the construction argument \code{param_set}. +} + +\section{Internals}{ + +Creates an object of class \code{\link{TorchIngressToken}} for the given task. +The purpuse of this is to store the information on how to construct the torch dataloader from the task for this +entry point of the network. +} + +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} + +Other Graph Network: +\code{\link{ModelDescriptor}()}, +\code{\link{TorchIngressToken}()}, +\code{\link{mlr_learners_torch_model}}, +\code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{model_descriptor_to_learner}()}, +\code{\link{model_descriptor_to_module}()}, +\code{\link{model_descriptor_union}()}, +\code{\link{nn_graph}()} +} +\concept{Graph Network} +\concept{PipeOps} +\section{Super class}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{PipeOpTorchIngress} +} +\section{Active bindings}{ +\if{html}{\out{
}} +\describe{ +\item{\code{feature_types}}{(\code{character(1)})\cr +The features types that can be consumed by this \code{PipeOpTorchIngress}.} +} +\if{html}{\out{
}} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchIngress-new}{\code{PipeOpTorchIngress$new()}} +\item \href{#method-PipeOpTorchIngress-clone}{\code{PipeOpTorchIngress$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchIngress-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchIngress$new( + id, + param_set = ps(), + param_vals = list(), + packages = character(0), + feature_types +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_set}}{(\code{paradox::ParamSet})\cr +The parameter set.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} + +\item{\code{packages}}{(\code{character()})\cr +The R packages this object depends on.} + +\item{\code{feature_types}}{(\code{character()})\cr +The feature types. +See \code{\link[=mlr_reflections]{mlr_reflections$task_feature_types}} for available values.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchIngress-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchIngress$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_torch_ingress_categ.Rd b/man/mlr_pipeops_torch_ingress_categ.Rd new file mode 100644 index 00000000..d0702feb --- /dev/null +++ b/man/mlr_pipeops_torch_ingress_categ.Rd @@ -0,0 +1,182 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchIngress.R +\name{mlr_pipeops_torch_ingress_categ} +\alias{mlr_pipeops_torch_ingress_categ} +\alias{PipeOpTorchIngressCategorical} +\title{Torch Entry Point for Categorical Features} +\description{ +Ingress PipeOp that represents a categorical (\code{factor()}, \code{ordered()} and \code{logical()}) entry point to a torch network. +} +\section{Parameters}{ + +\itemize{ +\item \code{select} :: \code{logical(1)}\cr +Whether \code{PipeOp} should selected the supported feature types. Otherwise it will err on receiving tasks +with unsupported feature types. +} +} + +\section{Internals}{ + +Uses \code{\link[=batchgetter_categ]{batchgetter_categ()}}. +} + +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is set to the input shape. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +graph = po("select", selector = selector_type("factor")) \%>>\% + po("torch_ingress_categ") +task = tsk("german_credit") +# The output is a model descriptor +md = graph$train(task)[[1L]] +ingress = md$ingress[[1L]] +ingress$batchgetter(task$data(1, ingress$features), "cpu") +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} + +Other Graph Network: +\code{\link{ModelDescriptor}()}, +\code{\link{TorchIngressToken}()}, +\code{\link{mlr_learners_torch_model}}, +\code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{model_descriptor_to_learner}()}, +\code{\link{model_descriptor_to_module}()}, +\code{\link{model_descriptor_union}()}, +\code{\link{nn_graph}()} +} +\concept{Graph Network} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorchIngress} -> \code{PipeOpTorchIngressCategorical} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchIngressCategorical-new}{\code{PipeOpTorchIngressCategorical$new()}} +\item \href{#method-PipeOpTorchIngressCategorical-clone}{\code{PipeOpTorchIngressCategorical$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchIngressCategorical-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchIngressCategorical$new( + id = "torch_ingress_categ", + param_vals = list() +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchIngressCategorical-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchIngressCategorical$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_torch_ingress_ltnsr.Rd b/man/mlr_pipeops_torch_ingress_ltnsr.Rd new file mode 100644 index 00000000..83106ca2 --- /dev/null +++ b/man/mlr_pipeops_torch_ingress_ltnsr.Rd @@ -0,0 +1,217 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchIngress.R +\name{mlr_pipeops_torch_ingress_ltnsr} +\alias{mlr_pipeops_torch_ingress_ltnsr} +\alias{PipeOpTorchIngressLazyTensor} +\title{Ingress for Lazy Tensor} +\description{ +Ingress for a single \code{\link{lazy_tensor}} column. +} +\section{Parameters}{ + +\itemize{ +\item \code{shape} :: \code{integer()}\cr +The shape of the tensor, where the first dimension (batch) must be \code{NA}. +When it is not specified, the lazy tensor input column needs to have a known shape. +} +} + +\section{Internals}{ + +The returned batchgetter materializes the lazy tensor column to a tensor. +} + +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is set to the input shape. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +po_ingress = po("torch_ingress_ltnsr") +task = tsk("lazy_iris") + +md = po_ingress$train(list(task))[[1L]] + +ingress = md$ingress +x_batch = ingress[[1L]]$batchgetter(data = task$data(1, "x"), device = "cpu", cache = NULL) +x_batch + +# Now we try a lazy tensor with unknown shape, i.e. the shapes between the rows can differ + +ds = dataset( + initialize = function() self$x = list(torch_randn(3, 10, 10), torch_randn(3, 8, 8)), + .getitem = function(i) list(x = self$x[[i]]), + .length = function() 2)() + +task_unknown = as_task_regr(data.table( + x = as_lazy_tensor(ds, dataset_shapes = list(x = NULL)), + y = rnorm(2) +), target = "y", id = "example2") + +# this task (as it is) can NOT be processed by PipeOpTorchIngressLazyTensor +# It therefore needs to be preprocessed +po_resize = po("trafo_resize", size = c(6, 6)) +task_unknown_resize = po_resize$train(list(task_unknown))[[1L]] + +# printing the transformed column still shows unknown shapes, +# because the preprocessing pipeop cannot infer them, +# however we know that the shape is now (3, 10, 10) for all rows +task_unknown_resize$data(1:2, "x") +po_ingress$param_set$set_values(shape = c(NA, 3, 6, 6)) + +md2 = po_ingress$train(list(task_unknown_resize))[[1L]] + +ingress2 = md2$ingress +x_batch2 = ingress2[[1L]]$batchgetter( + data = task_unknown_resize$data(1:2, "x"), + device = "cpu", + cache = NULL +) + +x_batch2 +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} + +Other Graph Network: +\code{\link{ModelDescriptor}()}, +\code{\link{TorchIngressToken}()}, +\code{\link{mlr_learners_torch_model}}, +\code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{model_descriptor_to_learner}()}, +\code{\link{model_descriptor_to_module}()}, +\code{\link{model_descriptor_union}()}, +\code{\link{nn_graph}()} +} +\concept{Graph Network} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorchIngress} -> \code{PipeOpTorchIngressLazyTensor} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchIngressLazyTensor-new}{\code{PipeOpTorchIngressLazyTensor$new()}} +\item \href{#method-PipeOpTorchIngressLazyTensor-clone}{\code{PipeOpTorchIngressLazyTensor$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchIngressLazyTensor-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchIngressLazyTensor$new( + id = "torch_ingress_ltnsr", + param_vals = list() +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchIngressLazyTensor-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchIngressLazyTensor$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_torch_ingress_num.Rd b/man/mlr_pipeops_torch_ingress_num.Rd new file mode 100644 index 00000000..2dec0671 --- /dev/null +++ b/man/mlr_pipeops_torch_ingress_num.Rd @@ -0,0 +1,170 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchIngress.R +\name{mlr_pipeops_torch_ingress_num} +\alias{mlr_pipeops_torch_ingress_num} +\alias{PipeOpTorchIngressNumeric} +\title{Torch Entry Point for Numeric Features} +\description{ +Ingress PipeOp that represents a numeric (\code{integer()} and \code{numeric()}) entry point to a torch network. +} +\section{Internals}{ + +Uses \code{\link[=batchgetter_num]{batchgetter_num()}}. +} + +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is set to the input shape. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +graph = po("select", selector = selector_type(c("numeric", "integer"))) \%>>\% + po("torch_ingress_num") +task = tsk("german_credit") +# The output is a model descriptor +md = graph$train(task)[[1L]] +ingress = md$ingress[[1L]] +ingress$batchgetter(task$data(1:5, ingress$features), "cpu") +} +\seealso{ +Other Graph Network: +\code{\link{ModelDescriptor}()}, +\code{\link{TorchIngressToken}()}, +\code{\link{mlr_learners_torch_model}}, +\code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{model_descriptor_to_learner}()}, +\code{\link{model_descriptor_to_module}()}, +\code{\link{model_descriptor_union}()}, +\code{\link{nn_graph}()} + +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{Graph Network} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorchIngress} -> \code{PipeOpTorchIngressNumeric} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchIngressNumeric-new}{\code{PipeOpTorchIngressNumeric$new()}} +\item \href{#method-PipeOpTorchIngressNumeric-clone}{\code{PipeOpTorchIngressNumeric$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchIngressNumeric-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchIngressNumeric$new(id = "torch_ingress_num", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchIngressNumeric-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchIngressNumeric$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_torch_loss.Rd b/man/mlr_pipeops_torch_loss.Rd new file mode 100644 index 00000000..16033da2 --- /dev/null +++ b/man/mlr_pipeops_torch_loss.Rd @@ -0,0 +1,169 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchLoss.R +\name{mlr_pipeops_torch_loss} +\alias{mlr_pipeops_torch_loss} +\alias{PipeOpTorchLoss} +\title{Loss Configuration} +\description{ +Configures the loss of a deep learning model. +} +\section{Input and Output Channels}{ + +One input channel called \code{"input"} and one output channel called \code{"output"}. +For an explanation see \code{\link{PipeOpTorch}}. +} + +\section{State}{ + +The state is the value calculated by the public method \code{shapes_out()}. +} + +\section{Parameters}{ + +The parameters are defined dynamically from the loss set during construction. +} + +\section{Internals}{ + +During training the loss is cloned and added to the \code{\link{ModelDescriptor}}. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +po_loss = po("torch_loss", loss = t_loss("cross_entropy")) +po_loss$param_set +mdin = po("torch_ingress_num")$train(list(tsk("iris"))) +mdin[[1L]]$loss +mdout = po_loss$train(mdin)[[1L]] +mdout$loss +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} + +Other Model Configuration: +\code{\link{ModelDescriptor}()}, +\code{\link{mlr_pipeops_torch_callbacks}}, +\code{\link{mlr_pipeops_torch_optimizer}}, +\code{\link{model_descriptor_union}()} +} +\concept{Model Configuration} +\concept{PipeOps} +\section{Super class}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{PipeOpTorchLoss} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchLoss-new}{\code{PipeOpTorchLoss$new()}} +\item \href{#method-PipeOpTorchLoss-clone}{\code{PipeOpTorchLoss$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchLoss-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchLoss$new(loss, id = "torch_loss", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{loss}}{(\code{\link{TorchLoss}} or \code{character(1)} or \code{nn_loss})\cr +The loss (or something convertible via \code{\link[=as_torch_loss]{as_torch_loss()}}).} + +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchLoss-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchLoss$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_torch_model.Rd b/man/mlr_pipeops_torch_model.Rd new file mode 100644 index 00000000..818b558d --- /dev/null +++ b/man/mlr_pipeops_torch_model.Rd @@ -0,0 +1,185 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchModel.R +\name{mlr_pipeops_torch_model} +\alias{mlr_pipeops_torch_model} +\alias{PipeOpTorchModel} +\title{PipeOp Torch Model} +\description{ +Builds a Torch Learner from a \code{\link{ModelDescriptor}} and trains it with the given parameter specification. +The task type must be specified during construction. +} +\section{Input and Output Channels}{ + +There is one input channel \code{"input"} that takes in \code{ModelDescriptor} during traing and a \code{Task} of the specified +\code{task_type} during prediction. +The output is \code{NULL} during training and a \code{Prediction} of given \code{task_type} during prediction. +} + +\section{State}{ + +A trained \code{\link{LearnerTorchModel}}. +} + +\section{Parameters}{ + +\itemize{ +\item \code{batch_size} :: (\code{integer(1)})\cr +The batch size. +\item \code{epochs} :: \code{integer(1)}\cr +The number of epochs. +\item \code{device} :: \code{character(1)}\cr +The device. One of \code{"auto"}, \code{"cpu"}, or \code{"cuda"} or other values defined in \code{mlr_reflections$torch$devices}. +The value is initialized to \code{"auto"}, which will select \code{"cuda"} if possible, then try \code{"mps"} and otherwise +fall back to \code{"cpu"}. +\item \code{measures_train} :: \code{\link{Measure}} or \code{list()} of \code{\link{Measure}}s. +Measures to be evaluated during training. +\item \code{measures_valid} :: \code{\link{Measure}} or \code{list()} of \code{\link{Measure}}s. +Measures to be evaluated during validation. +\item \code{num_threads} :: \code{integer(1)}\cr +The number of threads for intraop pararallelization (if \code{device} is \code{"cpu"}). +This value is initialized to 1. +\item \code{shuffle} :: \code{logical(1)}\cr +Whether to shuffle the instances in the dataset. This value is initialized to \code{TRUE}. +\item \code{seed} :: \code{integer(1)} or \code{"random"}\cr +The seed that is used during training and prediction. +This value is initialized to \code{"random"}, which means that a random seed will be sampled at the beginning of the +training phase. This seed (either set or randomly sampled) is available via \verb{$model$seed} after training +and used during prediction. +Note that by setting the seed during the training phase this will mean that by default (i.e. when \code{seed} is +\code{"random"}), clones of the learner will use a different seed. +} + +Additionally there are the parameters for the optimizer, the loss function and the callbacks. +They are prefixed with \code{"opt."}, \code{"loss."} and \code{"cb.."} respectively. +} + +\section{Internals}{ + +A \code{\link{LearnerTorchModel}} is created by calling \code{\link[=model_descriptor_to_learner]{model_descriptor_to_learner()}} on the +provided \code{\link{ModelDescriptor}} that is received through the input channel. +Then the parameters are set according to the parameters specified in \code{PipeOpTorchModel} and +its '$train()\verb{ method is called on the [}Task\verb{] stored in the [}ModelDescriptor`]. +} + +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model_classif}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super class}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{PipeOpTorchModel} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchModel-new}{\code{PipeOpTorchModel$new()}} +\item \href{#method-PipeOpTorchModel-clone}{\code{PipeOpTorchModel$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchModel-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchModel$new(task_type, id = "torch_model", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{task_type}}{(\code{character(1)})\cr +The task type of the model.} + +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchModel-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchModel$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_torch_model_classif.Rd b/man/mlr_pipeops_torch_model_classif.Rd new file mode 100644 index 00000000..71ad6391 --- /dev/null +++ b/man/mlr_pipeops_torch_model_classif.Rd @@ -0,0 +1,170 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchModel.R +\name{mlr_pipeops_torch_model_classif} +\alias{mlr_pipeops_torch_model_classif} +\alias{PipeOpTorchModelClassif} +\title{PipeOp Torch Classifier} +\description{ +Builds a torch classifier and trains it. +} +\section{Parameters}{ + See \code{\link{LearnerTorch}} +} + +\section{Input and Output Channels}{ + +There is one input channel \code{"input"} that takes in \code{ModelDescriptor} during traing and a \code{Task} of the specified +\code{task_type} during prediction. +The output is \code{NULL} during training and a \code{Prediction} of given \code{task_type} during prediction. +} + +\section{State}{ + +A trained \code{\link{LearnerTorchModel}}. +} + +\section{Internals}{ + +A \code{\link{LearnerTorchModel}} is created by calling \code{\link[=model_descriptor_to_learner]{model_descriptor_to_learner()}} on the +provided \code{\link{ModelDescriptor}} that is received through the input channel. +Then the parameters are set according to the parameters specified in \code{PipeOpTorchModel} and +its '$train()\verb{ method is called on the [}Task\verb{] stored in the [}ModelDescriptor`]. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# simple logistic regression + +# configure the model descriptor +md = as_graph(po("torch_ingress_num") \%>>\% + po("nn_head") \%>>\% + po("torch_loss", "cross_entropy") \%>>\% + po("torch_optimizer", "adam"))$train(tsk("iris"))[[1L]] + +print(md) + +# build the learner from the model descriptor and train it +po_model = po("torch_model_classif", batch_size = 50, epochs = 1) +po_model$train(list(md)) +po_model$state +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_regr}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorchModel} -> \code{PipeOpTorchModelClassif} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchModelClassif-new}{\code{PipeOpTorchModelClassif$new()}} +\item \href{#method-PipeOpTorchModelClassif-clone}{\code{PipeOpTorchModelClassif$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchModelClassif-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchModelClassif$new(id = "torch_model_classif", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchModelClassif-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchModelClassif$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_torch_model_regr.Rd b/man/mlr_pipeops_torch_model_regr.Rd new file mode 100644 index 00000000..818c944c --- /dev/null +++ b/man/mlr_pipeops_torch_model_regr.Rd @@ -0,0 +1,170 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchModel.R +\name{mlr_pipeops_torch_model_regr} +\alias{mlr_pipeops_torch_model_regr} +\alias{PipeOpTorchModelRegr} +\title{Torch Regression Model} +\description{ +Builds a torch regression model and trains it. +} +\section{Parameters}{ + See \code{\link{LearnerTorch}} +} + +\section{Input and Output Channels}{ + +There is one input channel \code{"input"} that takes in \code{ModelDescriptor} during traing and a \code{Task} of the specified +\code{task_type} during prediction. +The output is \code{NULL} during training and a \code{Prediction} of given \code{task_type} during prediction. +} + +\section{State}{ + +A trained \code{\link{LearnerTorchModel}}. +} + +\section{Internals}{ + +A \code{\link{LearnerTorchModel}} is created by calling \code{\link[=model_descriptor_to_learner]{model_descriptor_to_learner()}} on the +provided \code{\link{ModelDescriptor}} that is received through the input channel. +Then the parameters are set according to the parameters specified in \code{PipeOpTorchModel} and +its '$train()\verb{ method is called on the [}Task\verb{] stored in the [}ModelDescriptor`]. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +# simple linear regression + +# build the model descriptor +md = as_graph(po("torch_ingress_num") \%>>\% + po("nn_head") \%>>\% + po("torch_loss", "mse") \%>>\% + po("torch_optimizer", "adam"))$train(tsk("mtcars"))[[1L]] + +print(md) + +# build the learner from the model descriptor and train it +po_model = po("torch_model_regr", batch_size = 20, epochs = 1) +po_model$train(list(md)) +po_model$state +} +\seealso{ +Other PipeOps: +\code{\link{mlr_pipeops_nn_avg_pool1d}}, +\code{\link{mlr_pipeops_nn_avg_pool2d}}, +\code{\link{mlr_pipeops_nn_avg_pool3d}}, +\code{\link{mlr_pipeops_nn_batch_norm1d}}, +\code{\link{mlr_pipeops_nn_batch_norm2d}}, +\code{\link{mlr_pipeops_nn_batch_norm3d}}, +\code{\link{mlr_pipeops_nn_celu}}, +\code{\link{mlr_pipeops_nn_conv1d}}, +\code{\link{mlr_pipeops_nn_conv2d}}, +\code{\link{mlr_pipeops_nn_conv3d}}, +\code{\link{mlr_pipeops_nn_conv_transpose1d}}, +\code{\link{mlr_pipeops_nn_conv_transpose2d}}, +\code{\link{mlr_pipeops_nn_conv_transpose3d}}, +\code{\link{mlr_pipeops_nn_dropout}}, +\code{\link{mlr_pipeops_nn_elu}}, +\code{\link{mlr_pipeops_nn_flatten}}, +\code{\link{mlr_pipeops_nn_gelu}}, +\code{\link{mlr_pipeops_nn_glu}}, +\code{\link{mlr_pipeops_nn_hardshrink}}, +\code{\link{mlr_pipeops_nn_hardsigmoid}}, +\code{\link{mlr_pipeops_nn_hardtanh}}, +\code{\link{mlr_pipeops_nn_head}}, +\code{\link{mlr_pipeops_nn_layer_norm}}, +\code{\link{mlr_pipeops_nn_leaky_relu}}, +\code{\link{mlr_pipeops_nn_linear}}, +\code{\link{mlr_pipeops_nn_log_sigmoid}}, +\code{\link{mlr_pipeops_nn_max_pool1d}}, +\code{\link{mlr_pipeops_nn_max_pool2d}}, +\code{\link{mlr_pipeops_nn_max_pool3d}}, +\code{\link{mlr_pipeops_nn_merge}}, +\code{\link{mlr_pipeops_nn_merge_cat}}, +\code{\link{mlr_pipeops_nn_merge_prod}}, +\code{\link{mlr_pipeops_nn_merge_sum}}, +\code{\link{mlr_pipeops_nn_prelu}}, +\code{\link{mlr_pipeops_nn_relu}}, +\code{\link{mlr_pipeops_nn_relu6}}, +\code{\link{mlr_pipeops_nn_reshape}}, +\code{\link{mlr_pipeops_nn_rrelu}}, +\code{\link{mlr_pipeops_nn_selu}}, +\code{\link{mlr_pipeops_nn_sigmoid}}, +\code{\link{mlr_pipeops_nn_softmax}}, +\code{\link{mlr_pipeops_nn_softplus}}, +\code{\link{mlr_pipeops_nn_softshrink}}, +\code{\link{mlr_pipeops_nn_softsign}}, +\code{\link{mlr_pipeops_nn_squeeze}}, +\code{\link{mlr_pipeops_nn_tanh}}, +\code{\link{mlr_pipeops_nn_tanhshrink}}, +\code{\link{mlr_pipeops_nn_threshold}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_model}}, +\code{\link{mlr_pipeops_torch_model_classif}} +} +\concept{PipeOps} +\section{Super classes}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{mlr3torch::PipeOpTorchModel} -> \code{PipeOpTorchModelRegr} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchModelRegr-new}{\code{PipeOpTorchModelRegr$new()}} +\item \href{#method-PipeOpTorchModelRegr-clone}{\code{PipeOpTorchModelRegr$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchModelRegr-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchModelRegr$new(id = "torch_model_regr", param_vals = list())}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchModelRegr-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchModelRegr$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_pipeops_torch_optimizer.Rd b/man/mlr_pipeops_torch_optimizer.Rd new file mode 100644 index 00000000..9fadd513 --- /dev/null +++ b/man/mlr_pipeops_torch_optimizer.Rd @@ -0,0 +1,123 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchOptimizer.R +\name{mlr_pipeops_torch_optimizer} +\alias{mlr_pipeops_torch_optimizer} +\alias{PipeOpTorchOptimizer} +\title{Optimizer Configuration} +\description{ +Configures the optimizer of a deep learning model. +} +\section{Input and Output Channels}{ + +There is one input channel \code{"input"} and one output channel \code{"output"}. +During \emph{training}, the channels are of class \code{\link{ModelDescriptor}}. +During \emph{prediction}, the channels are of class \code{\link{Task}}. +} + +\section{State}{ + +The state is the value calculated by the public method \code{shapes_out()}. +} + +\section{Parameters}{ + +The parameters are defined dynamically from the optimizer that is set during construction. +} + +\section{Internals}{ + +During training, the optimizer is cloned and added to the \code{\link{ModelDescriptor}}. +Note that the parameter set of the stored \code{\link{TorchOptimizer}} is reference-identical to the parameter set of the +pipeop itself. +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +po_opt = po("torch_optimizer", "sgd", lr = 0.01) +po_opt$param_set +mdin = po("torch_ingress_num")$train(list(tsk("iris"))) +mdin[[1L]]$optimizer +mdout = po_opt$train(mdin) +mdout[[1L]]$optimizer +} +\seealso{ +Other PipeOp: +\code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch_callbacks}} + +Other Model Configuration: +\code{\link{ModelDescriptor}()}, +\code{\link{mlr_pipeops_torch_callbacks}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{model_descriptor_union}()} +} +\concept{Model Configuration} +\concept{PipeOp} +\section{Super class}{ +\code{\link[mlr3pipelines:PipeOp]{mlr3pipelines::PipeOp}} -> \code{PipeOpTorchOptimizer} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-PipeOpTorchOptimizer-new}{\code{PipeOpTorchOptimizer$new()}} +\item \href{#method-PipeOpTorchOptimizer-clone}{\code{PipeOpTorchOptimizer$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchOptimizer-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchOptimizer$new( + optimizer = t_opt("adam"), + id = "torch_optimizer", + param_vals = list() +)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{optimizer}}{(\code{\link{TorchOptimizer}} or \code{character(1)} or \code{torch_optimizer_generator})\cr +The optimizer (or something convertible via \code{\link[=as_torch_optimizer]{as_torch_optimizer()}}).} + +\item{\code{id}}{(\code{character(1)})\cr +Identifier of the resulting object.} + +\item{\code{param_vals}}{(\code{list()})\cr +List of hyperparameter settings, overwriting the hyperparameter settings that would +otherwise be set during construction.} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-PipeOpTorchOptimizer-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{PipeOpTorchOptimizer$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_resamplings_row_roles.Rd b/man/mlr_resamplings_row_roles.Rd new file mode 100644 index 00000000..0aa2e172 --- /dev/null +++ b/man/mlr_resamplings_row_roles.Rd @@ -0,0 +1,145 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ResamplingRowRoles.R +\name{mlr_resamplings_row_roles} +\alias{mlr_resamplings_row_roles} +\alias{ResamplingRowRoles} +\title{Resampling Using Row Roles} +\description{ +In mlr3 it is possible to manually set the row roles \code{use} and \code{test}. +This resampling sets the rows from \code{use} as the training ids and those from \code{test} as the test ids. +This can be useful for tasks like \link[=mlr_tasks_tiny_imagenet]{tiny imagenet} that come with predefined splits. +} +\examples{ +resampling = rsmp("row_roles") +resampling + +task = tsk("mtcars") +splits = partition(task) +task$row_roles$use = splits$train +task$row_roles$test = splits$test +rr = resample(task, lrn("regr.featureless"), resampling) +rr$score() +} +\section{Super class}{ +\code{\link[mlr3:Resampling]{mlr3::Resampling}} -> \code{ResamplingRowRoles} +} +\section{Active bindings}{ +\if{html}{\out{
}} +\describe{ +\item{\code{iters}}{(\code{integer(1)})\cr +The number of iterations which are always one for this resampling.} +} +\if{html}{\out{
}} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-ResamplingRowRoles-new}{\code{ResamplingRowRoles$new()}} +\item \href{#method-ResamplingRowRoles-instantiate}{\code{ResamplingRowRoles$instantiate()}} +\item \href{#method-ResamplingRowRoles-train_set}{\code{ResamplingRowRoles$train_set()}} +\item \href{#method-ResamplingRowRoles-test_set}{\code{ResamplingRowRoles$test_set()}} +\item \href{#method-ResamplingRowRoles-clone}{\code{ResamplingRowRoles$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-ResamplingRowRoles-new}{}}} +\subsection{Method \code{new()}}{ +Creates a new instance of this \link[R6:R6Class]{R6} class. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{ResamplingRowRoles$new()}\if{html}{\out{
}} +} + +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-ResamplingRowRoles-instantiate}{}}} +\subsection{Method \code{instantiate()}}{ +Materializes fixed training and test splits for a given task and stores them in \verb{$instance}. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{ResamplingRowRoles$instantiate(task)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{task}}{(\link{Task})\cr +Task used for instantiation.} +} +\if{html}{\out{
}} +} +\subsection{Returns}{ +Returns the object itself, but modified \strong{by reference}. +You need to explicitly \verb{$clone()} the object beforehand if you want to keeps +the object in its previous state. +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-ResamplingRowRoles-train_set}{}}} +\subsection{Method \code{train_set()}}{ +Returns the row ids of the i-th train set. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{ResamplingRowRoles$train_set(i)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{i}}{(\code{integer(1)})\cr +Iteration.} +} +\if{html}{\out{
}} +} +\subsection{Returns}{ +(\code{integer()}) of row ids. +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-ResamplingRowRoles-test_set}{}}} +\subsection{Method \code{test_set()}}{ +Returns the row ids of the i-th test set. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{ResamplingRowRoles$test_set(i)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{i}}{(\code{integer(1)})\cr +Iteration.} +} +\if{html}{\out{
}} +} +\subsection{Returns}{ +(\code{integer()}) of row ids. +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-ResamplingRowRoles-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{ResamplingRowRoles$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/mlr_tasks_lazy_iris.Rd b/man/mlr_tasks_lazy_iris.Rd new file mode 100644 index 00000000..f2d1089d --- /dev/null +++ b/man/mlr_tasks_lazy_iris.Rd @@ -0,0 +1,48 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TaskClassif_lazy_iris.R +\name{mlr_tasks_lazy_iris} +\alias{mlr_tasks_lazy_iris} +\title{Iris Classification Task} +\format{ +\link[R6:R6Class]{R6::R6Class} inheriting from \link[mlr3:TaskClassif]{mlr3::TaskClassif}. +} +\source{ +\url{https://en.wikipedia.org/wiki/Iris_flower_data_set} +} +\description{ +A classification task for the popular \link[datasets:iris]{datasets::iris} data set. +Just like the iris task, but the features are represented as one lazy tensor column. +} +\section{Construction}{ + + +\if{html}{\out{
}}\preformatted{tsk("lazy_iris") +}\if{html}{\out{
}} +} + +\section{Meta Information}{ + +\itemize{ +\item Task type: \dQuote{classif} +\item Properties: \dQuote{multiclass} +\item Has Missings: no +\item Target: \dQuote{Species} +\item Features: \dQuote{x} +\item Backend Dimension: 150x3 +\item Default Roles (use / test / holdout): 150, 0, 0 +} +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +task = tsk("lazy_iris") +df = task$data() +materialize(df$x[1:6], rbind = TRUE) +} +\references{ +Anderson E (1936). +\dQuote{The Species Problem in Iris.} +\emph{Annals of the Missouri Botanical Garden}, \bold{23}(3), 457. +\doi{10.2307/2394164}. +} diff --git a/man/mlr_tasks_mnist.Rd b/man/mlr_tasks_mnist.Rd new file mode 100644 index 00000000..6af1a5d8 --- /dev/null +++ b/man/mlr_tasks_mnist.Rd @@ -0,0 +1,54 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TaskClassif_mnist.R +\name{mlr_tasks_mnist} +\alias{mlr_tasks_mnist} +\title{MNIST Image classification} +\source{ +\url{https://torchvision.mlverse.org/reference/mnist_dataset.html} +} +\description{ +Classic MNIST image classification. + +The underlying \code{\link{DataBackend}} contains columns \code{"label"}, \code{"image"}, \code{"row_id"}, \code{"split"}, where the last column +indicates whether the row belongs to the train or test set. + +The first 60000 rows belong to the training set, the last 10000 rows to the test set. +} +\section{Download}{ + +The \link[=Task]{task}'s backend is a \code{\link{DataBackendLazy}} which will download the data once it is requested. +Other meta-data is already available before that. +You can cache these datasets by setting the \code{mlr3torch.cache} option to \code{TRUE} or to a specific path to be used +as the cache directory. +} + +\section{Construction}{ + + +\if{html}{\out{
}}\preformatted{tsk("mnist") +}\if{html}{\out{
}} +} + +\section{Meta Information}{ + +\itemize{ +\item Task type: \dQuote{classif} +\item Properties: \dQuote{multiclass} +\item Has Missings: no +\item Target: \dQuote{label} +\item Features: \dQuote{image} +\item Backend Dimension: 70000x3 +\item Default Roles (use / test / holdout): 60000, 10000, 0 +} +} + +\examples{ +task = tsk("mnist") +task +} +\references{ +Lecun, Y., Bottou, L., Bengio, Y., Haffner, P. (1998). +\dQuote{Gradient-based learning applied to document recognition.} +\emph{Proceedings of the IEEE}, \bold{86}(11), 2278-2324. +\doi{10.1109/5.726791}. +} diff --git a/man/mlr_tasks_tiny_imagenet.Rd b/man/mlr_tasks_tiny_imagenet.Rd new file mode 100644 index 00000000..12730832 --- /dev/null +++ b/man/mlr_tasks_tiny_imagenet.Rd @@ -0,0 +1,46 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TaskClassif_tiny_imagenet.R +\name{mlr_tasks_tiny_imagenet} +\alias{mlr_tasks_tiny_imagenet} +\title{Tiny ImageNet Classification Task} +\description{ +Subset of the famous ImageNet dataset. +The data is obtained from \code{\link[torchvision:tiny_imagenet_dataset]{torchvision::tiny_imagenet_dataset()}}. +It contains the train, validation and test data. +The row role \code{use} is set to the training data, the row role \code{test} to the valdiation data and the row role +\code{holdout} is set to the test data. +There are no labels available for the test data. + +The underlying \code{\link{DataBackend}} contains columns \code{"class"}, \code{"image"}, \code{"row_id"}, \code{"split"}, where the last column +indicates whether the row belongs to the train, validation or test set. +} +\section{Construction}{ + + +\if{html}{\out{
}}\preformatted{tsk("tiny_imagenet") +}\if{html}{\out{
}} +} + +\section{Meta Information}{ + +\itemize{ +\item Task type: \dQuote{classif} +\item Properties: \dQuote{multiclass} +\item Has Missings: no +\item Target: \dQuote{class} +\item Features: \dQuote{image} +\item Backend Dimension: 120000x3 +\item Default Roles (use / test / holdout): 100000, 10000, 10000 +} +} + +\examples{ +task = tsk("tiny_imagenet") +task +} +\references{ +Deng, Jia, Dong, Wei, Socher, Richard, Li, Li-Jia, Li, Kai, Fei-Fei, Li (2009). +\dQuote{Imagenet: A large-scale hierarchical image database.} +In \emph{2009 IEEE conference on computer vision and pattern recognition}, 248--255. +IEEE. +} diff --git a/man/model_descriptor_to_learner.Rd b/man/model_descriptor_to_learner.Rd new file mode 100644 index 00000000..ca28a14f --- /dev/null +++ b/man/model_descriptor_to_learner.Rd @@ -0,0 +1,36 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/nn_graph.R +\name{model_descriptor_to_learner} +\alias{model_descriptor_to_learner} +\title{Create a Torch Learner from a ModelDescriptor} +\usage{ +model_descriptor_to_learner(model_descriptor) +} +\arguments{ +\item{model_descriptor}{(\code{\link{ModelDescriptor}})\cr +The model descriptor.} +} +\value{ +\code{\link{Learner}} +} +\description{ +First a \code{\link{nn_graph}} is created using \code{\link{model_descriptor_to_module}} and then a learner is created from this +module and the remaining information from the model descriptor, which must include the optimizer and loss function +and optionally callbacks. +} +\seealso{ +Other Graph Network: +\code{\link{ModelDescriptor}()}, +\code{\link{TorchIngressToken}()}, +\code{\link{mlr_learners_torch_model}}, +\code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{model_descriptor_to_module}()}, +\code{\link{model_descriptor_union}()}, +\code{\link{nn_graph}()} +} +\concept{Graph Network} diff --git a/man/model_descriptor_to_module.Rd b/man/model_descriptor_to_module.Rd new file mode 100644 index 00000000..7eb09a67 --- /dev/null +++ b/man/model_descriptor_to_module.Rd @@ -0,0 +1,47 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/nn_graph.R +\name{model_descriptor_to_module} +\alias{model_descriptor_to_module} +\title{Create a nn_graph from ModelDescriptor} +\usage{ +model_descriptor_to_module( + model_descriptor, + output_pointers = NULL, + list_output = FALSE +) +} +\arguments{ +\item{model_descriptor}{(\code{\link{ModelDescriptor}})\cr +Model Descriptor. \code{pointer} is ignored, instead \code{output_pointer} values are used. \verb{$graph} member is +modified by-reference.} + +\item{output_pointers}{(\code{list} of \code{character})\cr +Collection of \code{pointer}s that indicate what part of the \code{model_descriptor$graph} is being used for output. +Entries have the format of \code{ModelDescriptor$pointer}.} + +\item{list_output}{(\code{logical(1)})\cr +Whether output should be a list of tensors. If \code{FALSE}, then \code{length(output_pointers)} must be 1.} +} +\value{ +\code{\link{nn_graph}} +} +\description{ +Creates the \code{\link{nn_graph}} from a \code{\link{ModelDescriptor}}. Mostly for internal use, since the \code{\link{ModelDescriptor}} is in +most circumstances harder to use than just creating \code{\link{nn_graph}} directly. +} +\seealso{ +Other Graph Network: +\code{\link{ModelDescriptor}()}, +\code{\link{TorchIngressToken}()}, +\code{\link{mlr_learners_torch_model}}, +\code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{model_descriptor_to_learner}()}, +\code{\link{model_descriptor_union}()}, +\code{\link{nn_graph}()} +} +\concept{Graph Network} diff --git a/man/model_descriptor_union.Rd b/man/model_descriptor_union.Rd new file mode 100644 index 00000000..1eee931e --- /dev/null +++ b/man/model_descriptor_union.Rd @@ -0,0 +1,60 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ModelDescriptor.R +\name{model_descriptor_union} +\alias{model_descriptor_union} +\title{Union of ModelDescriptors} +\usage{ +model_descriptor_union(md1, md2) +} +\arguments{ +\item{md1}{(\code{ModelDescriptor}) +The first \code{\link{ModelDescriptor}}.} + +\item{md2}{(\code{ModelDescriptor}) +The second \code{\link{ModelDescriptor}}.} +} +\value{ +\code{\link{ModelDescriptor}} +} +\description{ +This is a mostly internal function that is used in \code{\link{PipeOpTorch}}s with multiple input channels. + +It creates the union of multiple \code{\link{ModelDescriptor}}s: +\itemize{ +\item \code{graph}s are combinded (if they are not identical to begin with). The first entry's \code{graph} is modified by +reference. +\item \code{PipeOp}s with the same ID must be identical. No new input edges may be added to \code{PipeOp}s. +\item Drops \code{pointer} / \code{pointer_shape} entries. +\item The new task is the \link[=PipeOpFeatureUnion]{feature union} of the two incoming tasks. +\item The \code{optimizer} and \code{loss} of both \code{\link{ModelDescriptor}}s must be identical. +\item Ingress tokens and callbacks are merged, where objects with the same \code{"id"} must be identical. +} +} +\details{ +The requirement that no new input edgedes may be added to \code{PipeOp}s is not theoretically necessary, but since +we assume that ModelDescriptor is being built from beginning to end (i.e. \code{PipeOp}s never get new ancestors) we +can make this assumption and simplify things. Otherwise we'd need to treat "..."-inputs special.) +} +\seealso{ +Other Graph Network: +\code{\link{ModelDescriptor}()}, +\code{\link{TorchIngressToken}()}, +\code{\link{mlr_learners_torch_model}}, +\code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{model_descriptor_to_learner}()}, +\code{\link{model_descriptor_to_module}()}, +\code{\link{nn_graph}()} + +Other Model Configuration: +\code{\link{ModelDescriptor}()}, +\code{\link{mlr_pipeops_torch_callbacks}}, +\code{\link{mlr_pipeops_torch_loss}}, +\code{\link{mlr_pipeops_torch_optimizer}} +} +\concept{Graph Network} +\concept{Model Configuration} diff --git a/man/nn_graph.Rd b/man/nn_graph.Rd new file mode 100644 index 00000000..bb5039d7 --- /dev/null +++ b/man/nn_graph.Rd @@ -0,0 +1,59 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/nn_graph.R +\name{nn_graph} +\alias{nn_graph} +\title{Graph Network} +\usage{ +nn_graph(graph, shapes_in, output_map = graph$output$name, list_output = FALSE) +} +\arguments{ +\item{graph}{(\code{\link[mlr3pipelines:Graph]{Graph}})\cr +The \code{\link[mlr3pipelines:Graph]{Graph}} to wrap. Is \strong{not} cloned.} + +\item{shapes_in}{(named \code{integer})\cr +Shape info of tensors that go into \code{graph}. Names must be \code{graph$input$name}, possibly in different order.} + +\item{output_map}{(\code{character})\cr +Which of \code{graph}'s outputs to use. Must be a subset of \code{graph$output$name}.} + +\item{list_output}{(\code{logical(1)})\cr +Whether output should be a list of tensors. If \code{FALSE} (default), then \code{length(output_map)} must be 1.} +} +\value{ +\code{\link{nn_graph}} +} +\description{ +Represents a neural network using a \code{\link{Graph}} that usually costains mostly \code{\link{PipeOpModule}}s. +} +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +graph = mlr3pipelines::Graph$new() +graph$add_pipeop(po("module_1", module = nn_linear(10, 20)), clone = FALSE) +graph$add_pipeop(po("module_2", module = nn_relu()), clone = FALSE) +graph$add_pipeop(po("module_3", module = nn_linear(20, 1)), clone = FALSE) +graph$add_edge("module_1", "module_2") +graph$add_edge("module_2", "module_3") + +network = nn_graph(graph, shapes_in = list(module_1.input = c(NA, 10))) + +x = torch_randn(16, 10) + +network(module_1.input = x) +} +\seealso{ +Other Graph Network: +\code{\link{ModelDescriptor}()}, +\code{\link{TorchIngressToken}()}, +\code{\link{mlr_learners_torch_model}}, +\code{\link{mlr_pipeops_module}}, +\code{\link{mlr_pipeops_torch}}, +\code{\link{mlr_pipeops_torch_ingress}}, +\code{\link{mlr_pipeops_torch_ingress_categ}}, +\code{\link{mlr_pipeops_torch_ingress_ltnsr}}, +\code{\link{mlr_pipeops_torch_ingress_num}}, +\code{\link{model_descriptor_to_learner}()}, +\code{\link{model_descriptor_to_module}()}, +\code{\link{model_descriptor_union}()} +} +\concept{Graph Network} diff --git a/man/nn_merge_cat.Rd b/man/nn_merge_cat.Rd new file mode 100644 index 00000000..99a4b1c8 --- /dev/null +++ b/man/nn_merge_cat.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchMerge.R +\name{nn_merge_cat} +\alias{nn_merge_cat} +\title{Concatenates multiple tensors} +\usage{ +nn_merge_cat(dim = -1) +} +\arguments{ +\item{dim}{(\code{integer(1)})\cr +The dimension for the concatenation.} +} +\description{ +Concatenates multiple tensors on a given dimension. +No broadcasting rules are applied here, you must reshape the tensors before to have the same shape. +} diff --git a/man/nn_merge_prod.Rd b/man/nn_merge_prod.Rd new file mode 100644 index 00000000..2fb9ccf3 --- /dev/null +++ b/man/nn_merge_prod.Rd @@ -0,0 +1,11 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchMerge.R +\name{nn_merge_prod} +\alias{nn_merge_prod} +\title{Product of multiple tensors} +\usage{ +nn_merge_prod() +} +\description{ +Calculates the product of all input tensors. +} diff --git a/man/nn_merge_sum.Rd b/man/nn_merge_sum.Rd new file mode 100644 index 00000000..3e7fedf2 --- /dev/null +++ b/man/nn_merge_sum.Rd @@ -0,0 +1,11 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchMerge.R +\name{nn_merge_sum} +\alias{nn_merge_sum} +\title{Sum of multiple tensors} +\usage{ +nn_merge_sum() +} +\description{ +Calculates the sum of all input tensors. +} diff --git a/man/nn_reshape.Rd b/man/nn_reshape.Rd new file mode 100644 index 00000000..a18243d8 --- /dev/null +++ b/man/nn_reshape.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchReshape.R +\name{nn_reshape} +\alias{nn_reshape} +\title{Reshape} +\usage{ +nn_reshape(shape) +} +\arguments{ +\item{shape}{(\code{integer()})\cr +The desired output shape.} +} +\description{ +Reshape a tensor to the given shape. +} diff --git a/man/nn_squeeze.Rd b/man/nn_squeeze.Rd new file mode 100644 index 00000000..357f0f9f --- /dev/null +++ b/man/nn_squeeze.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchReshape.R +\name{nn_squeeze} +\alias{nn_squeeze} +\title{Squeeze} +\usage{ +nn_squeeze(dim) +} +\arguments{ +\item{dim}{(\code{integer()})\cr +The dimension to squeeze.} +} +\description{ +Squeezes a tensor by calling \code{\link[torch:torch_squeeze]{torch::torch_squeeze()}} with the given dimension \code{dim}. +} diff --git a/man/nn_unsqueeze.Rd b/man/nn_unsqueeze.Rd new file mode 100644 index 00000000..0fc27e93 --- /dev/null +++ b/man/nn_unsqueeze.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTorchReshape.R +\name{nn_unsqueeze} +\alias{nn_unsqueeze} +\title{Unsqueeze} +\usage{ +nn_unsqueeze(dim) +} +\arguments{ +\item{dim}{(\code{integer(1)})\cr +The dimension to unsqueeze.} +} +\description{ +Unsqueezes a tensor by calling \code{\link[torch:torch_unsqueeze]{torch::torch_unsqueeze()}} with the given dimension \code{dim}. +} diff --git a/man/pipeop_preproc_torch.Rd b/man/pipeop_preproc_torch.Rd new file mode 100644 index 00000000..3eb70276 --- /dev/null +++ b/man/pipeop_preproc_torch.Rd @@ -0,0 +1,72 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PipeOpTaskPreprocTorch.R +\name{pipeop_preproc_torch} +\alias{pipeop_preproc_torch} +\title{Create Torch Preprocessing PipeOps} +\usage{ +pipeop_preproc_torch( + id, + fn, + shapes_out = NULL, + param_set = NULL, + packages = character(0), + rowwise = FALSE, + parent_env = parent.frame(), + stages_init = NULL, + tags = NULL +) +} +\arguments{ +\item{id}{(\code{character(1)})\cr +The id for of the new object.} + +\item{fn}{(\code{function})\cr +The preprocessing function.} + +\item{shapes_out}{(\code{function} or \code{NULL} or \code{"infer"})\cr +The private \code{.shapes_out(shapes_in, param_vals, task)} method of \code{\link{PipeOpTaskPreprocTorch}} +(see section Inheriting). +Special values are \code{NULL} and \code{infer}: +If \code{NULL}, the output shapes are unknown. +If "infer", the output shape function is inferred and calculates the output shapes as follows: +For an input shape of (NA, ...) a meta-tensor of shape (1, ...) is created and the preprocessing function is +applied. Afterwards the batch dimension (1) is replaced with NA and the shape is returned. +If the first dimension is not \code{NA}, the output shape of applying the preprocessing function is returned. +Method \code{"infer"} should be correct in most cases, but might fail in some edge cases.} + +\item{param_set}{(\code{\link{ParamSet}} or \code{NULL})\cr +The parameter set. +If this is left as \code{NULL} (default) the parameter set is inferred in the following way: +All parameters but the first and \code{...} of \code{fn} are set as untyped parameters with tags 'train' and those that +have no default value are tagged as 'required' as well. +Default values are not annotated.} + +\item{packages}{(\code{character()})\cr +The R packages this object depends on.} + +\item{rowwise}{(\code{logical(1)})\cr +Whether the preprocessing is applied row-wise.} + +\item{parent_env}{(\code{environment})\cr +The parent environment for the R6 class.} + +\item{stages_init}{(\code{character(1)})\cr +Initial value for the \code{stages} parameter. +If \code{NULL} (default), will be set to \code{"both"} in case the \code{id} starts with \code{"trafo"} and to \code{"train"} +if it starts with \code{"augment"}. Otherwise it must specified.} + +\item{tags}{(\code{character()})\cr +Tags for the pipeop} +} +\value{ +An \code{\link[R6:R6Class]{R6Class}} instance inheriting from \code{\link{PipeOpTaskPreprocTorch}} +} +\description{ +Function to create objects of class \code{\link{PipeOpTaskPreprocTorch}} in a more convenient way. +Start by reading the documentation of \code{\link{PipeOpTaskPreprocTorch}}. +} +\examples{ +PipeOpPreprocExample = pipeop_preproc_torch("preproc_example", function(x, a) x + a, ) +po_example = PipeOpPreprocExample$new() +po_example$param_set +} diff --git a/man/reset_layer.Rd b/man/reset_layer.Rd new file mode 100644 index 00000000..f09d059b --- /dev/null +++ b/man/reset_layer.Rd @@ -0,0 +1,54 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/reset_last_layer.R +\name{reset_last_layer} +\alias{reset_last_layer} +\alias{reset_last_layer.AlexNet} +\alias{reset_last_layer.resnet} +\title{Reset a classification models last layer} +\usage{ +reset_last_layer(model, num_classes, bias, freeze) + +\method{reset_last_layer}{AlexNet}(model, num_classes, bias = TRUE, freeze = FALSE) + +\method{reset_last_layer}{resnet}(model, num_classes, bias = TRUE, freeze = FALSE) +} +\arguments{ +\item{model}{A pretrained model, e.g. +\code{torchvision::model_alexnet(pretrained = TRUE)}} + +\item{num_classes}{Number of desired output classes.} + +\item{bias}{\verb{[TRUE]} Whether to use bias in the last layer.} + +\item{freeze}{(\code{logical(1)})\cr +Whether to freee all layers expect for the output layer.} +} +\value{ +Same as input \code{model} with modified last layer. +} +\description{ +Used for pretrained models where the last layer is set to e.g. 1000 classes +but training is intended to be applied to e.g. 10 classes. +} +\note{ +As of this, this also freezes the parameters of all but the last layer. +} +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +\dontrun{ +# AlexNet +if (mlr3misc::requires_namespaces("torchvision") && torch::torch_is_installed(h)) { + model = torchvision::model_alexnet(pretrained = TRUE) + model$classifier[[7]]$out_feature + model = reset_last_layer(model, 10) + model$classifier[[7]]$out_feature + + # ResNet + model = torchvision::model_resnet18(pretrained = TRUE) + model$fc$out_feature + model = reset_last_layer(model, 10) + model$fc$out_feature +} +} +} diff --git a/man/t_clbk.Rd b/man/t_clbk.Rd new file mode 100644 index 00000000..8c2779ed --- /dev/null +++ b/man/t_clbk.Rd @@ -0,0 +1,61 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TorchCallback.R +\name{t_clbk} +\alias{t_clbk} +\alias{t_clbks} +\title{Sugar Function for Torch Callback} +\usage{ +t_clbk(.key, ...) + +t_clbks(.keys) +} +\arguments{ +\item{.key}{(\code{character(1)})\cr +The key of the torch callback.} + +\item{...}{(any)\cr +See description of \code{\link[=dictionary_sugar_get]{dictionary_sugar_get()}}.} + +\item{.keys}{(\code{character()})\cr +The keys of the callbacks.} +} +\value{ +\code{\link{TorchCallback}} + +\code{list()} of \code{\link{TorchCallback}}s +} +\description{ +Retrieves one or more \href{s}{\code{TorchCallback}} from \code{\link{mlr3torch_callbacks}}. +Works like \code{\link[mlr3:mlr_sugar]{mlr3::lrn()}} and \code{\link[mlr3:mlr_sugar]{mlr3::lrns()}}. +} +\examples{ +t_clbk("progress") +} +\seealso{ +Other Callback: +\code{\link{TorchCallback}}, +\code{\link{as_torch_callback}()}, +\code{\link{as_torch_callbacks}()}, +\code{\link{callback_set}()}, +\code{\link{mlr3torch_callbacks}}, +\code{\link{mlr_callback_set}}, +\code{\link{mlr_callback_set.checkpoint}}, +\code{\link{mlr_callback_set.progress}}, +\code{\link{mlr_context_torch}}, +\code{\link{torch_callback}()} + +Other Torch Descriptor: +\code{\link{TorchCallback}}, +\code{\link{TorchDescriptor}}, +\code{\link{TorchLoss}}, +\code{\link{TorchOptimizer}}, +\code{\link{as_torch_callbacks}()}, +\code{\link{as_torch_loss}()}, +\code{\link{as_torch_optimizer}()}, +\code{\link{mlr3torch_losses}}, +\code{\link{mlr3torch_optimizers}}, +\code{\link{t_loss}()}, +\code{\link{t_opt}()} +} +\concept{Callback} +\concept{Torch Descriptor} diff --git a/man/t_loss.Rd b/man/t_loss.Rd new file mode 100644 index 00000000..909eb1d2 --- /dev/null +++ b/man/t_loss.Rd @@ -0,0 +1,51 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TorchLoss.R +\name{t_loss} +\alias{t_loss} +\alias{t_losses} +\title{Loss Function Quick Access} +\usage{ +t_loss(.key, ...) + +t_losses(.keys, ...) +} +\arguments{ +\item{.key}{(\code{character(1)})\cr +Key of the object to retrieve.} + +\item{...}{(any)\cr +See description of \code{\link{dictionary_sugar_get}}.} + +\item{.keys}{(\code{character()})\cr +The keys of the losses.} +} +\value{ +A \code{\link{TorchLoss}} +} +\description{ +Retrieve one or more \href{es}{\code{TorchLoss}} from \code{\link{mlr3torch_losses}}. +Works like \code{\link[mlr3:mlr_sugar]{mlr3::lrn()}} and \code{\link[mlr3:mlr_sugar]{mlr3::lrns()}}. +} +\examples{ +t_loss("mse", reduction = "mean") +# get the dictionary +t_loss() +t_losses(c("mse", "l1")) +# get the dictionary +t_losses() +} +\seealso{ +Other Torch Descriptor: +\code{\link{TorchCallback}}, +\code{\link{TorchDescriptor}}, +\code{\link{TorchLoss}}, +\code{\link{TorchOptimizer}}, +\code{\link{as_torch_callbacks}()}, +\code{\link{as_torch_loss}()}, +\code{\link{as_torch_optimizer}()}, +\code{\link{mlr3torch_losses}}, +\code{\link{mlr3torch_optimizers}}, +\code{\link{t_clbk}()}, +\code{\link{t_opt}()} +} +\concept{Torch Descriptor} diff --git a/man/t_opt.Rd b/man/t_opt.Rd new file mode 100644 index 00000000..364d5b7f --- /dev/null +++ b/man/t_opt.Rd @@ -0,0 +1,57 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TorchOptimizer.R +\name{t_opt} +\alias{t_opt} +\alias{t_opts} +\title{Optimizers Quick Access} +\usage{ +t_opt(.key, ...) + +t_opts(.keys, ...) +} +\arguments{ +\item{.key}{(\code{character(1)})\cr +Key of the object to retrieve.} + +\item{...}{(any)\cr +See description of \code{\link{dictionary_sugar_get}}.} + +\item{.keys}{(\code{character()})\cr +The keys of the optimizers.} +} +\value{ +A \code{\link{TorchOptimizer}} +} +\description{ +Retrieves one or more \href{s}{\code{TorchOptimizer}} from \code{\link{mlr3torch_optimizers}}. +Works like \code{\link[mlr3:mlr_sugar]{mlr3::lrn()}} and \code{\link[mlr3:mlr_sugar]{mlr3::lrns()}}. +} +\examples{ +t_opt("adam", lr = 0.1) +# get the dictionary +t_opt() +t_opts(c("adam", "sgd")) +# get the dictionary +t_opts() +} +\seealso{ +Other Torch Descriptor: +\code{\link{TorchCallback}}, +\code{\link{TorchDescriptor}}, +\code{\link{TorchLoss}}, +\code{\link{TorchOptimizer}}, +\code{\link{as_torch_callbacks}()}, +\code{\link{as_torch_loss}()}, +\code{\link{as_torch_optimizer}()}, +\code{\link{mlr3torch_losses}}, +\code{\link{mlr3torch_optimizers}}, +\code{\link{t_clbk}()}, +\code{\link{t_loss}()} + +Other Dictionary: +\code{\link{mlr3torch_callbacks}}, +\code{\link{mlr3torch_losses}}, +\code{\link{mlr3torch_optimizers}} +} +\concept{Dictionary} +\concept{Torch Descriptor} diff --git a/man/task_dataset.Rd b/man/task_dataset.Rd new file mode 100644 index 00000000..30bd6d6a --- /dev/null +++ b/man/task_dataset.Rd @@ -0,0 +1,59 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/task_dataset.R +\name{task_dataset} +\alias{task_dataset} +\title{Create a Dataset from a Task} +\usage{ +task_dataset(task, feature_ingress_tokens, target_batchgetter = NULL, device) +} +\arguments{ +\item{task}{(\code{\link{Task}})\cr +The task for which to build the \link[torch:dataset]{dataset}.} + +\item{feature_ingress_tokens}{(named \code{list()} of \code{\link{TorchIngressToken}})\cr +Each ingress token defines one item in the \verb{$x} value of a batch with corresponding names.} + +\item{target_batchgetter}{(\verb{function(data, device)})\cr +A function taking in arguments \code{data}, which is a \code{data.table} containing only the target variable, and \code{device}. +It must return the target as a torch \link[torch:torch_tensor]{tensor} on the selected device.} + +\item{device}{(\code{character()})\cr +The device, e.g. \code{"cuda"} or \code{"cpu"}.} +} +\value{ +\code{\link[torch:dataset]{torch::dataset}} +} +\description{ +Creates a torch \link[torch:dataset]{dataset} from an mlr3 \code{\link{Task}}. +The resulting dataset's \verb{$.get_batch()} method returns a list with elements \code{x}, \code{y} and \code{index}: +\itemize{ +\item \code{x} is a list with tensors, whose content is defined by the parameter \code{feature_ingress_tokens}. +\item \code{y} is the target variable and its content is defined by the parameter \code{target_batchgetter}. +\item \code{.index} is the index of the batch in the task's data. +} + +The data is returned on the device specified by the parameter \code{device}. +} +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +task = tsk("iris") +sepal_ingress = TorchIngressToken( + features = c("Sepal.Length", "Sepal.Width"), + batchgetter = batchgetter_num, + shape = c(NA, 2) +) +petal_ingress = TorchIngressToken( + features = c("Petal.Length", "Petal.Width"), + batchgetter = batchgetter_num, + shape = c(NA, 2) +) +ingress_tokens = list(sepal = sepal_ingress, petal = petal_ingress) + +target_batchgetter = function(data, device) { + torch_tensor(data = data[[1L]], dtype = torch_float32(), device)$unsqueeze(2) +} +dataset = task_dataset(task, ingress_tokens, target_batchgetter, "cpu") +batch = dataset$.getbatch(1:10) +batch +} diff --git a/man/torch_callback.Rd b/man/torch_callback.Rd new file mode 100644 index 00000000..62b71f5a --- /dev/null +++ b/man/torch_callback.Rd @@ -0,0 +1,143 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/TorchCallback.R +\name{torch_callback} +\alias{torch_callback} +\title{Create a Callback Desctiptor} +\usage{ +torch_callback( + id, + classname = paste0("CallbackSet", capitalize(id)), + param_set = NULL, + packages = NULL, + label = capitalize(id), + man = NULL, + on_begin = NULL, + on_end = NULL, + on_epoch_begin = NULL, + on_before_valid = NULL, + on_epoch_end = NULL, + on_batch_begin = NULL, + on_batch_end = NULL, + on_after_backward = NULL, + on_batch_valid_begin = NULL, + on_batch_valid_end = NULL, + initialize = NULL, + public = NULL, + private = NULL, + active = NULL, + parent_env = parent.frame(), + inherit = CallbackSet, + lock_objects = FALSE +) +} +\arguments{ +\item{id}{(\code{character(1)})\cr`\cr +The id for the torch callback.} + +\item{classname}{(\code{character(1)})\cr +The class name.} + +\item{param_set}{(\code{ParamSet})\cr +The parameter set, if not present it is inferred from the \verb{$initialize()} method.} + +\item{packages}{(\code{character()})\cr\verb{The packages the callback depends on. Default is}NULL`.} + +\item{label}{(\code{character(1)})\cr +The label for the torch callback. +Defaults to the capitalized \code{id}.} + +\item{man}{(\code{character(1)})\cr +String in the format \verb{[pkg]::[topic]} pointing to a manual page for this object. +The referenced help package can be opened via method \verb{$help()}. +The default is \code{NULL}.} + +\item{on_begin, on_end, on_epoch_begin, on_before_valid, on_epoch_end, on_batch_begin, on_batch_end, on_after_backward, on_batch_valid_begin, on_batch_valid_end}{(\code{function})\cr +Function to execute at the given stage, see section \emph{Stages}.} + +\item{initialize}{(\verb{function()})\cr +The initialization method of the callback.} + +\item{public, private, active}{(\code{list()})\cr +Additional public, private, and active fields to add to the callback.} + +\item{parent_env}{(\code{environment()})\cr +The parent environment for the \code{\link{R6Class}}.} + +\item{inherit}{(\code{R6ClassGenerator})\cr +From which class to inherit. +This class must either be \code{\link{CallbackSet}} (default) or inherit from it.} + +\item{lock_objects}{(\code{logical(1)})\cr +Whether to lock the objects of the resulting \code{\link{R6Class}}. +If \code{FALSE} (default), values can be freely assigned to \code{self} without declaring them in the +class definition.} +} +\value{ +\code{\link{TorchCallback}} +} +\description{ +Convenience function to create a custom \code{\link{TorchCallback}}. +All arguments that are available in \code{\link[=callback_set]{callback_set()}} are also available here. +For more information on how to correctly implement a new callback, see \code{\link{CallbackSet}}. +} +\section{Internals}{ + +It first creates an \code{R6} class inheriting from \code{\link{CallbackSet}} (using \code{\link[=callback_set]{callback_set()}}) and +then wraps this generator in a \code{\link{TorchCallback}} that can be passed to a torch learner. +} + +\section{Stages}{ + +\itemize{ +\item \code{begin} :: Run before the training loop begins. +\item \code{epoch_begin} :: Run he beginning of each epoch. +\item \code{before_validation} :: Run before each validation loop. +\item \code{batch_begin} :: Run before the forward call. +\item \code{after_backward} :: Run after the backward call. +\item \code{batch_end} :: Run after the optimizer step. +\item \code{batch_valid_begin} :: Run before the forward call in the validation loop. +\item \code{batch_valid_end} :: Run after the forward call in the validation loop. +\item \code{epoch_end} :: Run at the end of each epoch. +\item \code{end} :: Run at last, using \code{on.exit()}. +} +} + +\examples{ +\dontshow{if (torch::torch_is_installed()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontshow{\}) # examplesIf} +custom_tcb = torch_callback("custom", + initialize = function(name) { + self$name = name + }, + on_begin = function() { + cat("Hello", self$name, ", we will train for ", self$ctx$total_epochs, "epochs.\n") + }, + on_end = function() { + cat("Training is done.") + } +) + +learner = lrn("classif.torch_featureless", + batch_size = 16, + epochs = 1, + callbacks = custom_tcb, + cb.custom.name = "Marie", + device = "cpu" +) +task = tsk("iris") +learner$train(task) +} +\seealso{ +Other Callback: +\code{\link{TorchCallback}}, +\code{\link{as_torch_callback}()}, +\code{\link{as_torch_callbacks}()}, +\code{\link{callback_set}()}, +\code{\link{mlr3torch_callbacks}}, +\code{\link{mlr_callback_set}}, +\code{\link{mlr_callback_set.checkpoint}}, +\code{\link{mlr_callback_set.progress}}, +\code{\link{mlr_context_torch}}, +\code{\link{t_clbk}()} +} +\concept{Callback}