Foundations: Python, Git and toolsLoading progress…

Indexing and views

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

Two arrays, one block of memory

Copying a big array is slow and uses memory, so NumPy avoids it when it can. A slice such as a[:, 1:3] does not copy: it creates a new array object that looks at the same memory with different bounds. That is a view. Write into the view and you write into the original.

Basic indexing (integers, slices, :, steps) gives views. Advanced indexing (a list of positions, or a boolean mask) must gather scattered cells into a fresh array, so it gives a copy. Transpose and, on contiguous data, reshape are also views.

b = a[:, 1:3]

a (the original)
0
1
2
3
4
5
6
7
8
9
10
11
b, shape (3, 2)
1
2
5
6
9
10
b is a view: it reads the same memory as a (np.shares_memory(a, b) is True). A slice of columns. Basic slicing, so it is a view.
Pick an expression, then run b[0] = 99. Blue cells are the cells b was built from. Watch which cells of the original a really change, with and without .copy().

Writing through an index is different from reading with one

A fancy index on the left of an assignment writes into the original: a[a > 6] = 0 zeroes those cells of a itself. The same index on the right(b = a[a > 6]) builds a copy, and changing b afterwards never reaches a.

Predict first. With a = np.arange(12).reshape(3, 4), you run b = a[a > 6] and then b[0] = 99. How many cells of a change?

The common mistake: an in-place edit on a slice you did not mean to share

>>> x = np.array([[1, 2], [3, 4]])
>>> y = x[:, 0]          # first column, a view
>>> y *= 2
>>> x
array([[2, 2],
       [6, 4]])           # x changed, although we only 'used' y

>>> z = x[:, 0].copy()   # an independent copy
>>> z *= 2               # x is untouched

And plain assignment copies nothing at all: b = a just gives the same array a second name.

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.