Foundations: Python, Git and toolsLoading progress…

Arrays and shapes

Use array shapes, broadcasting and reductions to express a small data transformation.

A shape is the size of every axis

A NumPy array is a block of numbers of one type, arranged on a grid. Its shape lists how long the grid is along each axis. A table of 4 examples with 3 features each has shape (4, 3): axis 0 (length 4) runs down the examples, axis 1 (length 3) runs across the features. Whether axis 0 means "examples" is a convention you choose and must remember; NumPy only knows the lengths.

>>> import numpy as np
>>> X = np.zeros((4, 3))
>>> X.shape, X.ndim, X.size
((4, 3), 2, 12)        # axis lengths, number of axes, number of elements

Inside memory the numbers are one flat line. The shape only says how to read that line as a grid: the last axis changes fastest. That is why a cell's position a[i, j] turns into the single offset i * (row length) + j.

a.shape = (3, 4) a.ndim = 2 a.size = 12 axis 0 has length 3, axis 1 has length 4 cell 5 sits at a[1, 1] offset = 1*4 + 1*1 = 5

Click a cell. The numbers in the cells are the order the values are stored in memory, row by row (the last axis changes fastest). Now reshape the same 12 values:

Choose a shape and click a cell to see its index and offset. Then try the reshapes: valid ones keep the numbers in order; invalid ones raise the real NumPy error.

Why shapes matter: (12,) is not (12, 1) is not (1, 12)

The same 12 numbers can be a flat list, a column or a row. These are three different shapes, and later (broadcasting) NumPy treats them differently. Try the three buttons above. Converting between them is a reshape, and -1 means "work this length out for me".

Predict first. You have 12 numbers. What does a.reshape(5, -1) do?

Predict first. In a feature table of shape (4, 3), what is X[:, 1]?

The common mistake: a reshape that is valid but means something else

Reshape only checks that the counts match, not that the meaning does:

>>> flat = np.arange(6)
>>> flat.reshape(-1, 3)      # 2 rows of 3 features
array([[0, 1, 2],
       [3, 4, 5]])
>>> flat.reshape(3, -1)      # 3 rows of 2 features
array([[0, 1],
       [2, 3],
       [4, 5]])
Chapter context

A tensor is a multidimensional array with a shape and element type. Many AI bugs come from doing a valid operation along the wrong axis. Write the intended dimensions before trying to shorten the code.

Chapter reference: math, worked example & code

This section belongs to the whole chapter, so it is the same on every lesson in it and may cover a different lesson's topic. The code for the experiment you just ran is inside the experiment itself.

Math and notation

For a data matrix X∈Rn×dX\in\mathbb R^{n\times d}, feature means are

μj=1n∑i=1nXij,Zij=Xij−μj.\mu_j=\frac1n\sum_{i=1}^n X_{ij},\qquad Z_{ij}=X_{ij}-\mu_j.

Here i indexes examples and j indexes features. The mean vector has d entries, so subtracting it from X broadcasts along rows.

Worked example

For X = [[1, 2], [3, 4]], the feature means are [2, 3]. Centering produces [[-1, -1], [1, 1]]. Each centered column has mean zero. Computing row means instead would answer a different question even though the operation is valid.

Reference code

The following example uses the Python standard library and does not call a remote service.

X = [[1, 2], [3, 4]]
means = [sum(row[j] for row in X) / len(X) for j in range(2)]
centered = [[x - m for x, m in zip(row, means)] for row in X]
assert means == [2, 3]
assert centered == [[-1, -1], [1, 1]]

Python examples are provided for study and local execution; this page does not execute Python.

Common mistakes

Broadcasting is a shape rule, not permission to ignore axis meanings. Vectorized code can create large intermediate arrays. Normalize training and test data with training statistics only.