Foundations: Python, Git and toolsLoading progress…

Broadcasting

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

Combining arrays of different shapes

Adding a table to a vector looks wrong at first: how do 6 numbers and 3 numbers add up? Broadcasting is the rule that answers it. NumPy compares the two shapes from the right. Two lengths are compatible if they are equal or one of them is 1. A missing leading axis counts as 1. A length 1 is stretched (conceptually repeated) to match the other.

>>> X = np.array([[1, 2, 3], [4, 5, 6]])     # shape (2, 3)
>>> b = np.array([10, 20, 30])                # shape (3,)
>>> X + b
array([[11, 22, 33],
       [14, 25, 36]])
A
B
axis (from the right)ABverdict
last33equal: fine
last - 12·B has no axis: treated as 1
A.shape (2, 3) + B.shape (3,) -> result shape (2, 3)
A stretched (dashed = copied)
1
2
3
4
5
6
B stretched (dashed = copied)
10
20
30
10
20
30
A + B
11
22
33
14
25
36

Cell [0, 0]: 1 + 10 = 11. A is filled with 1, 2, 3, ... and B with 10, 20, 30, ... NumPy does not really build the dashed copies; it reuses the same values, which is why broadcasting is cheap.

Choose two shapes. The table compares the axes from the right; the grids stretch the smaller array across the larger one; drag the slider to follow one result cell at a time.

Check yourself first

Predict first. What is the shape of the result of np.ones((3, 1)) + np.ones((1, 4))?

Predict first. Can (2, 3) and (2,) be added?

The common mistake: right shape rule, wrong axis meaning

Centering a table means subtracting each column mean. If you reduce along the wrong axis you either get an error or, worse, a quietly wrong answer on a square table:

>>> X = np.array([[1., 2., 3.], [4., 5., 6.]])
>>> X - X.mean(axis=1)
ValueError: operands could not be broadcast together with shapes (2,3) (2,)

>>> X - X.mean(axis=1, keepdims=True)    # shape (2,1): subtracts each ROW mean
array([[-1.,  0.,  1.],
       [-1.,  0.,  1.]])

>>> X - X.mean(axis=0)                   # shape (3,): subtracts each COLUMN mean
array([[-1.5, -1.5, -1.5],
       [ 1.5,  1.5,  1.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.