Note: This is an R port of the official tutorial available here. All credits goes to Soumith Chintala.

It’s a scientific computing package targeted at two sets of audiences:

  • An array library to use the power of GPUs
  • a deep learning research platform that provides maximum flexibility and speed

Getting started

Tensors

Tensors are similar to R arrays, with the addition being that Tensors can also be used on a GPU to accelerate computing.

Note: An uninitialized matrix is declared, but does not contain definite known values before it is used. When an uninitialized matrix is created, whatever values were in the allocated memory at the time will appear as the initial values.

Construct a 5x3 matrix, uninitialized:

x <- torch_empty(5, 3)
x
#> torch_tensor
#> -1.4391e-16  4.5765e-41 -1.4391e-16
#>  4.5765e-41 -1.4390e-16  4.5765e-41
#> -1.4390e-16  4.5765e-41 -1.4390e-16
#>  4.5765e-41 -1.4390e-16  4.5765e-41
#> -1.4390e-16  4.5765e-41 -1.4389e-16
#> [ CPUFloatType{5,3} ]

Construct a randomly initialized matrix:

x <- torch_rand(5, 3)
x
#> torch_tensor
#>  0.7929  0.7244  0.6064
#>  0.9672  0.9343  0.3779
#>  0.9790  0.6376  0.0521
#>  0.4001  0.6642  0.5126
#>  0.6414  0.9339  0.6715
#> [ CPUFloatType{5,3} ]

Construct a matrix filled zeros and of dtype long:

x <- torch_zeros(5, 3, dtype = torch_long())
x
#> torch_tensor
#>  0  0  0
#>  0  0  0
#>  0  0  0
#>  0  0  0
#>  0  0  0
#> [ CPULongType{5,3} ]

Construct a tensor directly from data:

x <- torch_tensor(c(5.5, 3))
x
#> torch_tensor
#>  5.5000
#>  3.0000
#> [ CPUFloatType{2} ]

or create a tensor based on an existing tensor. These methods will reuse properties of the input tensor, e.g. dtype, unless new values are provided by user

x <- torch_randn_like(x, dtype = torch_float()) # override dtype!
x                                               # result has the same size
#> torch_tensor
#>  0.9308
#>  2.3388
#> [ CPUFloatType{2} ]

Get its size:

x$size()
#> [1] 2

Operations

There are multiple syntaxes for operations. In the following example, we will take a look at the addition operation.

Addition: syntax 1

x <- torch_rand(5, 3)
y <- torch_rand(5, 3)
x + y
#> torch_tensor
#>  0.8263  0.7418  0.3512
#>  1.2059  0.8182  0.4930
#>  0.6130  0.7211  0.5668
#>  0.2880  0.2060  0.2389
#>  1.2657  0.6574  0.5647
#> [ CPUFloatType{5,3} ]

Addition: syntax 2

torch_add(x, y)
#> torch_tensor
#>  0.8263  0.7418  0.3512
#>  1.2059  0.8182  0.4930
#>  0.6130  0.7211  0.5668
#>  0.2880  0.2060  0.2389
#>  1.2657  0.6574  0.5647
#> [ CPUFloatType{5,3} ]

Addition: in-place

y$add_(x)
#> torch_tensor
#>  0.8263  0.7418  0.3512
#>  1.2059  0.8182  0.4930
#>  0.6130  0.7211  0.5668
#>  0.2880  0.2060  0.2389
#>  1.2657  0.6574  0.5647
#> [ CPUFloatType{5,3} ]
y
#> torch_tensor
#>  0.8263  0.7418  0.3512
#>  1.2059  0.8182  0.4930
#>  0.6130  0.7211  0.5668
#>  0.2880  0.2060  0.2389
#>  1.2657  0.6574  0.5647
#> [ CPUFloatType{5,3} ]

Note: Any operation that mutates a tensor in-place is post-fixed with an _. For example: x$copy_(y), x$t_(), will change x.

You can use standard R-like indexing with all bells and whistles! See more about indexing with vignette("indexing").

x[, 1]
#> torch_tensor
#>  0.2490
#>  0.4263
#>  0.2884
#>  0.2421
#>  0.7758
#> [ CPUFloatType{5} ]

Resizing: If you want to resize/reshape tensor, you can use torch_view:

x <- torch_randn(4, 4)
y <- x$view(16)
z <- x$view(size = c(-1, 8))  # the size -1 is inferred from other dimensions
x$size()
#> [1] 4 4
y$size()
#> [1] 16
z$size()
#> [1] 2 8

If you have a one element tensor, use $item() to get the value as an R number

x <- torch_randn(1)
x
#> torch_tensor
#>  0.4888
#> [ CPUFloatType{1} ]
x$item()
#> [1] 0.488809

You can find a complete list of operations in the reference page.

R bridge

Converting a Torch Tensor to an R array and vice versa is a breeze.

Converting a torch tensor into an R array

a <- torch_ones(5)
a
#> torch_tensor
#>  1
#>  1
#>  1
#>  1
#>  1
#> [ CPUFloatType{5} ]
b <- as_array(a)
b
#> [1] 1 1 1 1 1

Converting R arrays to torch tensors

a <- rep(1, 5)
a
#> [1] 1 1 1 1 1
b <- torch_tensor(a)
b
#> torch_tensor
#>  1
#>  1
#>  1
#>  1
#>  1
#> [ CPUFloatType{5} ]

Currently supported types are numerics and boolean types.

CUDA tensors

Tensors can be moved onto any device using the $to method.

if (cuda_is_available()) {
  device <- torch_device("cuda")
  y <- torch_ones_like(x, device = device)  # directly create a tensor on GPU
  x <- x$to(device)                       # or just use strings ``.to("cuda")``
  z <- x + y
  print(z)
  print(z$to(device = "cpu", torch_double())) # `$to` can also change dtype together!
}