Home/Machine Learning/Deep Learning Theory
Back
๐Ÿ”ฌ

Research Scientist

Deep Learning Theory

Research Scientist interviews probe deep theoretical understanding โ€” not just what works but why. You must derive backpropagation from first principles, explain initialization theory, understand the failure modes of normalization schemes, and engage with open research questions like double descent and the neural tangent kernel.

Linear algebraMultivariable calculusProbability theoryPython/NumPyBackpropInitializationNormalizationUniversal ApproximationDouble DescentAttention Theory

Core Theory

  • 1Backpropagation derivation: the chain rule applied to a computational graph. For a composed function f(g(x)), df/dx = (df/dg)(dg/dx). In a neural network, we compute gradients by propagating the upstream gradient backward through each operation. For linear layer y=Wx+b with upstream gradient ฮด=dL/dy: dL/dW = ฮด^T x (outer product), dL/dx = W^T ฮด, dL/db = ฮด. The backward pass is O(same) as the forward pass in FLOPs.
  • 2Initialization theory: the goal is to start with weights such that the signal neither vanishes nor explodes through many layers. Xavier/Glorot initialization: Var(W) = 2/(fan_in + fan_out). Derived by requiring Var(output) = Var(input) for a linear activation. He initialization: Var(W) = 2/fan_in. Derived for ReLU (which zeros out half the activations on average, halving the effective fan_in). Bad initialization โ†’ vanishing gradients (weights too small) or exploding activations (weights too large) โ†’ slow or failed training.
  • 3Universal Approximation Theorem: a single hidden layer neural network with sufficient width can approximate any continuous function on a compact set to arbitrary accuracy (Cybenko 1989 for sigmoid, Hornik 1991 for general activations). What it does NOT say: (1) how wide you need (can be exponential), (2) that you can find these weights by gradient descent, (3) that it will generalize. The theorem is about expressiveness, not learnability or generalization.
  • 4Vanishing/exploding gradients in deep networks: in a deep network, gradients are products of many Jacobians. If ||W_i|| < 1 for each layer, gradients vanish exponentially with depth. If ||W_i|| > 1, they explode. ReLU helps (gradient is 1 or 0, not < 1). Residual connections (ResNets) fix this by providing a gradient highway: dL/dx = dL/d(x + F(x)) = dL/dx + dL/dF(x). The identity path ensures gradient magnitude never drops below 1.
  • 5BatchNorm derivation and training vs. inference: forward: BN(x) = (x - ฮผ_B) / โˆš(ฯƒยฒ_B + ฮต) ร— ฮณ + ฮฒ, where ฮผ_B and ฯƒยฒ_B are computed over the batch. Backward: the gradient must account for the fact that ฮผ_B and ฯƒยฒ_B depend on x. During inference: use exponential moving averages of ฮผ and ฯƒยฒ from training (the 'running statistics'). This different behavior between train and eval is the source of many production bugs.
  • 6Double descent phenomenon: classical bias-variance predicts a U-shaped test error as model size increases (too simple = underfitting, too complex = overfitting). Double descent shows a second descent for very large models: test error peaks at the interpolation threshold (where the model exactly fits training data) then decreases again in the overparameterized regime. This explains why making neural networks larger often improves generalization even without regularization.
  • 7Neural Tangent Kernel (NTK): in the infinite-width limit, a neural network trained with gradient descent behaves like kernel regression with a fixed kernel (the NTK). This provides theoretical understanding of why neural networks generalize and why they can be trained with simple gradient descent. Practical implication: wide networks are more linear and easier to train, narrow networks are more nonlinear but harder to optimize. The NTK theory is an active research area explaining neural network behavior.
  • 8Pre-norm vs. post-norm in transformers: pre-norm (LN before attention/FFN, residual around the whole block) vs. post-norm (LN after the residual addition). Empirically, pre-norm trains more stably for deep transformers because gradients flow through the residual connection without passing through the LN operation, which can distort gradient magnitudes. GPT-2, GPT-3, LLaMA all use pre-norm. The original Transformer paper used post-norm.

Key Formulas

