Tensor shape: .shape attribute
Why this matters
You'll inspect tensor shapes constantly when debugging models. If your data is the wrong shape, your model will crash or silently produce wrong results. Understanding shape is foundational before you touch any neural network code.
Explanation
What it is: The .shape attribute is a read-only property of any PyTorch tensor that returns a torch.Size object describing the size of each dimension. For example, a tensor with shape (3, 4, 5) has 3 dimensions: 3 elements in the first, 4 in the second, 5 in the third.
How it works: When you create or transform a tensor, PyTorch tracks its shape internally. Accessing .shape doesn't perform any computation: it just reads metadata. You can also use .size() as an alias (they return the same thing), and you can access individual dimensions with bracket notation: tensor.shape[0] gives the size of the first dimension.
When to use it: Use .shape whenever you need to understand or validate the structure of your data: before reshaping, before passing to a model, after loading data, or when debugging dimension mismatches. It's your primary tool for understanding what you're working with.
Analogy
Think of shape like the dimensions of a spreadsheet: a 1D tensor is a single column (shape <code>(5,)</code> = 5 rows), a 2D tensor is rows and columns (shape <code>(3, 4)</code> = 3 rows, 4 columns), a 3D tensor is like a stack of spreadsheets (shape <code>(2, 3, 4)</code> = 2 sheets, each 3 rows by 4 columns).
Code
import torch
# Create tensors of different shapes
scalar = torch.tensor(5)
print(f"Scalar shape: {scalar.shape}")
vector = torch.tensor([1.0, 2.0, 3.0, 4.0, 5.0])
print(f"Vector shape: {vector.shape}")
matrix = torch.tensor([[1, 2, 3],
[4, 5, 6]])
print(f"Matrix shape: {matrix.shape}")
tensor_3d = torch.randn(2, 3, 4)
print(f"3D tensor shape: {tensor_3d.shape}")
# Access individual dimensions
print(f"First dimension size: {tensor_3d.shape[0]}")
print(f"Second dimension size: {tensor_3d.shape[1]}")
# Shape is indexable
shape_tuple = tensor_3d.shape
print(f"Shape as object: {shape_tuple}")
print(f"Number of dimensions: {len(tensor_3d.shape)}")
# .size() is equivalent to .shape
print(f"Using .size(): {tensor_3d.size()}")
# Total number of elements
total_elements = torch.numel(tensor_3d)
print(f"Total elements: {total_elements}") Scalar shape: torch.Size([]) Vector shape: torch.Size([5]) Matrix shape: torch.Size([2, 3]) 3D tensor shape: torch.Size([2, 3, 4]) First dimension size: 2 Second dimension size: 3 Shape as object: torch.Size([2, 3, 4]) Number of dimensions: 3 Using .size(): torch.Size([2, 3, 4]) Total elements: 24
What just happened?
We created five different tensors (one scalar with no dimensions, one 1D vector, one 2D matrix, and one 3D tensor with random values). We printed their shapes to see the dimension structure of each. We indexed into a shape object to get individual dimension sizes. We confirmed that <code>.size()</code> returns the same thing as <code>.shape</code>. Finally, we calculated the total number of elements using <code>torch.numel()</code> (2 × 3 × 4 = 24 elements).
Common gotcha
Developers often confuse .shape (which returns a torch.Size object) with the tensor itself. Writing if tensor.shape: will always be truthy: you need if tensor.shape == torch.Size([...]): or if tensor.numel() > 0: to check if a tensor is actually empty. Also, .shape[0] returns a Python integer (not a tensor), so you can use it directly in arithmetic without calling .item().
Error recovery
IndexErrorTypeError when comparing shapesExperienced dev note
In production, add shape assertions early in your data pipeline: assert tensor.shape == expected_shape, f"Got {tensor.shape}, expected {expected_shape}". This saves hours debugging silent failures downstream. Also, PyTorch allows you to reshape tensors with .reshape() or .view(): but always validate the total element count matches before reshaping, or you'll get an unhelpful error. One more: batch dimension (first dimension) often changes at inference time, so write flexible shape checks: assert tensor.shape[1:] == (3, 224, 224) instead of locking all dimensions.
Check your understanding
If you have a tensor with shape (4, 5, 6) and you flatten it to 1D, what will its new shape be? Why can't you reshape it to shape (4, 8) directly?
Show answer hint
A correct answer explains that flattening gives <code>(120,)</code> because 4 × 5 × 6 = 120 total elements. The reshape to <code>(4, 8)</code> fails because 4 × 8 = 32, which doesn't match the 120 total elements: PyTorch enforces that the total element count never changes during a reshape.