Week 12: Modern Deep Learning & the Road to Transformers

Stat 577 — Statistical Learning Theory

Soumojit Das

Spring 2026

Session 1: The Modern Training Toolkit

Block 1: Where We Are

Where We Are

Over Weeks 9 and 11 we built the full neural network foundation:

  • Architecture: layers of learned features, nonlinear activations (ReLU), output layer encodes distributional assumption
  • Loss function: negative log-likelihood — MSE for regression, cross-entropy for classification
  • Training algorithm: SGD + backpropagation — the chain rule on a computational graph, cost \(\approx\) 2x one forward pass
  • Regularization toolkit: weight decay (ridge on weights), early stopping (shrink toward linear), He/Xavier initialization (control variance across layers)

Today we add three innovations that transformed neural networks from a research curiosity into a practical tool: a better optimizer, a normalization trick, and a regularization method that sounds crazy but works.

Block 2: Beyond Vanilla SGD

The Problem with SGD

Two fundamental limitations of vanilla SGD:

1. Oscillation in high-curvature directions. When the loss surface is much steeper in one direction than another, SGD oscillates back and forth across the steep direction while making slow progress along the shallow direction.

2. One learning rate for all parameters. Some parameters need large steps (sparse gradients, infrequent features), others need small steps (dense gradients, frequent features). Vanilla SGD uses the same \(\eta\) for everything.

Momentum

Fix for oscillation. Accumulate a running average of past gradients:

\[\mathbf{m}^{(t)} = \gamma \mathbf{m}^{(t-1)} + \eta \nabla R(\boldsymbol{\theta}^{(t)})\]

\[\boldsymbol{\theta}^{(t+1)} = \boldsymbol{\theta}^{(t)} - \mathbf{m}^{(t)}\]

Typical \(\gamma = 0.9\).

Intuition: A ball rolling downhill accumulates speed in consistent directions and dampens oscillations. Gradients that point the same way reinforce each other; gradients that flip sign cancel out.

Adam (Adaptive Moment Estimation)

The modern default optimizer. Maintains per-parameter learning rates by tracking two quantities:

First moment (mean of gradients — like momentum):

\[m_t = \beta_1 m_{t-1} + (1 - \beta_1) g_t\]

Second moment (mean of squared gradients):

\[v_t = \beta_2 v_{t-1} + (1 - \beta_2) g_t^2\]

Bias correction (since \(m_0 = v_0 = 0\), early estimates are biased toward zero):

\[\hat{m}_t = \frac{m_t}{1 - \beta_1^t}, \qquad \hat{v}_t = \frac{v_t}{1 - \beta_2^t}\]

Update:

\[\theta \leftarrow \theta - \eta \cdot \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon}\]

Defaults: \(\beta_1 = 0.9\), \(\beta_2 = 0.999\), \(\epsilon = 10^{-8}\).

Why Adam Works

Parameters with consistently large gradients get smaller effective learning rates — the denominator \(\sqrt{\hat{v}_t}\) is large.

Parameters with small, noisy gradients get larger effective learning rates — the denominator is small.

Adam adapts automatically. No manual tuning of per-layer learning rates.

Tip

Practical advice: Adam is the default. Start with lr=1e-3. SGD+momentum can sometimes find better solutions (especially for vision tasks) but requires more tuning. When in doubt, use Adam.

Learning Rate Schedules

The learning rate \(\eta\) does not have to stay constant during training.

  • Warmup: Start with a very small \(\eta\), ramp up over the first few epochs. Stabilizes early training when gradients are unreliable.
  • Cosine annealing: Smoothly decrease \(\eta\) following a cosine curve. The idea: explore broadly early on, then fine-tune.
  • Step decay: Reduce \(\eta\) by a factor (e.g., \(\times 0.1\)) at fixed intervals.

These are refinements, not essentials. Adam with a fixed lr=1e-3 is a perfectly reasonable starting point.

Block 3: Batch Normalization

The Internal Covariate Shift Problem

During training, each layer’s input distribution changes because the layers below are also updating their weights.

Layer 3 is trying to learn a mapping from its inputs (outputs of layer 2) to its targets. But those inputs keep shifting as layer 2’s weights change.

Like trying to hit a moving target.

Even if layer 3 makes progress on one minibatch, the distribution it learned from may be different on the next minibatch — not because the data changed, but because the preceding layers changed.