01Linear layer backprop: โˆ‚L/โˆ‚W=ฮดTx\partial L/\partial W = \delta^T x, โˆ‚L/โˆ‚x=WTฮด\partial L/\partial x = W^T \delta
02Xavier init variance: Var(W)=2/(fanin+fanout)Var(W) = 2/(fan_{in} + fan_{out})
03He init variance: Var(W)=2/faninVar(W) = 2/fan_{in} (for ReLU)
04BatchNorm: x^=(xโˆ’ฮผB)/ฯƒB2+ฯต\hat{x} = (x - \mu_B) / \sqrt{\sigma^2_B + \epsilon}, output =ฮณx^+ฮฒ= \gamma\hat{x} + \beta
05ResNet gradient: โˆ‚L/โˆ‚x=โˆ‚L/โˆ‚(x+F(x))โ‰ฅโˆ‚L/โˆ‚F(x)\partial L / \partial x = \partial L / \partial (x + F(x)) \geq \partial L / \partial F(x)
06Cross-entropy + softmax gradient: โˆ‚L/โˆ‚z=y^โˆ’y\partial L/\partial z = \hat{y} - y
python
1import numpy as np
2
3np.random.seed(42)
4
5class MLP:
6 """
7 3-layer MLP with backprop implemented from scratch.
8 Architecture: Input โ†’ Linear โ†’ ReLU โ†’ Linear โ†’ ReLU โ†’ Linear โ†’ Softmax
9 Loss: Cross-entropy
10 """
11 def __init__(self, d_in: int, d_hid: int, d_out: int):
12 # He initialization for ReLU layers
13 self.W1 = np.random.randn(d_in, d_hid) * np.sqrt(2.0 / d_in)
14 self.W2 = np.random.randn(d_hid, d_hid) * np.sqrt(2.0 / d_hid)
15 self.W3 = np.random.randn(d_hid, d_out) * np.sqrt(2.0 / d_hid)
16 self.b1 = np.zeros(d_hid)
17 self.b2 = np.zeros(d_hid)
18 self.b3 = np.zeros(d_out)
19
20 def relu(self, x): return np.maximum(0, x)
21 def d_relu(self, x): return (x > 0).astype(float) # ReLU gradient
22
23 def softmax(self, x):
24 e = np.exp(x - x.max(axis=1, keepdims=True)) # numerically stable
25 return e / e.sum(axis=1, keepdims=True)
26
27 def forward(self, X):
28 # Layer 1
29 self.z1 = X @ self.W1 + self.b1
30 self.a1 = self.relu(self.z1)
31 # Layer 2
32 self.z2 = self.a1 @ self.W2 + self.b2
33 self.a2 = self.relu(self.z2)
34 # Output layer
35 self.z3 = self.a2 @ self.W3 + self.b3
36 self.probs = self.softmax(self.z3)
37 return self.probs
38
39 def loss(self, probs, y):
40 # Cross-entropy: -1/n * ฮฃ log p(correct class)
41 n = y.shape[0]
42 return -np.log(probs[np.arange(n), y] + 1e-8).mean()
43
44 def backward(self, X, y):
45 n = X.shape[0]
46
47 # --- Output layer gradient ---
48 # Softmax + cross-entropy gradient: dL/dz3 = (probs - one_hot(y)) / n
49 delta3 = self.probs.copy()
50 delta3[np.arange(n), y] -= 1
51 delta3 /= n # (n, d_out)
52
53 # --- Layer 3 weights ---
54 dW3 = self.a2.T @ delta3 # (d_hid, d_out)
55 db3 = delta3.sum(axis=0)
56
57 # --- Propagate through Layer 2 ---
58 delta2 = delta3 @ self.W3.T * self.d_relu(self.z2) # (n, d_hid)
59 dW2 = self.a1.T @ delta2
60 db2 = delta2.sum(axis=0)
61
62 # --- Propagate through Layer 1 ---
63 delta1 = delta2 @ self.W2.T * self.d_relu(self.z1) # (n, d_hid)
64 dW1 = X.T @ delta1
65 db1 = delta1.sum(axis=0)
66
67 return {"dW1": dW1, "dW2": dW2, "dW3": dW3,
68 "db1": db1, "db2": db2, "db3": db3}
69
70# โ”€โ”€โ”€ Training โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
71X = np.random.randn(200, 10)
72y = np.random.randint(0, 5, 200)
73
74model = MLP(d_in=10, d_hid=64, d_out=5)
75lr = 0.01
76
77for epoch in range(500):
78 probs = model.forward(X)
79 loss = model.loss(probs, y)
80 grads = model.backward(X, y)
81
82 # SGD update
83 for param, grad in [('W1', 'dW1'), ('W2', 'dW2'), ('W3', 'dW3'),
84 ('b1', 'db1'), ('b2', 'db2'), ('b3', 'db3')]:
85 setattr(model, param, getattr(model, param) - lr * grads[grad])
86
87 if (epoch + 1) % 100 == 0:
88 acc = (probs.argmax(axis=1) == y).mean()
89 print(f"Epoch {epoch+1:4d}: loss={loss:.4f}, acc={acc:.3f}")

