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 elementswithDevice
configures on which device the tensor is to be usedothers (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