The Scalars lecture established the zero-dimensional building block of numerical computation—a single number that scales vectors, weights loss functions, and appears as every element inside larger structures. Before that, Vectors and Matrices introduced one- and two-dimensional arrays that model features, embeddings, and linear transformations.
Tensors unify that hierarchy. In modern AI engineering, almost nothing is stored as a bare scalar, vector, or matrix in production code—frameworks represent data as tensors: typed, multi-dimensional arrays equipped with shape, data type, and (in GPU workflows) device placement. Whether you load a batch of images, tokenize text for a transformer, or inspect intermediate activations during debugging, you are working with tensors.
This lecture defines tensors as the generalization of scalars, vectors, and matrices; explains rank (order) and shape; and grounds both in PyTorch and TensorFlow—the two dominant tensor libraries in AI engineering. The next lecture, Matrix Multiplication, builds directly on tensor shapes and broadcasting rules introduced here.
Learning Objectives
By the end of this lesson, students should be able to:
- Define a tensor as a generalization of scalars, vectors, and matrices to arbitrary dimensions.
- Distinguish tensor order (rank) from matrix rank and use shape notation correctly.
- Read and interpret tensor shapes in PyTorch and TensorFlow, including
batch × height × width × channelsfor images. - Explain why batching is the first dimension in most deep learning pipelines.
- Identify dtype, device, and memory layout as first-class engineering concerns—not afterthoughts.
- Perform essential tensor inspections:
.shape,.dtype,.device, and sanity checks before training. - Recognize NCHW vs NHWC channel ordering and the bugs that arise when layouts are mixed.
- Connect tensor thinking to downstream topics: matrix multiplication, convolutions, and embedding lookups.
Introduction: The Data Structure Behind Every Model
Open any PyTorch training script or TensorFlow/Keras pipeline and you will encounter the same primitive repeatedly:
- A loss value computed from predictions and labels
- Weight matrices updated by an optimizer
- Activation tensors flowing through layers
- Input batches fed to the model each training step
Framework documentation calls all of these tensors. The word sounds abstract, but the engineering reality is concrete: a tensor is how numerical data is stored, typed, shaped, and moved through a computation graph. Misunderstanding tensor shape is one of the most common sources of runtime errors in AI engineering—often appearing as cryptic messages about incompatible dimensions during matrix multiplication or convolution.
Mastering tensors is not optional background mathematics. It is the vocabulary of production deep learning.
Scalars, Vectors, Matrices—and Beyond
A tensor is a multi-dimensional array of numbers (or booleans, integers, etc.) described by:
- Shape — the size along each axis (e.g.,
(32, 3, 224, 224)) - Dtype — the data type of each element (e.g.,
float32,int64) - Device — where the data lives in memory (CPU or GPU)
In this curriculum, scalars, vectors, and matrices are special cases of tensors with 0, 1, and 2 axes respectively.
| Object | Order (Rank) | Axes | Example Shape | AI Engineering Example |
|---|---|---|---|---|
| Scalar | 0 | none | () or (1,) |
Loss value, learning rate, classification threshold |
| Vector | 1 | 1 | (768,) |
Token embedding, class logits before softmax |
| Matrix | 2 | 2 | (512, 768) |
Linear layer weight, attention score matrix |
| 3D Tensor | 3 | 3 | (32, 128, 768) |
Batch of token sequences (batch × sequence × hidden) |
| 4D Tensor | 4 | 4 | (32, 3, 224, 224) |
Batch of RGB images (batch × channels × height × width) |
Mathematical physics uses “tensor” for objects that transform under coordinate changes—a richer definition than we need day to day in ML engineering. In PyTorch and TensorFlow, the term is operational: a tensor is the container type for numerical computation. That pragmatic definition is what matters when you debug a training job at 2 a.m.
Rank, Order, and Shape
Three terms appear constantly in documentation. Students must use them precisely.
Order (Rank) of a Tensor
The order or rank of a tensor is the number of dimensions (axes) it has. Equivalently, it is the length of the shape tuple.
- Shape
(768,)→ order 1 (vector) - Shape
(32, 768)→ order 2 (matrix) - Shape
(32, 128, 768)→ order 3 - Shape
(32, 3, 224, 224)→ order 4
Tensor rank (order) ≠ matrix rank. Matrix rank measures linear independence of rows/columns (a property of a 2D matrix). Tensor order simply counts axes. A 4D image batch has order 4 regardless of whether any 2D slice inside it has full matrix rank. Conflating these terms causes confusion when reading papers and framework docs side by side.
Shape
Shape tells you how many elements exist along each axis, read left to right. For a transformer hidden state with shape (32, 128, 768):
- Axis 0: batch size 32 (32 sequences processed in parallel)
- Axis 1: sequence length 128 (128 tokens per sequence)
- Axis 2: hidden dimension 768 (768 features per token)
Total elements: 32 × 128 × 768 = 3,145,728 floating-point values. Shape is how engineers reason about memory footprint and whether two tensors can be combined in an operation.
Element, Axis, and Slice
An element is a single stored value at a coordinate (e.g., batch 5, channel 2, row 100, column 50). An axis is one dimension of the array. A slice fixes all but one or more axes—for example, images[0] selects the first image in a batch, producing a (3, 224, 224) tensor.
Before writing model code, write the expected shapes on paper: input shape, output shape after each layer, loss shape. Shape annotations in notebooks and docstrings prevent an entire class of dimension-mismatch bugs. Senior engineers treat shape contracts as part of the API design.
Image Tensors: Batch × Height × Width × Channels
Computer vision pipelines represent images as 4D tensors. A single grayscale image is 2D (height × width). A single RGB image adds a channel axis: 3 × height × width. Production training almost always processes a batch of images in parallel, yielding a 4D tensor.
Scenario: 32 RGB images, each 224×224 pixels, fed to a ResNet classifier.
PyTorch (NCHW): (32, 3, 224, 224) — batch, channels, height, width
TensorFlow default (NHWC): (32, 224, 224, 3) — batch, height, width, channels
Same data, different axis ordering. Convolution layers expect a specific layout; mixing layouts without explicit permutation is a frequent source of silent wrong results or hard crashes.
| Notation | Axis Order | Default In | Typical Use |
|---|---|---|---|
| NCHW | batch, channels, height, width | PyTorch, many CUDA-optimized kernels | Research code, torchvision, most PyTorch production stacks |
| NHWC | batch, height, width, channels | TensorFlow/Keras (historical default), some mobile/TPU paths | Keras layers.Conv2D, TensorFlow Lite, certain TPU workflows |
Channel order within RGB is also standardized as R, G, B in most frameworks when channels are explicit. Preprocessing pipelines must match what the pretrained model expects—including normalization constants applied per channel.
From Pixels to Model Input
Raw image files are not tensors. Engineering pipelines perform deterministic transforms:
.to("cuda") or .to(device)
PyTorch Tensors
PyTorch is the dominant framework in research and an increasingly common production choice. Its central type is torch.Tensor.
Creating and Inspecting Tensors
import torch
# Scalar-like (0D): loss accumulator
loss = torch.tensor(2.47)
# Vector (1D): embedding dimension
vec = torch.randn(768)
# Matrix (2D): weight matrix
W = torch.randn(512, 768)
# 3D: batch of sequences (batch, seq_len, hidden)
hidden = torch.randn(32, 128, 768)
# 4D: image batch (NCHW)
images = torch.randn(32, 3, 224, 224)
print(images.shape) # torch.Size([32, 3, 224, 224])
print(images.dtype) # torch.float32
print(images.device) # cpu (until moved)
dtype and Numerical Stability
Common dtypes in AI engineering:
float32— default for most training; balance of speed and precisionfloat16/bfloat16— mixed-precision training on modern GPUs; faster, less memoryint64— token IDs, class labels, indexingbool— attention masks, padding masks
dtype mismatches (e.g., float64 weights with float32 inputs) trigger errors or implicit casts. Explicit dtype control is part of reproducible engineering.
Device Placement
GPU training requires every tensor in an operation to live on the same device. The pattern is universal:
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)
batch = batch.to(device)
Forgetting to move inputs while the model sits on GPU produces the infamous error: Expected all tensors to be on the same device.
Autograd: Tensors That Remember
Training tensors often set requires_grad=True so PyTorch can compute gradients via automatic differentiation. Loss scalars drive backpropagation; weight matrices accumulate .grad attributes. Inference-only tensors typically disable gradients for speed and memory savings:
with torch.no_grad():
predictions = model(images)
TensorFlow Tensors
TensorFlow (with Keras as the high-level API) remains widely deployed in enterprise and mobile/edge stacks. Its core type is tf.Tensor, often created implicitly through Keras layers and tf.data pipelines.
Creating and Inspecting Tensors
import tensorflow as tf
# Explicit tensor creation
scalar = tf.constant(2.47)
vec = tf.random.normal([768])
W = tf.random.normal([512, 768])
hidden = tf.random.normal([32, 128, 768])
images = tf.random.normal([32, 224, 224, 3]) # NHWC
print(images.shape) # (32, 224, 224, 3)
print(images.dtype) # <dtype: 'float32'>
Eager Execution vs Graph Mode
Modern TensorFlow runs in eager mode by default—operations execute immediately, similar to PyTorch’s imperative style. @tf.function traces computations into graphs for performance. Engineers debugging shape issues start in eager mode; they optimize with graphs once shapes are stable.
Keras Integration
Keras models accept NumPy arrays or tensors and return tensors. Layer definitions encode shape transformations:
model = tf.keras.Sequential([
tf.keras.layers.Conv2D(32, 3, activation="relu", input_shape=(224, 224, 3)),
tf.keras.layers.GlobalAveragePooling2D(),
tf.keras.layers.Dense(10, activation="softmax"),
])
Note input_shape=(224, 224, 3)—NHWC without the batch dimension. Keras inserts None for batch size automatically.
PyTorch Conventions
- Default image layout: NCHW
- Shape via
.shapeor.size() - Explicit device management
- Dynamic graphs (define-by-run)
torch.nnmodules; training loops often hand-written
TensorFlow / Keras Conventions
- Default image layout: NHWC (channels last)
- Shape via
.shape(may includeNonefor variable batch) - GPU placement via strategy API or implicit
tf.datafor input pipelines at scale- Keras
model.fit()for end-to-end training
Batching: Why the First Dimension Matters
Neural networks process batches of examples in parallel to saturate GPU throughput. Conventionally, axis 0 is the batch dimension unless documentation states otherwise.
- Training: batch size 32, 64, or 128 is typical; limited by GPU memory
- Inference: batch size 1 for latency-sensitive APIs; larger batches for offline scoring
- Variable-length sequences: padding and attention masks align batch items to a common length
When you squeeze or unsqueeze dimensions, you are changing tensor order. Removing the batch axis accidentally—images.squeeze() when batch size is 1—turns a 4D batch into a 3D tensor and breaks the next layer expecting 4D input.
Token IDs: (32, 128) — 32 sequences, 128 tokens each (int64)
Attention mask: (32, 128) — 1 for real tokens, 0 for padding (bool or float)
Embeddings after lookup: (32, 128, 768) — each token mapped to a 768-dimensional vector
Transformer output: (32, 128, 768) — contextualized representations per token
Reshaping, Broadcasting, and Views
Engineers constantly change tensor geometry without changing underlying data semantics.
Reshape and View
reshape / view (PyTorch) and reshape (TensorFlow) reinterpret the same elements with a new shape. Total element count must match. Flattening an image batch for a fully connected layer:
# PyTorch: (32, 3, 224, 224) -> (32, 150528)
flat = images.view(32, -1)
Broadcasting
Broadcasting allows operations between tensors of different but compatible shapes by virtually expanding dimensions. Adding a per-channel bias to an image batch relies on broadcasting. Incompatible shapes produce errors—another reason shape literacy matters before Matrix Multiplication.
Permute and Transpose
Switching between NCHW and NHWC is a permutation, not a copy of pixel values in a different order without care:
# PyTorch: NCHW -> NHWC
images_nhwc = images.permute(0, 2, 3, 1)
Tensor Operations Every Engineer Uses
| Operation | Purpose | Shape Intuition |
|---|---|---|
| Indexing / slicing | Select batch items, tokens, or channels | batch[0:8] → first 8 examples |
| Stack / cat | Combine tensors along a new or existing axis | Stack images into batch; concat sequences |
Reduction (sum, mean) |
Aggregate over axes (e.g., mean loss over batch) | loss.mean() → scalar |
| Matmul / einsum | Linear layers, attention | Inner dimensions must align (next lecture) |
| Element-wise ops | Activations (ReLU), masking, dropout | Same shape or broadcastable |
Debugging Tensors in Production Workflows
When a model fails or metrics look wrong, tensor inspection is the first diagnostic step:
- Print shape at model entry and exit—confirm expectations match reality
- Check dtype—uint8 images not normalized will destroy training
- Verify device—CPU/GPU mismatch errors are immediate; silent CPU fallback can hide performance issues
- Inspect value ranges—
tensor.min(),tensor.max(),torch.isnan(tensor).any() - Confirm channel order—visualize a single image after preprocessing
- Track memory—4D float32 batches consume VRAM quickly; order-5 video tensors more so
Element count × bytes per element ≈ tensor memory. A float32 tensor with 3,145,728 elements uses roughly 12 MB. A training batch with activations, gradients, and optimizer states multiplies that footprint many times over—shape decisions directly affect whether a job fits on available hardware.
Common Misconceptions
Why people believe it: High-level APIs like model.fit() hide tensor details.
Reality: APIs still require correctly shaped inputs. Data loading, custom loss functions, and debugging all expose raw tensors. Engineers who cannot read shapes cannot own a training pipeline.
Why people believe it: The word “rank” appears in both linear algebra and tensor documentation.
Reality: Tensor rank (order) counts axes. Matrix rank measures dimensionality of column/row space. A 4D image tensor has order 4; discussing its “matrix rank” is meaningless without specifying which 2D slice you mean.
Why people believe it: Both represent multi-dimensional arrays with similar APIs.
Reality: They are different runtime objects. Conversion requires explicit bridges (e.g., DLPack, NumPy as lingua franca). Layout conventions (NCHW vs NHWC) differ; blind copying causes subtle bugs.
Why people believe it: Both contain 768 numbers.
Reality: Order differs. Broadcasting, batching, and layer expectations treat them differently. A bias vector may need explicit unsqueeze to broadcast over a batch.
Quick Knowledge Check
- Short Answer: What is the order of a tensor with shape
(16, 3, 256, 256)? Answer: 4 (four axes: batch, channels, height, width in NCHW convention) - True/False: In PyTorch, tensor rank (order) is the same as matrix rank. Answer: False
- Multiple Choice: Which shape represents a batch of 32 RGB 224×224 images in PyTorch NCHW layout? Answer: (32, 3, 224, 224)
- Short Answer: What three attributes define a tensor in ML frameworks? Answer: Shape, dtype, and device (location in memory)
- True/False: TensorFlow’s historical default for Conv2D expects channels last (NHWC). Answer: True
- Multiple Choice: Which axis is conventionally the batch dimension? Answer: Axis 0 (the first dimension)
- Short Answer: Why do engineers batch inputs? Answer: To parallelize computation on GPUs and improve throughput during training and inference
- True/False: A scalar loss value in PyTorch is typically a 0-dimensional tensor. Answer: True
- Short Answer: What happens if model weights are on GPU but input tensors remain on CPU? Answer: Runtime error due to device mismatch (in standard workflows)
- Multiple Choice: Converting NCHW to NHWC requires which operation? Answer: Permute/transpose of axes (e.g.,
permute(0, 2, 3, 1)in PyTorch)
Key Takeaways
- Tensors generalize scalars (0D), vectors (1D), and matrices (2D) to any number of axes; they are the universal data container in PyTorch and TensorFlow.
- Tensor order (rank) counts dimensions; it is not the same as matrix rank from linear algebra.
- Shape defines size per axis; dtype and device are equally critical in engineering workflows.
- Image batches are 4D: PyTorch defaults to NCHW
(N, C, H, W); TensorFlow often uses NHWC(N, H, W, C). - Batching on axis 0 enables GPU parallelism; padding and masks handle variable-length sequences.
- Reshape, permute, and broadcasting change geometry without changing semantics—but incompatible shapes cause the most common runtime errors.
- Debug with shape, dtype, device, and value range checks before suspecting the model architecture.
- Fluency with tensors is prerequisite for matrix multiplication, convolutions, attention, and every downstream module in this volume.
Further Reading & References
Official Documentation
- PyTorch — Tensors and Autograd (
pytorch.org/docs) - TensorFlow — Introduction to Tensors (
tensorflow.org/guide/tensor) - torchvision transforms — Image preprocessing and NCHW conventions
- tf.keras.layers.Conv2D — Input shape and channels-last behavior
Books & Tutorials
- Deep Learning with PyTorch — Eli Stevens, Luca Antiga, and Thomas Viehmann. Practical tensor-centric workflows.
- Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow — Aurélien Géron. TensorFlow tensor and shape fundamentals.
- PyTorch 60-Minute Blitz — Official quickstart for tensor operations and neural network basics.
Related Lectures in This Module
- Scalars — Zero-dimensional tensors and numerical primitives
- Vectors — One-dimensional tensors and embeddings
- Matrices — Two-dimensional tensors and linear maps
- Matrix Multiplication — The operation that connects tensor shapes to layer design
Teaching strategy: Draw the hierarchy scalar → vector → matrix → 3D → 4D on the board. For each step, add one axis with a concrete AI example. Emphasize that frameworks never “leave” tensor land—even scalars are 0D tensors.
Whiteboard exercise: Given shape (8, 128, 768), ask students to identify batch size, sequence length, and hidden size. Repeat with (8, 3, 224, 224) in both NCHW and NHWC interpretations.
Hands-on idea (15 minutes): In a notebook, create random tensors in PyTorch and TensorFlow; print .shape and .dtype; permute an image tensor between NCHW and NHWC; move one tensor to GPU if available.
Discussion prompt: A teammate’s model expects (N, 3, 224, 224) but the data loader yields (N, 224, 224, 3). Where do you fix it—loader, model, or both—and how do you test the fix?
Expected difficulty: Students confuse tensor order with matrix rank. State the distinction explicitly and quiz it. Second pain point: forgetting batch axis when batch size is 1.