Code Architecture — Highway Networks (009)
1. Goal of the notebook
Build a fully-connected Highway layer from raw PyTorch operations, stack 20+ Highway layers, and compare training/gradient behavior against an equally deep plain MLP on MNIST. The notebook produces:
- side-by-side training-curve plots,
- per-layer gradient-norm plots,
- a visualization of transform-gate activity,
- a clean, Colab-runnable, pip-install-only implementation.
2. Notebook sections
| Section | What it does |
|---|---|
| Setup | Install/update torch, torchvision, matplotlib, seaborn, tqdm (CPU is enough; GPU optional). |
| Dataset: MNIST | torchvision.datasets.MNIST, normalize, create train/val dataloaders. |
| HighwayBlock | A single Highway layer: H(x, W_H) non-linear block + T(x, W_T) sigmoid gate; output y = H * T + x * (1 - T). Bias b_T initialized to a negative value. |
| HighwayMLP | Input projection to hidden size (plain linear layer), stack N HighwayBlocks, then output linear + softmax. |
| PlainMLP | Matched architecture with the same number of layers/units but standard linear + activation blocks. |
| Training loop | Shared train_epoch/evaluate functions; tracks cross-entropy loss and accuracy; supports both models. |
| Experiment: depth = 20 | Train both networks for a small number of epochs, plot train/val loss. |
| Gradient-flow diagnostic | After a forward/backward pass, record the L2 norm of gradients per layer and visualize them as a heatmap/line plot. |
| Transform-gate inspection | For a few test samples, print mean T(x) per layer to confirm that gates learn to be selective. |
| Summary / take-aways | Highlight that the Highway network trains stably where the plain deep MLP stalls. |
3. Key functions/classes
HighwayBlock(in_features, activation='relu', gate_bias=-2)forward(x) → y- Computes
H = act(x @ W_H^T + b_H)andT = σ(x @ W_T^T + b_T); returnsH * T + x * (1 - T).
HighwayMLP(input_size, hidden_size, num_highway_layers, num_classes)- One plain input linear, N
HighwayBlocks, one output linear.
- One plain input linear, N
PlainMLP(input_size, hidden_size, num_layers, num_classes)- Standard
Linear → Activationchain for comparison.
- Standard
train_model(model, loader, optimizer, criterion) → (loss, accuracy)evaluate_model(model, loader, criterion) → (loss, accuracy)plot_curves(...)andplot_gradient_flow(...)helpers.
4. Data flow and shapes
MNIST image [1, 28, 28]
→ flatten → [batch, 784]
→ Linear(784, hidden) + ReLU → [batch, hidden]
→ HighwayBlock x N:
x: [batch, hidden]
H: [batch, hidden]
T: [batch, hidden]
y = H*T + x*(1-T): [batch, hidden]
→ Linear(hidden, 10) → logits [batch, 10]
→ CrossEntropyLoss
5. Deliberate simplifications vs. the full paper
- The paper also experiments with convolutional highway layers on CIFAR-10/100; this notebook focuses on fully-connected layers on MNIST to keep the core gating mechanism visible and the runtime short.
- The paper uses up to 900 layers and random-search hyperparameter tuning; the notebook defaults to 20 layers (enough to show the effect) with a small number of epochs.
- CIFAR-100 experiments, maxout baselines, and FitNet comparisons are omitted; only the central optimization claim is reproduced.
- We do not implement the alternative
C(x, W_C)carry gate separately; we follow the paper’s simplificationC = 1 − T.