Deep learning
PyTorch tensors
Tensors carry a shape, a dtype and a device. Views, broadcasting and strides explain most of the surprises you will hit.
Every number in PyTorch lives in a tensor. A tensor is a multi-dimensional array with a fixed dtype and a device. Rank 0 is a scalar, rank 1 is a vector and rank 2 is a matrix. Most bugs you will meet come from one of three things: shapes, devices or dtypes.
Concept
A dtype is the number format, such as float32 for training or int64 for indices. A device is where the data lives: cpu, cuda:0 or mps on Apple Silicon.
Shapes, dtypes and devices
Common dtypes:
float32is the default for training.float16andbfloat16are used for mixed precision.int64is used for indices and class labels.boolis used for masks.
Devices never move on their own. Move the data explicitly:
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
x = x.to(device)Operands must be on the same device. A classic footgun is leaving labels on the CPU while the logits are on the GPU.
Views, copies and strides
A view is a new shape over the same memory. These operations are views or cheap changes:
viewandreshapechange the shape.transposeandpermutereorder the axes.contiguous()makes a copy laid out in row order, when you need one.clone()always makes a true copy.
a = torch.arange(6).reshape(2, 3)
print(a.stride(), a.t().stride())
print(a.t().is_contiguous())Output:
(3, 1) (1, 3)
FalseA stride says how many steps in memory you take to move one place along an axis. Transposing swaps the strides, so the memory is no longer laid out row by row. That is why view can fail after a transpose. Use reshape, or call .contiguous() first.
Broadcasting
Shapes are compared from the right. Two dimensions match when they are equal or one of them is 1. Here (2, 5, 4) plus (4,) works, because the (4,) vector is repeated across the other axes:
h = torch.randn(2, 5, 4)
bias = torch.tensor([1.0, 2.0, 3.0, 4.0])
print((h + bias).shape)Output:
torch.Size([2, 5, 4])Broadcasting also hides bugs. Adding a (B,) vector to a (B, T) matrix can silently run along the wrong axis. When something "kind of works," print the shapes.
Common mistakes
- Mixing devices. Move the model, the batch and the targets to the same device.
- Trusting
viewafter a transpose. It needs contiguous memory. Usereshapeor.contiguous(). - Broadcasting by accident. Print
shapeon both sides of a suspicious add or multiply.
Check yourself
- Why does
h.transpose(0, 1).view(10, 4)fail? Answer: the transposed tensor is not contiguous, andviewneeds contiguous memory. Usereshapeinstead. - What shape does
(2, 1, 4) + (3, 1)give? Answer:(2, 3, 4). Align from the right: 4 with 1 gives 4, 1 with 3 gives 3, and 2 stands alone.
Key takeaways
- A tensor is an array with a shape, a dtype and a device.
- Move data to the device explicitly. Mismatched devices raise errors.
viewneeds contiguous memory. Strides explain why.- Broadcasting is convenient and quietly dangerous. Check shapes.
Further learning
Next, learn how PyTorch computes gradients for these tensors in autograd.
Related
PyTorch autograd
Autograd records the operations you run and computes gradients with backward(). It is the backprop algorithm, done for you.
PyTorch fundamentals
Tensors, autograd, modules, data loaders and a clean training loop. The daily-driver API for deep learning. Start here for the map.
Backpropagation from scratch
How training computes the gradient of the loss for every weight in one backward pass. Covers computational graphs, reverse-mode autodiff and the bugs that break training.