We are pleased to announce version 0.2.0. torch
Just landed on CRAN.
This release includes many bug fixes and some cool new features that I’ll introduce in this blog post. You can view the full change log in the NEWS.md file.
The features we will discuss in detail are:
- Initial support for JIT tracking
- Multi-worker dataloader
- Printing method
nn_modules
Multi-worker dataloader
dataloaders
respond now num_workers
Enter the arguments and run preprocessing on a parallel worker.
For example, let’s say you have the following dummy dataset that performs a long calculation:
library(torch)
dat <- dataset(
"mydataset",
initialize = function(time, len = 10) {
self$time <- time
self$len <- len
},
.getitem = function(i) {
Sys.sleep(self$time)
torch_randn(1)
},
.length = function() {
self$len
}
)
ds <- dat(1)
system.time(ds(1))
user system elapsed
0.029 0.005 1.027
Now we will create two dataloaders: one that runs sequentially and one that runs in parallel.
seq_dl <- dataloader(ds, batch_size = 5)
par_dl <- dataloader(ds, batch_size = 5, num_workers = 2)
Now you can compare the time it takes to process two batches sequentially versus the time it takes to process them in parallel.
seq_it <- dataloader_make_iter(seq_dl)
par_it <- dataloader_make_iter(par_dl)
two_batches <- function(it) {
dataloader_next(it)
dataloader_next(it)
"ok"
}
system.time(two_batches(seq_it))
system.time(two_batches(par_it))
user system elapsed
0.098 0.032 10.086
user system elapsed
0.065 0.008 5.134
Note that these are batches obtained in parallel rather than individual observations. As such, in the future we will be able to support datasets with variable batch sizes.
Using multiple workers is ~ no It is necessarily faster than serial execution because there is significant overhead not only when initializing workers, but also when passing tensors from workers to the main session.
This feature is powerful callr
It comes packaged and works on all supported operating systems. torch
. callr
Let’s create a persistent R session. Therefore, the overhead of transferring potentially large dataset objects to workers is paid only once.
In implementing this feature, we made the dataloader behave like this: coro
Iterator. This means you can now use: coro
Syntax for looping through the dataloader:
coro::loop(for(batch in par_dl) {
print(batch$shape)
})
(1) 5 1
(1) 5 1
this is the first torch
This is a release that includes the multi-worker dataloader feature, and extreme cases may occur when using it. If you find any issues, please let us know.
Initial JIT support
Program using torch
The package is necessarily an R program, so it will always require an R installation to run.
Starting with version 0.2.0, torch
Allow users to perform JIT track
torch
R functions as TorchScript. Just in time (JIT) tracing calls an R function with example input, records all actions that occur when the function runs, and script_function
An object containing a TorchScript representation.
The nice thing about this is that TorchScript programs are easily serializable, optimizable, and can be loaded by PyTorch or other programs written in LibTorch without any R dependencies.
Suppose we have the following R function, which uses a tensor to perform matrix multiplication with a fixed weight matrix and then adds a bias term.
w <- torch_randn(10, 1)
b <- torch_randn(1)
fn <- function(x) {
a <- torch_mm(x, w)
a + b
}
This function can be JIT-tracked with TorchScript using: jit_trace
By passing a function and example input:
x <- torch_ones(2, 10)
tr_fn <- jit_trace(fn, x)
tr_fn(x)
torch_tensor
-0.6880
-0.6880
( CPUFloatType{2,1} )
now everyone torch
I traced what happened when calculating the result of this function and converted it to a graph.
graph(%0 : Float(2:10, 10:1, requires_grad=0, device=cpu)):
%1 : Float(10:1, 1:1, requires_grad=0, device=cpu) = prim::Constant(value=-0.3532 0.6490 -0.9255 0.9452 -1.2844 0.3011 0.4590 -0.2026 -1.2983 1.5800 ( CPUFloatType{10,1} ))()
%2 : Float(2:1, 1:1, requires_grad=0, device=cpu) = aten::mm(%0, %1)
%3 : Float(1:1, requires_grad=0, device=cpu) = prim::Constant(value={-0.558343})()
%4 : int = prim::Constant(value=1)()
%5 : Float(2:1, 1:1, requires_grad=0, device=cpu) = aten::add(%2, %3, %4)
return (%5)
The traced function can be serialized like this: jit_save
:
jit_save(tr_fn, "linear.pt")
You can reload it in R using: jit_load
However, you can also reload it in Python using: torch.jit.load
:
import torch
fn = torch.jit.load("linear.pt")
fn(torch.ones(2, 10))
tensor(((-0.6880),
(-0.6880)))
How cool is that?!
This is only initial support for JIT in R. We will continue to develop this. Especially in the next version torch
We plan to support tracking nn_modules
directly. Currently, you have to separate all parameters before you can track them. See an example here. This also lets you take advantage of TorchScript to run your models faster!
Tracking also has some limitations. This is especially true if your code has loops or control flow statements that depend on tensor data. see ?jit_trace
Learn more
A new way to print nn_modules
This release also includes the following improvements: nn_module
We use a printing method to make it easier to understand what’s inside.
for example, nn_linear
The modules you will see are:
An `nn_module` containing 11 parameters.
── Parameters ──────────────────────────────────────────────────────────────────
● weight: Float (1:1, 1:10)
● bias: Float (1:1)
You can immediately see the total number of parameters in a module, as well as its name and appearance.
This also applies to custom modules (including their submodules). for example:
my_module <- nn_module(
initialize = function() {
self$linear <- nn_linear(10, 1)
self$param <- nn_parameter(torch_randn(5,1))
self$buff <- nn_buffer(torch_randn(5))
}
)
my_module()
An `nn_module` containing 16 parameters.
── Modules ─────────────────────────────────────────────────────────────────────
● linear: <nn_linear> #11 parameters
── Parameters ──────────────────────────────────────────────────────────────────
● param: Float (1:5, 1:1)
── Buffers ─────────────────────────────────────────────────────────────────────
● buff: Float (1:5)
I hope this makes your understanding easier. nn_module
objects. We’ve also improved autocompletion support for the following items: nn_modules
All submodules, parameters, and buffers are now visible while typing.
Torch Audio
torchaudio
This is an extension to torch
Developed by Athos Damiani (@athospd
), provides a common architecture for audio loading, transformation, and signal processing, pre-trained weights, and access to commonly used datasets. It is an almost literal translation of PyTorch’s Torchaudio library into R.
torchaudio
is not yet included on CRAN, but you can try the development version already available here.
You can also visit: pkgdown
Website with examples and reference documentation.
Other features and bug fixes
Thanks to community contributions, we’ve found and fixed many bugs. torch
. We’ve also added the following new features:
You can see the full list of changes in the NEWS.md file.
Thank you so much for reading this blog post. If you need help or discussion, please feel free to contact us on GitHub!
The photo used to preview this post was taken by Oleg Illarionov on Unsplash.