Deep Learning library that extends the mlr3 framework by building upon the 'torch' package. It makes it convenient to 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'.
Package website: release | dev
Deep Learning with torch and mlr3.
# Install from CRAN
install.packages("mlr3torch")
# Install the development version from GitHub:
pak::pak("mlr-org/mlr3torch")
Afterwards, you also need to run the command below:
torch::install_torch()
More information about installing torch can be found
here.
mlr3torch is a deep learning framework for the
mlr3 ecosystem built on top of
torch. It makes it easy to build, train
and evaluate deep learning models in a few lines of code, without
needing to worry about low-level details. Off-the-shelf learners are
readily available, but custom architectures can be defined by connecting
PipeOpTorch operators in an mlr3pipelines::Graph.
Using predefined learners such as a simple multi-layer perceptron (MLP)
works just like any other mlr3 Learner.
library(mlr3torch)
learner_mlp = lrn("classif.mlp",
# defining network parameters
activation = nn_relu,
neurons = c(20, 20),
# training parameters
batch_size = 16,
epochs = 50,
device = "cpu",
# Proportion of data to use for validation
validate = 0.3,
# Defining the optimizer, loss, and callbacks
optimizer = t_opt("adam", lr = 0.1),
loss = t_loss("cross_entropy"),
callbacks = t_clbk("history"), # this saves the history in the learner
# Measures to track
measures_valid = msrs(c("classif.logloss", "classif.ce")),
measures_train = msrs(c("classif.acc")),
# predict type (required by logloss)
predict_type = "prob"
)
Below, we train this learner on the sonar example task:
learner_mlp$train(tsk("sonar"))
Next, we construct the same architecture using PipeOpTorch objects.
The first pipeop – a PipeOpTorchIngress – defines the entry point of
the network. All subsequent pipeops define the neural network layers.
architecture = po("torch_ingress_num") %>>%
nn("linear", out_features = 20) %>>%
nn("relu") %>>%
nn("head")
To turn this into a learner, we configure the loss, optimizer, callbacks
as well as the training arguments, and convert the resulting Graph via
as_learner_torch().
graph_mlp = architecture %>>%
po("torch_loss", loss = t_loss("cross_entropy")) %>>%
po("torch_optimizer", optimizer = t_opt("adam", lr = 0.1)) %>>%
po("torch_callbacks", callbacks = t_clbk("history")) %>>%
po("torch_model_classif",
batch_size = 16, epochs = 50, device = "cpu")
graph_lrn = as_learner_torch(graph_mlp)
To work with generic tensors, the lazy_tensor type can be used. It
wraps a torch::dataset, but makes it possible to preprocess the data
(lazily) using PipeOp objects. Below, we flatten the MNIST task, so we
can then train a multi-layer perceptron on it. Note that this does not
transform the data in-memory, but is only applied when the data is
actually loaded.
# load the predefined mnist task
mnist = tsk("mnist")
mnist$head(3L)
#> label image
#> <fctr> <lazy_tensor>
#> 1: 5 <tnsr[1x28x28]>
#> 2: 0 <tnsr[1x28x28]>
#> 3: 4 <tnsr[1x28x28]>
# Flatten the images
flattener = po("trafo_reshape", shape = c(-1, 28 * 28))
mnist_flat = flattener$train(list(mnist))[[1L]]
mnist_flat$head(3L)
#> label image
#> <fctr> <lazy_tensor>
#> 1: 5 <tnsr[784]>
#> 2: 0 <tnsr[784]>
#> 3: 4 <tnsr[784]>
To actually access the tensors, we can call materialize(). We only
show a slice of the resulting tensor for readability:
materialize(
mnist_flat$data(1:2, cols = "image")[[1L]],
rbind = TRUE
)[1:2, 1:4]
#> torch_tensor
#> 0 0 0 0
#> 0 0 0 0
#> [ CPUFloatType{2,4} ]
Below, we define a more complex architecture that has one single input
which is a lazy_tensor. For that, we first define a single residual
block:
layer = list(
po("nop"),
nn("linear", out_features = 50L) %>>%
nn("dropout") %>>% nn("relu")
) %>>% nn("merge_sum")
Next, we create a neural network that takes as input a lazy_tensor
(po("torch_ingress_ltnsr")). It first applies a linear layer and then
repeats the above layer using the special PipeOpTorchBlock, followed
by the network’s head. After that, we configure the loss, optimizer and
the training parameters.
deep_network = po("torch_ingress_ltnsr") %>>%
nn("linear", out_features = 50L) %>>%
nn("block", layer, n_blocks = 5L) %>>%
nn("head") %>>%
po("torch_loss", loss = t_loss("cross_entropy")) %>>%
po("torch_optimizer", optimizer = t_opt("adam")) %>>%
po("torch_model_classif",
epochs = 100L, batch_size = 32
)
Next, we prepend the preprocessing step that flattens the images so we can directly apply this learner to the unflattened MNIST task.
deep_learner = as_learner_torch(
flattener %>>% deep_network
)
deep_learner$id = "deep_network"
In order to keep track of the performance during training, we use 20% of the data and evaluate it using classification accuracy.
set_validate(deep_learner, 0.2)
deep_learner$param_set$set_values(
torch_model_classif.measures_valid = msr("classif.acc")
)
All that is left is to train the learner:
deep_learner$train(mnist)
mlr3::Learners,
for both tabular classification and regression, as well as image
classification.Graph language
from mlr3pipelines and turned into a learner. Alternatively, you can
also simply define your custom architecture as a torch::nn_module.lazy_tensor data type.
This means that, in principle, the package can support arbitrary
modalities of data, including multi-modal datasets.mlr3 integration: Resampling, benchmarking, and
parallelization work as for any other mlr3 learner. Neural network
architectures, as well as their hyperparameters, can be easily tuned
via mlr3tuning and friends.TEST_TORCH = 1, e.g. by adding it to .Renviron.torch none of this would have been
possible.torch.PipeOpTorch operators is inspired by
keras.If you use mlr3torch in a scientific publication, please cite it as:
@article{fischer2026mlr3torch,
title={mlr3torch: A Deep Learning Framework in R based on mlr3 and torch},
author={Fischer, Sebastian and Burk, Lukas and Zhang, Carson and Bischl, Bernd and Binder, Martin},
journal={arXiv preprint arXiv:2604.18152},
year={2026}
}
mlr3torch is a free and open source software project that encourages participation and feedback. If you have any issues, questions, suggestions or feedback, please do not hesitate to open an “issue” about it on the GitHub page!
In case of problems / bugs, it is often helpful if you provide a “minimum working example” that showcases the behaviour (but don’t worry about this if the bug is obvious).
Please understand that the resources of the project are limited: responses may sometimes be delayed by a few days, and some feature suggestions may be rejected if they are deemed too tangential to the vision behind the project.