================
by Jawad Haider
00 - Tensor Basics¶
- 1 Tensor Basics
- 1.1 Perform standard imports
- 1.2 Converting NumPy arrays to PyTorch tensors
- 1.3 Copying vs. sharing
- 1.4 Class constructors
- 1.5 Creating tensors from scratch
- 1.5.1 Uninitialized tensors with .empty()
- 1.5.2 Initialized tensors with .zeros() and .ones()
- 1.5.3 Tensors from ranges
- 1.5.4 Tensors from data
- 1.5.5 Changing the dtype of existing tensors
- 1.5.6 Random number tensors
- 1.5.7 Random number tensors that follow the input size
- 1.5.8 Setting the random seed
- 1.6 Tensor attributes
Tensor Basics¶
This section covers: * Converting NumPy arrays to PyTorch tensors * Creating tensors from scratch
Perform standard imports¶
Confirm you’re using PyTorch version 1.1.0
'1.1.0'
Converting NumPy arrays to PyTorch tensors¶
A
torch.Tensor
is a multi-dimensional matrix containing elements of a single data
type.
Calculations between tensors can only happen if the tensors
share the same dtype.
In some cases tensors are used as a
replacement for NumPy to use the power of GPUs (more on this later).
[1 2 3 4 5]
int32
<class 'numpy.ndarray'>
tensor([1, 2, 3, 4, 5], dtype=torch.int32)
torch.int32
<class 'torch.Tensor'>
torch.IntTensor
[[ 0. 1. 2.]
[ 3. 4. 5.]
[ 6. 7. 8.]
[ 9. 10. 11.]]
tensor([[ 0., 1., 2.],
[ 3., 4., 5.],
[ 6., 7., 8.],
[ 9., 10., 11.]], dtype=torch.float64)
torch.DoubleTensor
Here torch.DoubleTensor refers to 64-bit floating point data.
Tensor Datatypes
TYPE | NAME | EQUIVALENT | TENSOR TYPE |
---|---|---|---|
32-bit integer (signed) | torch.int32 | torch.int | IntTensor |
64-bit integer (signed) | torch.int64 | torch.long | LongTensor |
16-bit integer (signed) | torch.int16 | torch.short | ShortTensor |
32-bit floating point | torch.float32 | torch.float | FloatTensor |
64-bit floating point | torch.float64 | torch.double | DoubleTensor |
16-bit floating point | torch.float16 | torch.half | HalfTensor |
8-bit integer (signed) | torch.int8 | CharTensor | |
8-bit integer (unsigned) | torch.uint8 | ByteTensor |
Copying vs. sharing¶
torch.from_numpy()
torch.as_tensor()
torch.tensor()
There are a number of different functions available for creating tensors. When using torch.from_numpy() and torch.as_tensor(), the PyTorch tensor and the source NumPy array share the same memory. This means that changes to one affect the other. However, the torch.tensor() function always makes a copy.
tensor([0, 1, 2, 3, 4], dtype=torch.int32)
tensor([ 0, 1, 77, 3, 4], dtype=torch.int32)
tensor([0, 1, 2, 3, 4], dtype=torch.int32)
tensor([0, 1, 2, 3, 4], dtype=torch.int32)
Class constructors¶
torch.Tensor()
torch.FloatTensor()
torch.LongTensor(),
etc.
There’s a subtle difference between using the factory function
torch.tensor(data) and the class
constructor torch.Tensor(data).
The factory function determines the dtype from the incoming data, or
from a passed-in dtype argument.
The class constructor
torch.Tensor()is simply an alias for
torch.FloatTensor(data). Consider the following:
tensor([1., 2., 3.]) torch.FloatTensor
tensor([1, 2, 3], dtype=torch.int32) torch.IntTensor
tensor([1, 2, 3]) torch.LongTensor
Creating tensors from scratch¶
Uninitialized tensors with .empty()¶
torch.empty() returns an uninitialized tensor. Essentially a block of memory is allocated according to the size of the tensor, and any values already sitting in the block are returned. This is similar to the behavior of numpy.empty().
tensor([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
Initialized tensors with .zeros() and .ones()¶
torch.zeros(size)
torch.ones(size)
It’s a good idea to pass in the intended dtype.
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
Tensors from ranges¶
torch.arange(start,end,step)
torch.linspace(start,end,steps)
Note that with .arange(), end is exclusive, while with
linspace(), end is inclusive.
tensor([[ 0, 2, 4],
[ 6, 8, 10],
[12, 14, 16]])
tensor([[ 0.0000, 1.6364, 3.2727, 4.9091],
[ 6.5455, 8.1818, 9.8182, 11.4545],
[13.0909, 14.7273, 16.3636, 18.0000]])
Tensors from data¶
torch.tensor() will choose the dtype based on incoming data:
tensor([1, 2, 3, 4])
torch.int64
torch.LongTensor
Alternatively you can set the type by the tensor method used. For a list of tensor types visit https://pytorch.org/docs/stable/tensors.html
tensor([5., 6., 7.])
torch.float32
torch.FloatTensor
You can also pass the dtype in as an argument. For a list of dtypes
visit
https://pytorch.org/docs/stable/tensor_attributes.html#torch.torch.dtype
tensor([ 8, 9, -3], dtype=torch.int32)
torch.int32
torch.IntTensor
Changing the dtype of existing tensors¶
Don’t be tempted to use x = torch.tensor(x, dtype=torch.type)
as it will raise an error about improper use of tensor cloning.
Instead, use the tensor .type() method.
Old: torch.IntTensor
New: torch.LongTensor
Random number tensors¶
torch.rand(size)
returns random samples from a uniform distribution over [0, 1)
torch.randn(size)
returns samples from the “standard normal” distribution [σ = 1]
Unlike rand which is uniform, values closer to zero are
more likely to appear.
torch.randint(low,high,size)
returns random integers from low (inclusive) to high (exclusive)
tensor([[0.0211, 0.2336, 0.6775],
[0.4790, 0.5132, 0.9878],
[0.7552, 0.0789, 0.1860],
[0.6712, 0.1564, 0.3753]])
tensor([[ 0.7164, -0.1538, -0.9980],
[-1.8252, 1.1863, -0.1523],
[ 1.4093, -0.0212, -1.5598],
[ 0.1831, -0.6961, 1.3497]])
tensor([[0, 3, 0],
[1, 3, 4],
[1, 2, 3],
[4, 4, 3]])
Random number tensors that follow the input size¶
torch.rand_like(input)
torch.randn_like(input)
torch.randint_like(input,low,high)
these return random number tensors with the same size as input
tensor([[0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0.]])
tensor([[-0.5442, -0.3149, 0.0922, 1.1829, -0.7873],
[ 0.3143, 0.9465, 0.4534, 0.4623, 2.2044]])
The same syntax can be used with
torch.zeros_like(input)
torch.ones_like(input)
tensor([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]])
Setting the random seed¶
torch.manual_seed(int) is used to obtain reproducible results
tensor([[0.8823, 0.9150, 0.3829],
[0.9593, 0.3904, 0.6009]])
tensor([[0.8823, 0.9150, 0.3829],
[0.9593, 0.3904, 0.6009]])
Tensor attributes¶
Besides dtype, we can look at other tensor attributes like shape, device and layout
torch.Size([2, 3])
torch.Size([2, 3])
device(type='cpu')
PyTorch supports use of multiple devices, harnessing the power of one or more GPUs in addition to the CPU. We won’t explore that here, but you should know that operations between tensors can only happen for tensors installed on the same device.
torch.strided
PyTorch has a class to hold the memory layout option. The default setting of strided will suit our purposes throughout the course.