knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = identical(Sys.getenv("TORCH_TEST", unset = "0"), "1"), purl = FALSE )
library(torch)
In this article we describe the indexing operator for torch tensors and how it compares to the R indexing operator for arrays.
Torch's indexing semantics are closer to numpy's semantics than R's. You will find a lot of similarities between this article and the numpy
indexing article available here.
Single element indexing for a 1-D tensors works mostly as expected. Like R, it is 1-based. Unlike R though, it accepts negative indices for indexing from the end of the array. (In R, negative indices are used to remove elements.)
x <- torch_tensor(1:10) x[1] x[-1]
You can also subset matrices and higher dimensions arrays using the same syntax:
x <- x$reshape(shape = c(2,5)) x x[1,3] x[1,-1]
Note that if one indexes a multidimensional tensor with fewer indices than dimensions, torch's behaviour differs from R,
which flattens the array. In torch, the missing indices are considered complete slices :
.
x[1]
It is possible to slice and stride arrays to extract sub-arrays of the same number of dimensions, but of different sizes than the original. This is best illustrated by a few examples:
x <- torch_tensor(1:10) x x[2:5] x[1:(-7)]
You can also use the 1:10:2
syntax which means: In the range from 1 to 10, take every second item. For example:
x[1:5:2]
Another special syntax is the N
, meaning the size of the specified dimension.
x[5:N]
Note: the slicing behavior relies on Non Standard Evaluation. It requires that the expression is passed to the
[
not exactly the resulting R vector.
To allow dynamic dynamic indices, you can create a new slice using the slc
function.
For example:
x[1:5:2]
is equivalent to:
x[slc(start = 1, end = 5, step = 2)]
Like in R, you can take all elements in a dimension by leaving an index empty.
Consider a matrix:
x <- torch_randn(2, 3) x
The following syntax will give you the first row:
x[1,]
And this would give you the first 2 columns:
x[,1:2]
By default, when indexing by a single integer, this dimension will be dropped to avoid the singleton dimension:
x <- torch_randn(2, 3) x[1,]$shape
You can optionally use the drop = FALSE
argument to avoid dropping the dimension.
x[1,,drop = FALSE]$shape
It's possible to add a new dimension to a tensor using index-like syntax:
x <- torch_tensor(c(10)) x$shape x[, newaxis]$shape x[, newaxis, newaxis]$shape
You can also use NULL
instead of newaxis
:
x[,NULL]$shape
Sometimes we don't know how many dimensions a tensor has, but we do know what to do with the last available dimension, or the first one. To subsume all others, we can use ..
:
z <- torch_tensor(1:125)$reshape(c(5,5,5)) z[1,..] z[..,1]
Vector indexing is also supported but care must be taken regarding performance as, in general its much less performant than slice based indexing.
Note: Starting from version 0.5.0, vector indexing in torch follows R semantics, prior to that the behavior was similar to numpy's advanced indexing. To use the old behavior, consider using
?torch_index
,?torch_index_put
ortorch_index_put_
.
x <- torch_randn(4,4) x[c(1,3), c(1,3)]
You can also use boolean vectors, for example:
x[c(TRUE, FALSE, TRUE, FALSE), c(TRUE, FALSE, TRUE, FALSE)]
The above examples also work if the index were long or boolean tensors, instead of R vectors. It's also possible to index with multi-dimensional boolean tensors:
x <- torch_tensor(rbind( c(1,2,3), c(4,5,6) )) x[x>3]
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.