The BatchNorm Idea

For each minibatch, normalize the pre-activations to mean 0 and variance 1:

\[\hat{z}_j = \frac{z_j - \mu_{\mathcal{B}}}{\sqrt{\sigma_{\mathcal{B}}^2 + \epsilon}}\]

where \(\mu_{\mathcal{B}}\) and \(\sigma_{\mathcal{B}}^2\) are the mean and variance of \(z_j\) computed over the current minibatch.

Then add learnable parameters \(\gamma\) (scale) and \(\beta\) (shift):

\[\tilde{z}_j = \gamma \hat{z}_j + \beta\]

Why add \(\gamma\) and \(\beta\) back? Because forcing mean 0 / variance 1 might be too restrictive — the network should be able to choose to undo the normalization if that is what is optimal. The identity transformation (\(\gamma = \sigma_{\mathcal{B}}\), \(\beta = \mu_{\mathcal{B}}\)) is always recoverable.

Why BatchNorm Works

Important

The honest answer: The original paper (Ioffe & Szegedy, 2015) argued BatchNorm works by reducing internal covariate shift. Later work (Santurkar et al., 2018) showed this explanation is likely wrong — BatchNorm actually works by smoothing the loss landscape, making gradients more predictable and allowing larger learning rates.

The practical effects are clear even if the theory is unsettled:

  • Allows much higher learning rates \(\to\) faster training
  • Reduces sensitivity to initialization (remember our Xavier/He discussion?)
  • Acts as a mild regularizer (the minibatch statistics add noise)

BatchNorm in Practice

Where to place it? Before activation (original paper) or after? Both work. No definitive answer.

During inference: No minibatch at test time. Use running averages of \(\mu\) and \(\sigma^2\) computed during training.

In PyTorch: nn.BatchNorm1d(num_features) — one line.

Code: BatchNorm comparison on make_moons
import torch
import torch.nn as nn
from sklearn.datasets import make_moons

# Generate data
X, y = make_moons(n_samples=1000, noise=0.25, random_state=42)
X_t = torch.tensor(X, dtype=torch.float32)
y_t = torch.tensor(y, dtype=torch.float32).unsqueeze(1)

# Model WITHOUT BatchNorm
class PlainMLP(nn.Module):
    def __init__(self):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(2, 64), nn.ReLU(),
            nn.Linear(64, 64), nn.ReLU(),
            nn.Linear(64, 64), nn.ReLU(),
            nn.Linear(64, 1), nn.Sigmoid()
        )
    def forward(self, x):
        return self.net(x)

# Model WITH BatchNorm
class BNormMLP(nn.Module):
    def __init__(self):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(2, 64), nn.BatchNorm1d(64), nn.ReLU(),
            nn.Linear(64, 64), nn.BatchNorm1d(64), nn.ReLU(),
            nn.Linear(64, 64), nn.BatchNorm1d(64), nn.ReLU(),
            nn.Linear(64, 1), nn.Sigmoid()
        )
    def forward(self, x):
        return self.net(x)

# Train both and record loss curves
def train(model, X_t, y_t, epochs=200, lr=0.01):
    opt = torch.optim.Adam(model.parameters(), lr=lr)
    loss_fn = nn.BCELoss()
    losses = []
    for _ in range(epochs):
        pred = model(X_t)
        loss = loss_fn(pred, y_t)
        opt.zero_grad(); loss.backward(); opt.step()
        losses.append(loss.item())
    return losses

torch.manual_seed(42)
plain = PlainMLP(); losses_plain = train(plain, X_t, y_t)
torch.manual_seed(42)
bnorm = BNormMLP(); losses_bnorm = train(bnorm, X_t, y_t)

# Plot
fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(losses_plain, color="#D62828", label="Without BatchNorm", linewidth=2)
ax.plot(losses_bnorm, color="#06A77D", label="With BatchNorm", linewidth=2)
ax.set_xlabel("Epoch"); ax.set_ylabel("BCE Loss")
ax.set_title("Effect of Batch Normalization on Training")
ax.legend(); ax.set_ylim(0, 0.8)
plt.tight_layout()
plt.savefig("../figures/week12/03_batchnorm_effect.png", dpi=200, bbox_inches="tight")
plt.show()

Block 4: Dropout

The Co-adaptation Problem

