Tensors

To get the most out of the walkthrough, we encourage you to follow along with the examples in a GHCi session.

To start, import Torch:

import Torch

A Tensor in Hasktorch is multidimensional array with a fixed shape and element type.

For example, we can initialize a tensor with shape [3, 4] and filled with zeros using

zeros' ([3, 4] :: [Int]) => 
Tensor Float [3,4] [[ 0.0000,  0.0000,  0.0000,  0.0000],
                    [ 0.0000,  0.0000,  0.0000,  0.0000],
                    [ 0.0000,  0.0000,  0.0000,  0.0000]]

We can also initialize a tensor from a Haskell list using asTensor:

asTensor ([[4, 3], [2, 1]] :: [[Float]]) => 
Tensor Float [2,2] [[ 4.0000   ,  3.0000   ],
                    [ 2.0000   ,  1.0000   ]]

Note that the numerical type of the tensor is inferred from the types of the values in the list.

Scalar values are represented in Hasktorch as tensors with shape []:

asTensor (3.5 :: Float) => 
Tensor Float []  3.5000   

We can get the scalar value back out using asValue:

asValue (asTensor (3.5 :: Float)) :: Float => 
3.5

Specifying Tensor parameters

In the previous section we initialized a tensor filled with zeros using zeros' (note the prime suffix). Hasktorch functions use a convention where default versions of functions use a prime suffix. The unprimed versions of these functions expect an additional parameter specifying tensor parameters. For example:

zeros :: [Int] -> Torch.TensorOptions -> Tensor

TensorOptions are typically specified by starting with Torch.TensorOptions.defaultOpts and modifying using one or more of the following:

  • withDType configures the data type of the elements

  • withDevice configures on which device the tensor is to be used

  • others (see Torch.TensorOptions)

For example, to construct a matrix filled with zeros of dtype Int64:

zeros [4, 4] (withDType Int64 defaultOpts) => 
Tensor Int64 [4,4] [[ 0,  0,  0,  0],
                    [ 0,  0,  0,  0],
                    [ 0,  0,  0,  0],
                    [ 0,  0,  0,  0]]

Tensor factories

Hasktorch comes with many "factory" functions similar to zeros and zeros' useful for initializing common kinds of tensors. For example, ones, full, eye, and the primed versions of these. See the Torch.TensorFactories module for a complete list.

One useful class of factory functions are those suffixed with "-like" (e.g. onesLike), which initialize a tensor with the same dimensions as their argument. For example:

let x = zeros' [3, 2] in onesLike x => 
Tensor Float [3,2] [[ 1.0000   ,  1.0000   ],
                    [ 1.0000   ,  1.0000   ],
                    [ 1.0000   ,  1.0000   ]]

Operations

Most operations are pure functions, similar to Haskell standard library math operations.

Tensors implement the Num typeclass, meaning they support the usual arithmetic operations:

let x = ones' [4] in x + x => 
Tensor Float [4] [ 2.0000   ,  2.0000   ,  2.0000   ,  2.0000   ]

Some operations transform a tensor:

relu (asTensor ([-1.0, -0.5, 0.5, 1] :: [Float])) => 
Tensor Float [4] [ 0.0000,  0.0000,  0.5000   ,  1.0000   ]

Torch.Tensor.select slices out a selection by specifying a dimension and index:

let x = asTensor ([[[1, 2, 3]], [[4, 5, 6]], [[7, 8, 9]], [[10, 11, 12]]] :: [[[Int]]])
shape x => 
[4,1,3]
select 2 1 x => 
Tensor Int64 [4,1] [[ 2],
                    [ 5],
                    [ 8],
                    [ 11]]
let y = asTensor ([1, 2, 3] :: [Int])
select 0 1 y => 
Tensor Int64 []  2

Values can be extracted from a tensor using asValue so long as the dtype matches the Haskell type:

let x = asTensor ([2] :: [Int]); y = asValue x :: Int in y => 
2