XOR was the smallest witness that linear models fail. Here is a harder one: two interleaved spirals, with no straight line anywhere close to separating them. We train the network from the reading, writing our own forward and backward pass, and watch the decision region bend to match.
import numpy as npimport matplotlib.pyplot as pltimport scienceplotsfrom matplotlib.colors import LinearSegmentedColormapplt.style.use(["science", "no-latex"])TEAL, CARDINAL ="#009090", "#9c1b33"FIELD = LinearSegmentedColormap.from_list("field", ["#ffffff", "#7a7a7a"]) # background shadingrng = np.random.default_rng(11)n_per_class, noise =150, 0.15X, y = [], []for c in [0, 1]: r = np.linspace(0.15, 1.0, n_per_class) t = np.linspace(c * np.pi, c * np.pi +3.0* np.pi, n_per_class) + rng.normal(0, noise, n_per_class) X.append(np.column_stack([r * np.sin(t), r * np.cos(t)])) y.append(np.full(n_per_class, c))X, y = np.vstack(X), np.concatenate(y)fig, ax = plt.subplots(figsize=(7, 7))ax.scatter(*X[y ==0].T, color=CARDINAL, s=14, label="Class 0")ax.scatter(*X[y ==1].T, color=TEAL, s=14, marker="^", label="Class 1")ax.set_xlabel("$x_1$")ax.set_ylabel("$x_2$")ax.legend(frameon=False)plt.show()
Before adding anything new, run last lecture’s model on it: one linear score per class, softmax on top, cross-entropy loss, trained with the softmax - one_hot gradient we derived at the board. How far does a straight boundary get?
def softmax(Z): Z = Z - Z.max(axis=1, keepdims=True) E = np.exp(Z)return E / E.sum(axis=1, keepdims=True)Y = np.zeros((len(y), 2)) # one-hot labelsY[np.arange(len(y)), y] =1rng_linear = np.random.default_rng(1)W = rng_linear.normal(0, 0.1, size=(2, 2))b = np.zeros(2)for epoch inrange(4000): P = softmax(X @ W + b) dZ = (P - Y) /len(X) W -=1.0* (X.T @ dZ) b -=1.0* dZ.sum(0)linear_accuracy = np.mean(softmax(X @ W + b)[:, 1].round() == y)print(f"linear model, training accuracy: {linear_accuracy:.1%}")
linear model, training accuracy: 66.3%
Now insert one hidden layer of ReLU neurons between the input and the logits. The backward pass is the reading’s, line for line: softmax minus one-hot at the top, an outer product for each weight gradient, and the ReLU mask on the way down.
Punchline: the reading’s backpropagation equations, with nothing changed but the shapes of the matrices, bend a decision boundary all the way around a spiral: \(322\) parameters and \(100\%\) training accuracy where a straight line manages \(66\%\). Four hidden neurons run out of creases long before that and land exactly on the linear model’s accuracy, so it is the width doing the work rather than the training time. Next lecture asks how to train a network like this one when the dataset is far too large to compute a full gradient over all of it at once.