Neurons can become overly dependent on each other — “neuron A only works when neuron B is active.”

This creates fragile representations. The network learns a solution that relies on specific combinations of neurons rather than robust individual features.

Dropout breaks co-adaptation by force.

Dropout Mechanism

During training: Randomly set each neuron’s output to zero with probability \(p\).

  • Typical \(p = 0.5\) for hidden layers, \(p = 0.2\) for the input layer

During testing: Use all neurons. But their outputs are now \(p\) times too large (since during training only a fraction \(1 - p\) were active on average).

Two equivalent fixes:

  1. Scale outputs by \((1 - p)\) at test time
  2. Inverted dropout (standard): scale by \(\frac{1}{1-p}\) during training, do nothing at test time

The Ensemble Interpretation

Important

Key insight (course connection): A network with \(n\) neurons and dropout is implicitly training \(2^n\) different subnetworks (one for each dropout pattern) that share weights. At test time, you average over all subnetworks.

This is bagging (Week 7) applied at the neuron level — same variance-reduction principle, different mechanism.

The Modern Training Recipe

Tip

The Modern Training Recipe

  1. Optimizer: Adam with lr=1e-3 (default starting point)
  2. Normalization: BatchNorm after each hidden layer
  3. Regularization: Dropout (\(p = 0.2\)–\(0.5\)) + weight decay (\(\lambda \sim 10^{-4}\)) + early stopping
  4. Activation: ReLU (from Week 11)
  5. Initialization: He/Kaiming (from Week 11)

These five choices, combined with the foundations from Weeks 9 & 11, are enough to train competitive deep networks on most problems.

Session 2: From Spatial to Sequential

Block 5: CNNs in 15 Minutes

Preview — Obrey will go much deeper next week.

The Key Idea

Fully connected networks treat every input pixel as independent. For a \(256 \times 256\) image, that is 65,536 input units, each connected to every neuron in the first hidden layer.

This ignores the fact that images have spatial structure. CNNs exploit two properties:

  1. Local patterns matter: Edges, textures, and shapes are detected by small local regions, not by looking at the entire image at once.
  1. The same pattern can appear anywhere: A horizontal edge in the top-left corner looks the same as a horizontal edge in the bottom-right. The same detector should work everywhere.

Convolution = Local + Shared Weights

A small filter (e.g., \(3 \times 3\)) slides across the image. At each position, it computes a dot product between the filter weights and the local image patch.

Same weights everywhere — weight sharing — so a pattern detector learned in one location works in all locations.

Dramatically reduces parameters: a \(3 \times 3\) filter has 9 parameters regardless of image size.

The CNN Pipeline

\[\text{Input} \to \underbrace{\text{Conv} \to \text{ReLU} \to \text{Pool}}_{\text{repeat}} \to \text{Flatten} \to \text{FC} \to \text{Output}\]

  • Convolution detects local patterns with shared weights
  • ReLU introduces nonlinearity (same activation from Week 11)
  • Pooling (max or average over small regions) provides translation invariance and reduces spatial dimensions

The result: early layers detect edges, middle layers textures and parts, late layers objects and concepts — the hierarchical feature learning we discussed in Week 11, now with architectural structure.

Why CNNs Changed Everything

In 2012, AlexNet (Krizhevsky, Sutskever, Hinton) won the ImageNet Large Scale Visual Recognition Challenge. The error rate dropped from 26% to 16% — more than 10 percentage points in a single year.

This was the moment the deep learning revolution started. Every subsequent year, the winning architecture was a deeper CNN.

Note

Obrey presents the full CNN story — LeNet to AlexNet — on Monday of Week 13. Wooyoung follows on Wednesday with residual networks.

Block 6: The Sequence Problem

What CNNs Cannot Do

CNNs assume fixed-size input with spatial structure. But many problems involve sequences of variable length where order matters:

  • Text: “The cat sat on the mat” \(\neq\) “The mat sat on the cat”
  • Speech: variable-length audio signals
  • Time series: stock prices, climate data, sensor readings
  • Biological sequences: DNA, protein structures

For all of these, the position of each element in the sequence carries information. We need architectures that respect sequential structure.

The RNN Idea

Process one element at a time, maintaining a hidden state \(\mathbf{h}_t\) that summarizes everything seen so far:

