beginner · ~10 min

What is a Tensor?

Scalars, vectors, matrices, and beyond — build an intuition for the shapes TensorFlow moves data around in.

Every number TensorFlow works with — a single price, a row of house features, a whole image — is stored as a tensor. The name sounds intimidating, but a tensor is nothing more than "numbers arranged in a grid of some number of dimensions."

  • Rank 0 (scalar) — a single number, like 72.5.
  • Rank 1 (vector) — a list of numbers, like [72.5, 3, 12] (maybe: price, bedrooms, age).
  • Rank 2 (matrix) — a grid, like one grayscale image's pixel values.
  • Rank 3+ — stacks of matrices, like a color image (height × width × color channel) or a batch of images.

Beginner tip

If you've used a spreadsheet, a rank-2 tensor is just the grid of cells. A rank-1 tensor is a single row or column. A rank-0 tensor is a single cell. A quick trick for reading rank straight off the page: count the opening brackets before the first number. [1, 2, 3] has one bracket → rank 1. [[1, 2], [3, 4]] has two → rank 2.

Every tensor also has a shape — the size along each axis — and a dtype, the type of number it holds.

Play with the explorer below: switch between scalar, vector, and matrix, resize it, and reroll the values. The shape [rows, cols] — and the rank and size TensorFlow reports for it — updates live underneath.

Production note

In production code you'll almost always work with a batch dimension too — even a single image becomes rank 4: [batch, height, width, channels]. Keras layers expect the batch dimension even when you're only predicting on one example, which is the most common "why is my shape wrong" bug for people new to the framework.

🔍 Deep dive: Why does the batch dimension exist?

Training in batches (rather than one example at a time) lets the GPU parallelize the matrix multiplications behind every layer, and it gives gradient descent a smoother, less noisy signal to follow. tf.tensor([1, 2, 3]) has shape [3]; tf.tensor([[1, 2, 3]]) has shape [1, 3] — a batch of one 3-element example. The extra bracket is doing real work.

🔍 Deep dive: Broadcasting: how tensors of different shapes combine

Every arithmetic op in this course so far — xsT.mul(w).add(b) in the linear regression playground, for instance — quietly relies on broadcasting: when shapes don't match exactly, TensorFlow stretches the smaller tensor to fit, without copying data, as long as the shapes are compatible. A scalar w (shape []) multiplying a vector xsT (shape [16]) broadcasts w across all 16 elements. Two shapes are compatible for broadcasting if, comparing dimensions from the right, each pair is either equal or one of them is 1 — [16, 1] and [16, 4] broadcast together (the 1 stretches to 4), but [16, 3] and [16, 4] do not.

🔍 Deep dive: dtype: why float32 is the default, and when it bites you

tf.tensor([1, 2, 3]) silently becomes dtype float32, not the integers you typed — float32 is TensorFlow's default because gradient descent needs to represent tiny, continuously-varying updates, which integers can't. This matters in practice: dividing two int32 tensors truncates like integer division in most languages, and mixing dtypes in one operation (say, an int32 label tensor against a float32 prediction tensor) throws rather than silently casting — you'll hit this the first time you build a label tensor from raw class indices and forget to cast it.

Production note

Every lib/tf/*.ts helper elsewhere in this course wraps its math in tf.tidy(() => ...). TensorFlow.js doesn't garbage-collect tensors automatically the way plain JavaScript objects are — each one holds real GPU/CPU memory until explicitly disposed, and tf.tidy disposes every intermediate tensor created inside it once it returns (except ones you explicitly return out). Forgetting this in a loop that runs every animation frame — like every "Play" button in this course — leaks a little memory on every single tick.

Playground

6
0.33
0.31
0.93
0.73
0.34
-0.38

shape: [6] · rank: 1 · size: 6 — this is exactly what tf.tensor(values, [6]) reports for .shape, .rank, and .size in real TensorFlow.js code.