Complete backpropagation implementation from scratch. Key details: (1) He initialization (โˆš(2/fan_in)) for ReLU layers โ€” ensures variance is preserved through many layers; (2) numerically stable softmax (subtract max before exp to prevent overflow); (3) the beautiful simplification: cross-entropy + softmax gradient = (probs - one_hot(y))/n; (4) ReLU backward pass: multiply upstream gradient by indicator (x > 0); (5) chain rule applied sequentially from output layer to input.

Worked Interview Problems

3 problems

Problem

Given logits z โˆˆ R^C and one-hot target y, derive โˆ‚L/โˆ‚z where L = -log(softmax(z)_y). Show that it simplifies to ลท - y.

Solution

1

Softmax: ลท_c = exp(z_c) / S where S = ฮฃ_j exp(z_j). Cross-entropy: L = -log ลท_y = -(z_y - log S) where y is the correct class.

2

โˆ‚L/โˆ‚z_c for the correct class: โˆ‚L/โˆ‚z_y = -1 + exp(z_y)/S = ลท_y - 1.

3

โˆ‚L/โˆ‚z_c for other classes (c โ‰  y): โˆ‚L/โˆ‚z_c = -(โˆ‚log S/โˆ‚z_c) = -(exp(z_c)/S) = -ลท_c. But L = -log ลท_y so โˆ‚L/โˆ‚z_c = ลท_c.

4

Combining: โˆ‚L/โˆ‚z_c = ลท_c - y_c where y_c = 1 if c = correct class, else 0.

5

Vectorized: โˆ‚L/โˆ‚z = ลท - y. This elegant form means: for the correct class, gradient = ลท_y - 1 (negative, pulls logit down if ลท_y < 1). For wrong classes, gradient = ลท_c (positive, pushes logit down).

Answer

โˆ‚L/โˆ‚z=y^โˆ’y\partial L / \partial z = \hat{y} - y. The gradient is simply the difference between predicted probabilities and the one-hot target. This beautiful simplification is why softmax + cross-entropy is the universal classification loss.

Common Mistakes

!

Saying 'the gradient of ReLU is 0 everywhere' โ€” it's 0 for negative inputs, 1 for positive inputs. The derivative at 0 is undefined (usually set to 0 in implementations). The 'dying ReLU' problem is when neurons get stuck in the all-negative regime permanently, receiving only 0 gradients.

!

Confusing Xavier and He initialization. Xavier: for tanh/sigmoid activations, Var = 2/(fan_in + fan_out). He: for ReLU, Var = 2/fan_in (larger because ReLU zeros half the activations on average, reducing the effective signal by half, so you need 2ร— larger weights to compensate).

!

Not understanding BatchNorm's train/eval difference. During training, BN uses batch statistics (ฮผ_B, ฯƒ_B). During eval, it uses running averages accumulated during training. Setting model.eval() in PyTorch is not optional โ€” it switches BN to eval mode. Forgetting this is a common production bug.

!

Claiming Universal Approximation Theorem means neural networks are guaranteed to generalize. The UAT only says a solution exists that fits the data โ€” it says nothing about whether gradient descent finds it, how wide the network needs to be, or whether it will generalize to new data.

!

Not knowing the cross-entropy + softmax gradient simplification: โˆ‚L/โˆ‚z = ลท - y. If a research interviewer asks you to implement the backward pass for a classification network, you must know this โ€” computing the full Jacobian of softmax separately is unnecessary and inefficient.

Only works in the Electron app

<webview> is an Electron-only tag. Run npm run electron:dev to use this.

25:00Focus
0

25 min focus ยท 5 min break ยท long break every 4 sessions

The Ultimate Grind