\[\mathbf{h}_t = \sigma(\mathbf{W}_h \mathbf{h}_{t-1} + \mathbf{W}_x \mathbf{x}_t + \mathbf{b})\]

At each time step \(t\): combine the previous hidden state \(\mathbf{h}_{t-1}\) (memory) with the current input \(\mathbf{x}_t\) (new information).

The same weights \(\mathbf{W}_h\) and \(\mathbf{W}_x\) are used at every time step — weight sharing across time, just as CNNs share weights across space.

Note

Jackie presents the full RNN/LSTM story — including Hochreiter & Schmidhuber’s solution to the vanishing gradient problem in sequences — on Monday of Week 14.

The Bottleneck

In the standard encoder-decoder architecture, the encoder processes the entire input sequence and compresses it into a single fixed-length vector \(\mathbf{h}_T\):

\[\underbrace{x_1, x_2, \ldots, x_T}_{\text{input sequence}} \;\xrightarrow{\text{encoder}}\; \mathbf{h}_T \;\xrightarrow{\text{decoder}}\; \underbrace{y_1, y_2, \ldots, y_{T'}}_{\text{output sequence}}\]

The decoder must reconstruct the entire output from this one vector.

Imagine summarizing a 500-word paragraph into a single number. That is what the encoder-decoder bottleneck asks the network to do.

For short sequences, this works. For long sequences, too much information is lost. This is the problem attention solves.

Block 7: The Attention Idea

What If the Decoder Could Look Back?

Bahdanau, Cho & Bengio (2015). Instead of compressing everything into one vector, let the decoder attend to all encoder hidden states at every decoding step.

When translating “le chat est sur le tapis” and generating the word “cat,” the decoder should focus on “chat.”

When generating “mat,” it should focus on “tapis.”

The decoder dynamically decides where to look in the input, depending on what it is currently generating.

Attention as Soft Retrieval

Three steps:

1. Score: How relevant is each encoder state \(\mathbf{h}_j\) to the current decoder state \(\mathbf{s}_t\)?

\[e_{tj} = \text{score}(\mathbf{s}_t, \mathbf{h}_j)\]

2. Normalize: Softmax converts scores to weights that sum to 1:

\[\alpha_{tj} = \text{softmax}_j(e_{tj}) = \frac{\exp(e_{tj})}{\sum_{j'} \exp(e_{tj'})}\]

3. Aggregate: Context vector is a weighted average of all encoder states:

\[\mathbf{c}_t = \sum_j \alpha_{tj} \mathbf{h}_j\]

A soft lookup — instead of selecting one encoder state (hard attention), we blend all of them with learned, context-dependent weights.

The QKV Abstraction

Vaswani et al. (2017) generalized the attention mechanism into three roles:

  • Query (Q): “What am I looking for?” — the decoder state asking a question
  • Key (K): “What do I contain?” — encoder states, used for matching against the query
  • Value (V): “What information do I carry?” — encoder states, used for the output

Tip

Analogy: Think of a library. The query is your search term. The keys are the book titles. The values are the book contents. You match your search term against titles (query-key), get relevance scores, and blend the contents (values) accordingly.

Looking Ahead

On Friday, we formalize all of this — the exact equation, why it is scaled, and what happens when Q, K, and V all come from the same sequence (self-attention).

In Week 15, we build the full transformer architecture.

Session 3: Self-Attention Mechanics

Where We Left Off

Wednesday we motivated attention — the encoder-decoder bottleneck problem and the QKV abstraction:

  • Query: “What am I looking for?”
  • Key: “What do I contain?” (for matching)
  • Value: “What information do I carry?” (for output)

Today we formalize the exact equation, explain the \(\sqrt{d_k}\) scaling, and see what happens when Q, K, and V all come from the same sequence.

Block 8: Scaled Dot-Product Attention

The Equation

The core computation of modern attention (Vaswani et al., 2017):

\[\text{Attention}(Q, K, V) = \text{softmax}\!\left(\frac{QK^T}{\sqrt{d_k}}\right)V\]

Let’s unpack this piece by piece.

Unpacking the Attention Equation

Step 1: \(QK^T\) — a matrix of dot products between every query and every key.

Entry \((i, j) = \mathbf{q}_i^T \mathbf{k}_j\) = how much query \(i\) matches key \(j\).

Step 2: \(\div \sqrt{d_k}\) — scaling factor. Why? (next slide)

Step 3: softmax — normalize each row to sum to 1. Each row corresponds to one query — it distributes its attention across all keys, so each row sums to 1.

Step 4: \(\times V\) — weighted combination of values. Each query’s output is a weighted average of all value vectors, where the weights come from step 3.

The entire operation: matrix multiply \(\to\) scale \(\to\) normalize \(\to\) aggregate.

Why Scale by \(\sqrt{d_k}\)?

Important

Connection to initialization (Week 11): If query and key vectors have entries with variance 1, their dot product has variance \(d_k\) (sum of \(d_k\) products of independent terms — the same calculation as our Xavier initialization argument!).

For large \(d_k\), dot products become large, pushing softmax into saturation where gradients vanish.

Dividing by \(\sqrt{d_k}\) restores unit variance. Same principle as He/Xavier initialization — control the variance to keep gradients healthy.

Worked Example

\(d_k = 4\), three positions. Small concrete numbers:

\[Q = \begin{bmatrix} 1 & 0 & 1 & 0 \\ 0 & 1 & 0 & 1 \\ 1 & 1 & 0 & 0 \end{bmatrix}, \quad K = \begin{bmatrix} 1 & 1 & 0 & 0 \\ 0 & 0 & 1 & 1 \\ 1 & 0 & 1 & 0 \end{bmatrix}, \quad V = \begin{bmatrix} 1 & 0 \\ 0 & 1 \\ 0.5 & 0.5 \end{bmatrix}\]

Step 1: \(QK^T = \begin{bmatrix} 1 & 1 & 2 \\ 1 & 1 & 0 \\ 2 & 0 & 1 \end{bmatrix}\)

Step 2: Scale by \(\sqrt{4} = 2\): \(\frac{QK^T}{\sqrt{d_k}} = \begin{bmatrix} 0.5 & 0.5 & 1.0 \\ 0.5 & 0.5 & 0.0 \\ 1.0 & 0.0 & 0.5 \end{bmatrix}\)

Step 3: Softmax each row: \(\approx \begin{bmatrix} 0.27 & 0.27 & 0.45 \\ 0.38 & 0.38 & 0.23 \\ 0.51 & 0.19 & 0.31 \end{bmatrix}\)

Worked Example (continued)

Step 4: Multiply by \(V\):

\[\text{Output} = \text{softmax}\!\left(\frac{QK^T}{\sqrt{d_k}}\right) V \approx \begin{bmatrix} 0.50 & 0.50 \\ 0.50 & 0.50 \\ 0.66 & 0.34 \end{bmatrix}\]

Each row is a weighted average of the value vectors.

  • Query 1 attended most to position 3 (weight 0.45), so its output blends toward \(V_3 = [0.5, 0.5]\).
  • Query 2 attended equally to positions 1 and 2 (weights 0.38 each), producing an even blend.
  • Query 3 attended most to position 1 (weight 0.51), pulling its output toward \(V_1 = [1, 0]\).

The point: this is matrix multiplication \(\to\) normalize \(\to\) weighted average. Nothing mysterious.

Block 9: Self-Attention

When Q, K, V Come from the Same Sequence

In cross-attention (Bahdanau), queries come from the decoder, keys and values from the encoder.

In self-attention, Q, K, V are all derived from the same input sequence \(\mathbf{X}\):

\[Q = \mathbf{X}W^Q, \qquad K = \mathbf{X}W^K, \qquad V = \mathbf{X}W^V\]

where \(W^Q, W^K, W^V\) are learned projection matrices.

Every position attends to every other position in the same sequence. Each token asks: “what other tokens in this sentence are relevant to me?”

What Self-Attention Captures

Consider the sentence: “The animal didn’t cross the street because it was too tired.”

When processing “it,” self-attention attends strongly to “animal” — resolving the pronoun.

This requires looking far back in the sequence — something RNNs struggle with due to vanishing gradients.

Self-attention gives every position a direct connection to every other position. No bottleneck, no sequential processing.

Self-Attention vs. Everything Else

Property Fully Connected CNN RNN Self-Attention
Connectivity all-to-all local sequential all-to-all
Weight sharing none spatial temporal via Q, K, V projections
Variable length no with tricks yes yes
Long-range deps limited by depth limited by kernel vanishing gradients direct
Parallelizable yes yes no yes

The Computational Cost

Self-attention computes a score for every pair of positions: \(O(n^2 d)\) time, \(O(n^2)\) memory.

Sequence length \(n\) Number of pairwise scores
100 10,000
1,000 1,000,000
10,000 100,000,000
100,000 10,000,000,000

This quadratic cost is the main limitation of self-attention — and an active research area (linear attention, sparse attention, FlashAttention).

Attention Demo: From Scratch

Code: Scaled dot-product attention in ~10 lines
import numpy as np

def scaled_dot_product_attention(Q, K, V):
    """Scaled dot-product attention (Vaswani et al., 2017)."""
    d_k = Q.shape[-1]
    scores = Q @ K.T / np.sqrt(d_k)          # (n_queries, n_keys)
    scores = scores - scores.max(axis=-1, keepdims=True)  # numerical stability
    weights = np.exp(scores) / np.exp(scores).sum(axis=-1, keepdims=True)  # softmax
    return weights @ V, weights               # (n_queries, d_v), (n_queries, n_keys)

# Small example: 4 tokens, d_k = d_v = 3
np.random.seed(42)
X = np.random.randn(4, 3)                    # 4 tokens, embedding dim 3
W_Q = np.random.randn(3, 3) * 0.5
W_K = np.random.randn(3, 3) * 0.5
W_V = np.random.randn(3, 3) * 0.5

Q, K, V = X @ W_Q, X @ W_K, X @ W_V
output, attn_weights = scaled_dot_product_attention(Q, K, V)

# Visualize attention weights
fig, ax = plt.subplots(figsize=(6, 5))
tokens = ["The", "cat", "sat", "down"]
im = ax.imshow(attn_weights, cmap="Blues", vmin=0, vmax=1)
ax.set_xticks(range(4)); ax.set_xticklabels(tokens)
ax.set_yticks(range(4)); ax.set_yticklabels(tokens)
ax.set_xlabel("Key (attending to)"); ax.set_ylabel("Query (attending from)")
ax.set_title("Self-Attention Weights")
for i in range(4):
    for j in range(4):
        ax.text(j, i, f"{attn_weights[i,j]:.2f}", ha="center", va="center",
                color="white" if attn_weights[i,j] > 0.5 else "black", fontsize=12)
plt.colorbar(im, ax=ax, label="Attention Weight")
plt.tight_layout()
plt.savefig("../figures/week12/09_attention_demo.png", dpi=200, bbox_inches="tight")
plt.show()

Note: These are random, untrained weights — the attention pattern is meaningless. In a trained model, the weights would reflect learned relationships between tokens.

Block 10: Preview of Multi-Head Attention

One Head Is Not Enough

A single attention head learns one notion of “relevance.” But relevance is multifaceted:

  • Syntactic: subject-verb agreement (“The dogs … are”)
  • Semantic: coreference resolution (“The animal … it”)
  • Positional: nearby context words

Multi-head attention runs \(h\) attention operations in parallel, each with its own learned projections \(W^Q_i, W^K_i, W^V_i\), then concatenates:

\[\text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, \ldots, \text{head}_h)\, W^O\]

Think of multiple “experts,” each attending to different aspects of the input.

We will build this out fully in Week 15.

Block 11: Summary and Bridge

What You Now Know

Important

Week 12 Takeaways:

  1. Adam adapts learning rates per parameter — the default optimizer.
  2. Batch normalization smooths the loss landscape and stabilizes training.
  3. Dropout is implicit ensembling — trains \(2^n\) subnetworks that share weights.
  4. CNNs exploit spatial structure via local filters + weight sharing.
  5. Attention solves the sequence bottleneck by letting the model look back at all positions.
  6. Self-attention applies the same idea within a single sequence — every position attends to every other. Cost is \(O(n^2 d)\).

Connection Map

Week 11 Connections

  • The \(\sqrt{d_k}\) scaling is the same variance argument as Xavier/He initialization

  • BatchNorm reduces sensitivity to initialization — same problem, different solution

  • Dropout’s ensemble interpretation connects to bagging (Weeks 7–8)

What’s Coming

  • Weeks 13–14: Your classmates go deep on CNNs (Obrey), ResNets (Wooyoung), double descent (Alex), RNNs/LSTMs (Jackie), transfer learning (Garrett), and scaling laws (Ephraim)

  • Week 15: We build the full transformer architecture