Ds Math Notes Advanced Part3
Ds Math Notes Advanced Part3
Topic 4 Support Vector Machines (SVMs) Margin, kernel trick, dual problem
⚡ Each topic: Definition • Explanation • Formulas • Interview Q&A • Code • Mistakes • When to Use • Visual • Quick
Revision • Comparison
TOPIC 1 Neural Networks & Backpropagation The math behind deep learning's
engine
📖 DEFINITION
A Neural Network is a computational model loosely inspired by biological brains, composed of layers of
neurons (nodes) connected by weighted edges. Each neuron applies a weighted sum plus an activation
function. Backpropagation is the algorithm that efficiently computes gradients of the loss with respect to
every weight using the chain rule of calculus, enabling gradient descent to train the network.
💡 EXPLANATION (200-250 words)
A neural network has three types of layers: Input layer (receives raw features), Hidden layers (learn internal
representations), Output layer (produces predictions).
Forward Pass — how prediction is made:
1. Each neuron computes: z = Σ(wᵢ·xᵢ) + b (weighted sum + bias)
2. Apply activation function: a = σ(z) or ReLU(z) or tanh(z)
3. Output of one layer becomes input to the next. Final layer gives prediction ŷ.
Backward Pass (Backpropagation) — how learning happens:
4. Compute loss L = Loss(y, ŷ) at output.
5. Apply chain rule backward: ∂L/∂w = ∂L/∂a × ∂a/∂z × ∂z/∂w
6. Propagate gradients layer by layer back to the input.
7. Update every weight: w = w - α × ∂L/∂w
Activation functions add non-linearity so the network can learn complex patterns. Without activations,
stacking layers is useless — it collapses to a single linear transformation. ReLU is the modern default: fast,
avoids vanishing gradients in most cases.
📐 MATHEMATICAL FORMULAS
Forward: zˡ = Wˡ·aˡ⁻¹ + bˡ → aˡ = f(zˡ) [f = activation
function]
ReLU: f(z) = max(0, z) → f'(z) = 1 if z>0, else 0
Sigmoid: σ(z) = 1/(1+e⁻ᶻ) → σ'(z) = σ(z)·(1-σ(z))
Tanh: tanh(z) = (eᶻ-e⁻ᶻ)/(eᶻ+e⁻ᶻ) → tanh'(z) = 1 - tanh²(z)
Chain Rule: ∂L/∂Wˡ = ∂L/∂aˡ · ∂aˡ/∂zˡ · ∂zˡ/∂Wˡ = δˡ · (aˡ⁻¹)ᵀ
Weight Update: Wˡ ← Wˡ - α·∂L/∂Wˡ [α = learning rate]
Output Loss (Cross-Entropy): L = -Σ yᵢ·log(ŷᵢ)
🎯 REAL INTERVIEW QUESTIONS & ANSWERS
Q1: Why does vanishing gradient happen and how do you fix it?
Answer: Vanishing gradients occur when gradients become extremely small as they propagate back through
many layers — multiplying sigmoid derivatives (max 0.25) repeatedly gives nearly zero gradients in early
layers. Early layers barely update, so deep networks don't learn. Fixes: (1) Use ReLU instead of
sigmoid/tanh — gradient is 1 for positive inputs. (2) Batch Normalization — normalizes layer inputs,
stabilizes gradients. (3) Skip connections (ResNets) — gradients flow directly backward without decay. (4)
LSTM gates for sequences — manage gradient flow explicitly.
Q2: What is the dying ReLU problem?
Answer: If a neuron's input is always negative, ReLU outputs 0 always, gradient is 0 always — the neuron
never activates or updates ('dies'). Causes: large negative biases, very high learning rates. Fixes: (1) Leaky
ReLU: f(z) = max(0.01z, z) — small gradient for negatives. (2) ELU: smooth negative region. (3) GELU
(used in BERT/GPT): probabilistic smooth version. (4) Careful weight initialization and lower learning rates.
Q3: What is Xavier/Glorot initialization and why does it matter?
Answer: Random weight initialization matters because: too large → exploding activations/gradients. Too
small → vanishing activations/gradients. Xavier initialization sets weights from a distribution with variance =
2/(fan_in + fan_out). This keeps the variance of activations approximately constant across layers, preventing
vanishing/exploding from the very start. For ReLU, He initialization uses variance = 2/fan_in (accounts for
ReLU zeroing half the neurons).
⚠️ COMMON MISTAKES TO AVOID
• ❌ Initializing all weights to zero — every neuron computes the same gradient; symmetry never
breaks. Always use random init.
• ❌ Using sigmoid/tanh in deep hidden layers — causes vanishing gradients. Use ReLU family instead.
• ❌ Not using Batch Normalization in deep networks — activations shift during training, slowing
convergence.
• ❌ Setting learning rate too high — weights explode; set to 1e-3 (Adam) or 1e-2 (SGD) as starting
points.
• ❌ Forgetting to call [Link]() at inference — Dropout and BatchNorm behave differently during
training vs inference.
✅ WHEN TO USE vs ❌ WHEN NOT TO USE
✅ Deep networks: images (CNN), sequences ❌ Shallow networks on small tabular data — use
(RNN/LSTM), text (Transformers) XGBoost instead
✅ ReLU: default for hidden layers in deep networks ❌ Sigmoid/tanh in hidden layers of deep networks
— vanishing gradients
✅ Sigmoid: output layer for binary classification ❌ Without Batch Normalization in very deep
networks
✅ Softmax: output layer for multiclass classification ❌ Without proper weight initialization — zero init
breaks symmetry
# Training step
[Link]()
optimizer.zero_grad() # clear old gradients
output = model(X_batch) # forward pass
loss = criterion(output, y_batch)
[Link]() # backpropagation
[Link]() # update weights
📖 DEFINITION
A Convolutional Neural Network (CNN) is a deep learning architecture designed for grid-structured data
(images, audio spectrograms, time series). Instead of fully connected layers, CNNs use convolutional layers
that apply learned filters (kernels) across the input — detecting local patterns like edges, textures, and
shapes in a spatially invariant way.
💡 EXPLANATION (200-250 words)
Convolution operation: slide a small filter (e.g., 3×3 matrix of weights) across the input image. At each
position, compute the dot product between the filter and the image patch — producing a feature map. This
detects whether a specific pattern (edge, curve) exists at each location.
Key CNN components:
• Convolutional Layer: Applies F filters → produces F feature maps. Learns spatial patterns. Parameters
= F × (kernel_H × kernel_W × channels + 1).
• Activation (ReLU): Applied after convolution, adds non-linearity.
• Pooling Layer (MaxPool/AvgPool): Reduces spatial dimensions. MaxPool: take maximum value in
each pool region. Provides translation invariance and reduces computation.
• Batch Normalization: Normalizes feature maps — speeds training, acts as regularizer.
• Fully Connected Layer: At the end, flattened features → class scores.
Why CNNs are powerful: (1) Parameter sharing — same filter applied everywhere → far fewer parameters
than fully connected. (2) Local connectivity — each neuron sees only a small patch, not the whole image. (3)
Translation invariance — pooling makes CNN robust to small shifts in position.
Modern architectures: ResNet (skip connections), VGG (deep simple), EfficientNet (compound scaling),
Vision Transformer (attention-based).
📐 MATHEMATICAL FORMULAS
Convolution: (I★K)[i,j] = ΣₘΣₙ I[i+m, j+n] · K[m,n]
Output size: O = floor((I - K + 2P) / S) + 1
I=input size, K=kernel size, P=padding, S=stride
Parameters in Conv layer: (K×K×C_in + 1) × C_out
C_in=input channels, C_out=output filters
Receptive Field after L layers of kernel K: RF = 1 + L×(K-1)
MaxPool: output[i,j] = max of pool_size region at position [i,j]
🎯 REAL INTERVIEW QUESTIONS & ANSWERS
Q1: What is the difference between valid and same padding?
Answer: Valid padding (no padding): output is smaller than input. Output size = (I-K)/S + 1. Used when you
want to reduce spatial size. Same padding (zero padding): add zeros around the border so output size =
input size (when stride=1). Keeps spatial dimensions consistent through layers. 'Same' is often preferred in
hidden layers to avoid rapid size reduction. The number of zeros to add per side = (K-1)/2 for odd kernel
sizes.
Q2: What is the vanishing gradient problem specific to deep CNNs and how do ResNets solve it?
Answer: In very deep CNNs (50+ layers), gradients decay through many layers during backprop — early
layers barely learn. ResNets (Residual Networks) add skip connections: output = F(x) + x (the identity
shortcut). This means the gradient flows directly through the shortcut path (gradient = 1), bypassing potential
vanishing. The network only needs to learn the residual F(x) = desired_output - x, which is easier than
learning the full mapping from scratch.
Q3: Why does CNN have fewer parameters than a fully connected network for images?
Answer: For a 224×224×3 image with FC layer of 1000 neurons: parameters = 224×224×3×1000 ≈ 150M.
For a CNN with one 3×3 conv layer of 32 filters: parameters = (3×3×3+1)×32 = 896. CNN achieves this
through (1) Local connectivity — each filter covers only a 3×3 patch. (2) Weight sharing — the same 896
parameters are reused at every spatial position. This inductive bias (translation invariance) makes CNNs
extremely parameter-efficient for images.
⚠️ COMMON MISTAKES TO AVOID
• ❌ Not applying Batch Normalization after conv layers in deep CNNs — training is unstable without it.
• ❌ Using too large a stride without checking output dimensions — can cause dimension errors.
• ❌ Forgetting to normalize input images to [0,1] or [-1,1] — unnormalized pixels (0-255) cause slow
convergence.
• ❌ Using average pooling everywhere — MaxPool is standard for image classification; global average
pooling is used before the final FC layer.
• ❌ Training CNN from scratch on small datasets — always use transfer learning (pretrained ImageNet
weights).
✅ WHEN TO USE vs ❌ WHEN NOT TO USE
✅ Image classification, object detection, ❌ Small datasets without transfer learning — will
segmentation overfit
✅ Transfer learning from pretrained CNNs (ResNet, ❌ Non-grid structured data (use GNN or MLP)
EfficientNet)
✅ 1D CNNs for time series or text classification ❌ When full self-attention is needed (use Vision
Transformer)
✅ When spatial/local patterns are important ❌ Without data augmentation on small image
datasets
class SimpleCNN([Link]):
def __init__(self, num_classes=10):
super().__init__()
[Link] = [Link](
nn.Conv2d(1, 32, kernel_size=3, padding=1), # same padding
nn.BatchNorm2d(32),
[Link](),
nn.MaxPool2d(2, 2), # halve spatial dims
nn.Conv2d(32, 64, kernel_size=3, padding=1),
nn.BatchNorm2d(64),
[Link](),
nn.MaxPool2d(2, 2),
)
[Link] = [Link](
[Link](),
[Link](64*7*7, 128), # for 28x28 input
[Link](),
[Link](0.5),
[Link](128, num_classes)
)
def forward(self, x):
return [Link]([Link](x))
# Count parameters
model = SimpleCNN()
total = sum([Link]() for p in [Link]() if p.requires_grad)
print(f'Trainable params: {total:,}')
VGG Very deep, 3×3 convs only Simple architecture, large model
📖 DEFINITION
Recurrent Neural Networks (RNNs) are neural networks designed for sequential data by maintaining a
hidden state that carries information from previous time steps. LSTMs (Long Short-Term Memory networks)
are an advanced RNN variant with gating mechanisms that solve the vanishing gradient problem and allow
learning of long-range dependencies — critical for language, speech, and time series.
💡 EXPLANATION (200-250 words)
Standard RNN: at each time step t, the hidden state hₜ = f(Wₓ·xₜ + W ₕ·h ₜ₋₁ + b). This creates a feedback
loop — each output depends on the current input AND all previous hidden states. Problem: multiplying the
same weight matrix Wₕ repeatedly through many steps causes gradients to vanish (too small) or explode
(too large).
LSTM solution — three gates control information flow:
• Forget Gate (fₜ): 'What old memory to discard?' — sigmoid output ∈ (0,1) multiplied with cell state.
• Input Gate (iₜ): 'What new information to store?' — sigmoid decides how much of the new candidate to
add.
• Output Gate (oₜ): 'What to output from cell state?' — sigmoid filters cell state into hidden state.
• Cell State (Cₜ): The 'memory conveyor belt' — flows through time with only small multiplicative
changes. Gradient highway — allows gradients to flow back without vanishing.
GRU (Gated Recurrent Unit) is a simplified LSTM with only 2 gates (reset + update) — fewer parameters,
similar performance, faster training. Preferred for smaller datasets.
Modern replacement: Transformers have largely replaced RNNs/LSTMs for NLP because attention
processes all positions in parallel (vs sequential RNN), but LSTMs are still used for streaming/online
prediction and edge devices.
📐 MATHEMATICAL FORMULAS
RNN: hₜ = tanh(Wₓ·xₜ + Wₕ·hₜ₋₁ + b)
LSTM Forget Gate: fₜ = σ(Wf·[hₜ₋₁, xₜ] + bf) ∈ (0,1)
LSTM Input Gate: iₜ = σ(Wᵢ·[hₜ₋₁, xₜ] + bᵢ)
LSTM Candidate: C̃ₜ = tanh(Wc·[hₜ₋₁, xₜ] + bc)
LSTM Cell State: Cₜ = fₜ⊙Cₜ₋₁ + iₜ⊙C̃ₜ [⊙ = element-wise multiply]
LSTM Output Gate: oₜ = σ(Wo·[hₜ₋₁, xₜ] + bo)
LSTM Hidden State: hₜ = oₜ ⊙ tanh(Cₜ)
🎯 REAL INTERVIEW QUESTIONS & ANSWERS
Q1: How does an LSTM prevent vanishing gradients?
Answer: The LSTM cell state Cₜ = fₜ⊙Cₜ₋₁ + iₜ⊙C̃ ₜ is the key. The gradient flows through the cell state with
only element-wise multiplications and additions — no repeated matrix multiplication by the same weight
matrix. The forget gate fₜ can be set close to 1 (remember everything), allowing gradients to flow back over
many time steps without shrinking. This is unlike vanilla RNN where the gradient is multiplied by W ₕ at every
step, causing it to vanish or explode.
Q2: When would you use LSTM vs GRU vs Transformer?
Answer: LSTM: best when very long-range dependencies matter and you have enough data. Slightly better
than GRU on complex tasks. GRU: faster training, fewer parameters, good for smaller datasets or
streaming. Use when speed matters and task is not extremely long-range. Transformer: use when you have
large datasets, need parallelism, and long-range dependencies across the whole sequence matter (NLP,
large-scale time series). For small sequential datasets or real-time/edge prediction: LSTM/GRU still
preferred.
Q3: What is BPTT (Backpropagation Through Time)?
Answer: BPTT is the algorithm for training RNNs. Since the network is 'unrolled' in time (same weights
applied at each step), backprop flows through time steps from the final output backward to the first input —
computing gradient contributions from all time steps. Truncated BPTT (TBPTT) only backpropagates
through k steps instead of all T steps — trades accuracy for speed and memory. Used in practice for very
long sequences where full BPTT is too expensive.
⚠️ COMMON MISTAKES TO AVOID
• ❌ Feeding raw time steps to LSTM without normalization — scale matters for gradient stability.
• ❌ Using too many LSTM layers without dropout — deep LSTMs overfit on small datasets. Use
dropout=0.2.
• ❌ Ignoring sequence padding — variable-length sequences need packed_padded_sequence in
PyTorch to mask padding.
• ❌ Not resetting hidden state between independent sequences — carry-over from previous batch
corrupts training.
• ❌ Using LSTM when a Transformer would work better — for large NLP tasks, attention mechanisms
are now standard.
✅ WHEN TO USE vs ❌ WHEN NOT TO USE
✅ Time series forecasting (stock prices, sensors) ❌ Large-scale NLP — use Transformer/BERT
instead
✅ NLP tasks when compute is limited (edge/mobile) ❌ Fixed-length tabular data — use MLP/XGBoost
✅ Streaming/online prediction where full context ❌ Without gradient clipping for vanilla RNNs —
isn't available gradients explode
✅ GRU for smaller datasets or faster training needs ❌ Very long sequences without truncated BPTT —
memory issues
class LSTMClassifier([Link]):
def __init__(self, input_size, hidden_size, num_layers, num_classes):
super().__init__()
[Link] = [Link](
input_size=input_size,
hidden_size=hidden_size,
num_layers=num_layers,
batch_first=True,
dropout=0.2 if num_layers>1 else 0,
bidirectional=False
)
[Link] = [Link](hidden_size, num_classes)
Bidirectional LSTM Process fwd + backward NLP where full context available
(not real-time)
📖 DEFINITION
A Support Vector Machine is a supervised classification (and regression) algorithm that finds the optimal
hyperplane separating two classes by maximizing the margin — the distance between the hyperplane and
the nearest data points (support vectors). The kernel trick allows SVMs to find nonlinear decision boundaries
without explicit feature mapping.
💡 EXPLANATION (200-250 words)
Imagine drawing a line to separate red and blue points. Many lines work — but SVM finds the one with the
MAXIMUM gap (margin) between the two classes. Why maximum margin? Because a larger margin means
the classifier is more confident and generalizes better to new data.
Support vectors: the data points closest to the decision boundary. Only these points determine the
hyperplane — all other points are irrelevant. This makes SVMs memory efficient.
Hard margin SVM: requires all training points to be correctly classified (only works for linearly separable
data). Soft margin SVM (C-SVM): allows some misclassifications. C hyperparameter controls trade-off: large
C → narrow margin, fewer errors (high variance). Small C → wide margin, more errors allowed (high bias).
Kernel Trick: instead of explicitly transforming features to higher dimensions (expensive), we compute dot
products in the transformed space using a kernel function K(xᵢ, xⱼ). This implicitly maps data to infinite-
dimensional space. Common kernels: Linear, Polynomial (x·z+c)^d, RBF/Gaussian exp(-γ||x-z||²). RBF is the
default for nonlinear data.
📐 MATHEMATICAL FORMULAS
Decision boundary: wᵀx + b = 0
Margin: 2/||w|| → Maximize margin = Minimize ||w||²
Primal Objective: min (1/2)||w||² subject to yᵢ(wᵀxᵢ+b) ≥ 1
Soft Margin: min (1/2)||w||² + C·Σξᵢ (ξᵢ = slack variable ≥ 0)
Kernel RBF: K(x,z) = exp(-γ||x-z||²) [γ controls smoothness]
Kernel Polynomial: K(x,z) = (xᵀz + c)^d
SVM Prediction: f(x) = sign(Σᵢ αᵢyᵢK(xᵢ,x) + b)
🎯 REAL INTERVIEW QUESTIONS & ANSWERS
Q1: What is the kernel trick and why is it powerful?
Answer: Some data isn't linearly separable in original space (e.g., concentric circles). We could manually
add features (x², y², xy) to transform to higher dimensions — but this is expensive. The kernel trick computes
K(xᵢ,xⱼ) = φ(xᵢ)·φ(xⱼ) — the dot product in the transformed space — WITHOUT ever explicitly computing φ(x).
The RBF kernel implicitly maps to infinite-dimensional space. This gives SVMs the power of infinite feature
maps with the cost of just computing pairwise dot products.
Q2: How does the C parameter affect SVM?
Answer: C is the regularization parameter. Large C: penalizes misclassifications heavily → model tries to
classify everything correctly → narrow margin → low bias, high variance → may overfit. Small C: tolerates
misclassifications → wider margin → high bias, low variance → may underfit. Tune C with cross-validation.
Similarly, γ in RBF kernel: large γ → each point influences only nearby region → complex boundary (overfit).
Small γ → smooth decision boundary.
Q3: Why are SVMs not commonly used for large datasets today?
Answer: SVMs have O(n²) to O(n³) training time complexity because they solve a quadratic programming
optimization over all pairs of support vectors. For n=100K+ samples, this becomes computationally
prohibitive. Deep learning scales much better with data and GPUs. SVMs still shine for: small to medium
datasets (< 100K), high-dimensional data (text classification with linear SVM), problems where the kernel
provides the right inductive bias, and when training data is limited.
⚠️ COMMON MISTAKES TO AVOID
• ❌ Not scaling features — SVM is extremely sensitive to feature scale (uses distances). Always
StandardScaler first.
• ❌ Using RBF kernel without tuning C and γ — always GridSearchCV over both parameters together.
• ❌ Using kernel SVM on millions of samples — training time is O(n²~n³). Use LinearSVC or
SGDClassifier instead.
• ❌ Not using probability=True when you need probability outputs — SVMs don't naturally output
probabilities; use Platt scaling.
• ❌ Choosing kernel based on intuition alone — always cross-validate across linear, RBF, and
polynomial.
✅ WHEN TO USE vs ❌ WHEN NOT TO USE
✅ Small to medium datasets (< 100K samples) ❌ Very large datasets — too slow
✅ High-dimensional data (text, genomics) ❌ Without feature scaling — results will be wrong
✅ Clear margin of separation exists ❌ When probabilities are needed (use logistic
regression)
✅ Linear SVM for text classification (fast, effective) ❌ When neural networks are available and data is
abundant
# Hyperparameter tuning
param_grid = {
'svm__C': [0.1, 1, 10, 100],
'svm__gamma': ['scale', 'auto', 0.001, 0.01]
}
grid = GridSearchCV(svm_pipe, param_grid, cv=5, scoring='f1')
[Link](X_train, y_train)
print(f'Best params: {grid.best_params_}')
print(f'Best CV F1: {grid.best_score_:.4f}')
Linear SVM Max margin, linear boundary High-dim sparse data (text,
genomics)
📖 DEFINITION
Ensemble methods combine multiple ML models ('weak learners') to create a stronger, more accurate
predictor. The core insight: diverse models that make different types of errors can be combined to cancel out
individual errors. The three main paradigms are Bagging (parallel, reduces variance), Boosting (sequential,
reduces bias), and Stacking (meta-learning).
💡 EXPLANATION (200-250 words)
Bagging (Bootstrap Aggregating): Train K models on K different bootstrap samples (random sampling with
replacement from training data). Aggregate predictions by majority vote (classification) or mean (regression).
Random Forest adds random feature subsampling at each split on top of bagging → decorrelates trees
further.
Boosting: Train models sequentially. Each new model focuses on the samples that the previous models got
WRONG (harder examples). Final prediction = weighted sum of all models. Reduces bias primarily.
Examples:
• AdaBoost: weights misclassified samples higher at each round.
• Gradient Boosting: fits each new tree to the residual errors (pseudo-residuals = negative gradient of
loss) of the ensemble so far.
• XGBoost/LightGBM/CatBoost: optimized gradient boosting with regularization, parallel tree building,
and hardware optimization. State-of-the-art for tabular data.
Stacking: train several diverse base models, then train a meta-model ('blender') on their out-of-fold
predictions. The meta-model learns how to best combine the base models. More powerful than simple voting
but harder to implement correctly (requires care to avoid leakage).
📐 MATHEMATICAL FORMULAS
Bagging Prediction (regression): ŷ = (1/K) Σₖ fₖ(x)
Bagging (classification): ŷ = argmax_c Σₖ 𝟙[fₖ(x) = c] (majority
vote)
AdaBoost weight update: wᵢ ← wᵢ · exp(-αₜ · yᵢ · fₜ(xᵢ))
AdaBoost model weight: αₜ = (1/2) ln[(1-errₜ)/errₜ]
Gradient Boosting: Fₘ(x) = Fₘ₋₁(x) + η·hₘ(x) [η = learning rate]
Residual: rᵢₘ = -[∂L(yᵢ, F(xᵢ))/∂F(xᵢ)] (pseudo-residuals)
XGBoost Objective: L = Σloss(yᵢ,ŷᵢ) + Σ[γT + (1/2)λ||w||²]
🎯 REAL INTERVIEW QUESTIONS & ANSWERS
Q1: What is the difference between Bagging and Boosting?
Answer: Bagging: trains K models INDEPENDENTLY in parallel on different bootstrap samples. Reduces
variance. Models are unweighted (equal vote). Best when base models overfit (high variance). Random
Forest is bagging of decision trees. Boosting: trains models SEQUENTIALLY where each model corrects the
previous one's errors. Reduces bias. Models are weighted (better models get more vote). Best when base
models underfit (high bias). XGBoost is boosting. Key: bagging reduces variance; boosting reduces bias.
Bagging: harder to overfit. Boosting: can overfit if too many rounds.
Q2: Why does XGBoost perform so well on tabular data?
Answer: XGBoost improves on gradient boosting with: (1) Regularization: L1+L2 on tree weights + minimum
leaf weight → prevents overfitting that vanilla GB suffers from. (2) Tree pruning: grows tree to max depth
then prunes, unlike greedy growth. (3) Weighted quantile sketch: efficient approximate split finding for large
datasets. (4) Sparse awareness: handles missing values natively. (5) Cache optimization + parallel column
block for fast training. (6) Built-in cross-validation and early stopping. Together these make it extremely
robust and fast.
Q3: What is out-of-bag (OOB) error in Random Forest?
Answer: Each bootstrap sample contains ~63.2% of training data (some points sampled multiple times,
~36.8% never sampled = out-of-bag). For each training point, we can evaluate it using only trees that did
NOT use it in their training — giving a free, unbiased validation estimate without a held-out set. OOB error is
approximately equal to leave-one-out cross-validation accuracy. If oob_score=True in sklearn, this is
computed automatically. Very useful for quick model evaluation on small datasets.
⚠️ COMMON MISTAKES TO AVOID
• ❌ Too many boosting rounds without early stopping — gradient boosting will overfit on training data.
• ❌ Using boosting with complex base learners (deep trees) — shallow trees (max_depth=3-6) are
standard.
• ❌ Not tuning n_estimators, learning_rate, and max_depth together in XGBoost — they interact
strongly.
• ❌ Stacking without out-of-fold predictions for meta-features — causes severe data leakage.
• ❌ Ignoring feature importance masking with correlated features — split importance between
correlated features can mislead.
✅ WHEN TO USE vs ❌ WHEN NOT TO USE
✅ Random Forest: robust baseline when tuning ❌ Bagging when base model is already low-
time is limited variance
✅ AdaBoost: with weak learners (decision stumps) ❌ Ensembles when interpretability is a hard
for simple tasks requirement
# Feature importance
import pandas as pd
fi = [Link](xgb.feature_importances_, index=feature_names)
print(fi.sort_values(ascending=False).head(10))
Random Forest Bagging + random features Robust, fast, low tuning — great
baseline
📖 DEFINITION
Optimization algorithms in deep learning are methods for updating model parameters to minimize the loss
function. Beyond vanilla gradient descent, modern optimizers like Adam adaptively adjust learning rates per
parameter — dramatically improving convergence speed, stability, and final performance. Choosing the right
optimizer and learning rate schedule is critical for training neural networks efficiently.
💡 EXPLANATION (200-250 words)
Vanilla SGD: θ = θ - α∇L. Problem: same learning rate for all parameters. Features with infrequent updates
(sparse gradients) should have larger updates; frequently updated features should have smaller updates.
Momentum: adds a 'velocity' term that accumulates gradients over time — like a ball rolling downhill that
builds up speed. Helps escape flat regions and overshoots local minima less.
RMSProp: divides gradient by the moving average of its recent squared magnitude. Features with
historically large gradients get smaller updates (adaptive per-parameter learning rates). Solves the
'diminishing learning rate' problem of AdaGrad.
Adam (Adaptive Moment Estimation): combines Momentum (1st moment: mean of gradients) and RMSProp
(2nd moment: variance of gradients). Uses bias correction for the first few steps when moments are
initialized at zero. Adam is the most popular optimizer in practice — works well out of the box with lr=1e-3.
Learning Rate Schedules: keep learning rate high early (fast learning) then reduce it as training progresses
(fine-tuning). Common: StepLR (reduce by factor every N epochs), CosineAnnealingLR (cosine decay),
OneCycleLR (warm-up + cosine decay — often fastest convergence).
📐 MATHEMATICAL FORMULAS
Momentum: vₜ = β·vₜ₋₁ + (1-β)·gₜ → θ = θ - α·vₜ
RMSProp: sₜ = β·sₜ₋₁ + (1-β)·gₜ² → θ = θ - α·gₜ/√(sₜ+ε)
Adam — 1st moment: mₜ = β₁·mₜ₋₁ + (1-β₁)·gₜ
Adam — 2nd moment: vₜ = β₂·vₜ₋₁ + (1-β₂)·gₜ²
Adam — bias correction: m̂ ₜ = mₜ/(1-β₁ᵗ), v̂ ₜ = vₜ/(1-β₂ᵗ)
Adam — update: θₜ = θₜ₋₁ - α·m̂ ₜ/(√v̂ ₜ + ε)
Defaults: β₁=0.9, β₂=0.999, ε=1e-8, α=1e-3
🎯 REAL INTERVIEW QUESTIONS & ANSWERS
Q1: Why does Adam work better than vanilla SGD for most deep learning tasks?
Answer: Adam adapts the learning rate for each parameter individually: (1) Parameters with large gradients
get smaller updates (prevents overshooting). (2) Parameters with small/sparse gradients get larger updates
(ensures they still learn). (3) Momentum helps navigate flat loss regions and saddle points efficiently. (4)
Bias correction prevents under-shooting in early steps. SGD with momentum can match or beat Adam on
carefully tuned tasks (especially in computer vision with cosine LR schedules), but Adam is far more
forgiving of hyperparameter choices.
Q2: What is weight decay and how does it relate to L2 regularization?
Answer: Weight decay directly decays weights at each step: θ = θ - α·∇L - λ·θ. For SGD, weight decay and
L2 regularization are mathematically equivalent. For adaptive optimizers like Adam, they are NOT equivalent
— AdamW (Adam with decoupled weight decay) was introduced to fix this: weight decay is applied directly
to the weights, not scaled by the adaptive learning rate. AdamW is now the preferred optimizer for
Transformers and most modern deep learning.
Q3: What is learning rate warm-up and why is it needed?
Answer: At the start of training, the model weights are random and the gradient estimates are noisy. Starting
with a large learning rate causes huge, unstable updates. Warm-up gradually increases the learning rate
from near-zero to the target value over the first N steps/epochs. This stabilizes early training. After warm-up,
the learning rate is often decayed with cosine annealing. This is critical for Transformers (BERT uses 10K
warm-up steps) and large-batch training where the effective gradient is noisier.
⚠️ COMMON MISTAKES TO AVOID
• ❌ Using vanilla Adam without weight decay — use AdamW for better regularization.
• ❌ Setting learning rate too high without warm-up — unstable training especially for Transformers.
• ❌ Not tuning learning rate — it's the single most impactful hyperparameter. Always tune it.
• ❌ Using Adam when SGD+momentum would generalize better — for vision models with long training,
SGD+cosine schedule often outperforms Adam.
• ❌ Not using gradient clipping with RNNs — Adam doesn't prevent exploding gradients in RNNs.
✅ WHEN TO USE vs ❌ WHEN NOT TO USE
✅ Adam/AdamW: NLP, Transformers, default for ❌ Adam without weight decay on models that need
most tasks strong regularization
✅ SGD + momentum + cosine schedule: computer ❌ High lr without warm-up for Transformers
vision fine-tuning
✅ RMSProp: RNNs and non-stationary problems ❌ No lr schedule for long training runs
✅ OneCycleLR: fastest convergence for training ❌ Same optimizer for all tasks — empirically
from scratch compare on your problem
model = YourModel()
# Training loop
for batch in train_loader:
loss = compute_loss(batch)
optimizer.zero_grad()
[Link]()
[Link].clip_grad_norm_([Link](), 1.0)
[Link]()
[Link]()
SGD + Momentum Accumulate gradient history Escapes flat regions faster than
SGD
📖 DEFINITION
Bayesian Optimization is a sequential, model-based optimization strategy for expensive black-box functions
(like ML model training). It builds a probabilistic surrogate model (usually a Gaussian Process) of the
objective function and uses an acquisition function to decide where to evaluate next — balancing exploration
(try unknown regions) and exploitation (refine promising regions).
💡 EXPLANATION (200-250 words)
Grid Search: tries all combinations in a fixed grid. Random Search: tries random combinations. Both are
'dumb' — they don't learn from previous evaluations. Bayesian Optimization is 'smart':
8. Start with a few random evaluations of the objective (e.g., model accuracy at different
hyperparameters).
9. Fit a Gaussian Process (GP) surrogate model to these observations. The GP gives a mean prediction
AND uncertainty estimate at every unobserved point.
10. Maximize the acquisition function (e.g., Expected Improvement) to find the most promising next
hyperparameter to try.
11. Evaluate the true objective (train model) at that point. Update the GP. Repeat.
Gaussian Process: a distribution over functions. At any unobserved point, it predicts both a mean (best
guess of objective value) and a variance (uncertainty). Points far from observations have high variance —
we should explore them. Points near observed good results have low variance — we should exploit them.
AutoML systems (Auto-sklearn, Optuna, H2O AutoML) use Bayesian optimization under the hood to
automatically find the best algorithm, preprocessing pipeline, and hyperparameters — democratizing ML for
non-experts.
📐 MATHEMATICAL FORMULAS
GP Prior: f(x) ~ GP(μ(x), k(x,x')) [k = kernel/covariance function]
GP Posterior: μₙ(x) = kᵀ(Kₙₙ+σ²I)⁻¹y (posterior mean)
GP Variance: σₙ²(x) = k(x,x) - kᵀ(Kₙₙ+σ²I)⁻¹k
Expected Improvement: EI(x) = E[max(f(x)-f*,0)] [f* = current best]
EI = (μ(x)-f*)·Φ(Z) + σ(x)·φ(Z) where Z=(μ(x)-f*)/σ(x)
Upper Confidence Bound: UCB(x) = μ(x) + κ·σ(x) [κ controls
exploration]
🎯 REAL INTERVIEW QUESTIONS & ANSWERS
Q1: Why is Bayesian Optimization better than Grid or Random Search for hyperparameter tuning?
Answer: Grid Search: exponential cost with dimensions; wastes evaluations on bad regions. Random
Search: better (Bergstra & Bengio 2012 showed it's more efficient than grid for most real problems), but still
doesn't learn from results. Bayesian Optimization: builds a probabilistic model of the objective → uses
previous results to decide where to look next → converges to good hyperparameters in 5-10× fewer
evaluations than random search. Critical when each evaluation is expensive (hours of training). Optuna uses
Tree-structured Parzen Estimator (TPE) as the surrogate — a fast approximation to full GP-based BO.
Q2: What is the exploration-exploitation trade-off in Bayesian Optimization?
Answer: Exploration: try hyperparameter regions with high uncertainty (high σ) — might discover better
regions. Exploitation: try regions predicted to perform well (high μ) — refine known good areas. Acquisition
functions balance this: EI (Expected Improvement) balances naturally. UCB (Upper Confidence Bound) has
κ parameter: high κ → more exploration, low κ → more exploitation. In practice: explore early (few
observations → high uncertainty everywhere), exploit later (many observations → surrogate is accurate).
Q3: What is the difference between Optuna, Hyperopt, and Auto-sklearn?
Answer: Optuna: modern, define-by-run API, uses TPE (Bayesian) + CMA-ES, excellent pruning (stop bad
trials early), distributed search, very user-friendly. Hyperopt: older TPE-based BO library, still widely used.
Auto-sklearn: full AutoML — automatically selects algorithm + preprocessing + hyperparameters using BO +
ensemble methods. Returns a complete sklearn pipeline without manual intervention. H2O AutoML:
enterprise-grade AutoML. Use Optuna for hyperparameter tuning; Auto-sklearn/H2O when you want a fully
automated ML pipeline.
⚠️ COMMON MISTAKES TO AVOID
• ❌ Using Grid Search for high-dimensional hyperparameter spaces (5+ params) — exponential cost.
Use Optuna/BO instead.
• ❌ Not defining search bounds carefully — BO can't explore outside the defined range.
• ❌ Running only 5-10 BO trials and concluding — BO needs 20-50+ trials to outperform random
search meaningfully.
• ❌ Not using pruning callbacks — Optuna's pruning stops unpromising trials early, saving enormous
compute.
• ❌ Treating AutoML output as 'production-ready' without validation — always validate on a proper
held-out test set.
✅ WHEN TO USE vs ❌ WHEN NOT TO USE
✅ When model training takes hours (expensive ❌ Grid search if > 4 hyperparameters — too
evaluation) expensive
✅ AutoML: rapid prototyping, non-expert users ❌ AutoML when domain expertise should inform
architecture
✅ Optuna with pruning for neural architecture ❌ Without proper test set validation of AutoML
search results
def objective(trial):
# Define hyperparameter search space
n_estimators = trial.suggest_int('n_estimators', 50, 500)
max_depth = trial.suggest_int('max_depth', 2, 20)
min_samples = trial.suggest_int('min_samples_leaf', 1, 20)
max_features = trial.suggest_float('max_features', 0.3, 1.0)
model = RandomForestClassifier(
n_estimators=n_estimators,
max_depth=max_depth,
min_samples_leaf=min_samples,
max_features=max_features,
n_jobs=-1, random_state=42)
scores = cross_val_score(model, X_train, y_train,
cv=5, scoring='f1')
return [Link]()
study = optuna.create_study(direction='maximize')
[Link](objective, n_trials=50, show_progress_bar=True)
print('Best params:', study.best_params)
print('Best F1:', study.best_value)
📖 DEFINITION
Time series analysis is the study of data points collected sequentially over time where the ORDER matters.
Unlike regular tabular data, time series has temporal dependencies — past values predict future values. Key
models include ARIMA (statistical), Prophet (trend+seasonality), and LSTM/Transformer (deep learning).
Core concepts: stationarity, autocorrelation, and decomposition.
💡 EXPLANATION (200-250 words)
A time series has 4 components:
• Trend: Long-term upward or downward movement (e.g., growing revenue).
• Seasonality: Regular periodic patterns (e.g., higher sales every December).
• Cyclical: Irregular long-term fluctuations (e.g., economic cycles).
• Residual/Noise: Random unexplained variation after removing above components.
Stationarity: A stationary time series has constant mean, constant variance, and constant autocorrelation
structure over time. Most statistical models (ARIMA) require stationarity. Test: Augmented Dickey-Fuller
(ADF) test — p < 0.05 → stationary. Make stationary: differencing (subtract previous value), log transform
(for variance), seasonal differencing.
ARIMA(p,d,q):
• AR(p): AutoRegressive — current value depends on p previous values.
• I(d): Integrated — differenced d times to achieve stationarity.
• MA(q): Moving Average — current value depends on q previous error terms.
ACF (Autocorrelation Function): correlation between series and its lag. Helps identify MA order q. PACF
(Partial ACF): correlation removing effect of intermediate lags. Helps identify AR order p.
📐 MATHEMATICAL FORMULAS
AR(p): Xₜ = c + φ₁Xₜ₋₁ + φ₂Xₜ₋₂ + ... + φₚXₜ₋ₚ + εₜ
MA(q): Xₜ = μ + εₜ + θ₁εₜ₋₁ + θ₂εₜ₋₂ + ... + θqεₜ₋q
ARIMA(p,d,q): Δᵈ Xₜ = AR(p) terms + MA(q) terms + εₜ
First Differencing: Δ¹Xₜ = Xₜ - Xₜ₋₁ (removes linear trend)
ACF(k): ρₖ = Cov(Xₜ, Xₜ₋ₖ) / Var(Xₜ) [autocorrelation at lag k]
ADF Test H₀: series has a unit root (non-stationary). p < 0.05 →
reject H₀ → stationary
SARIMA(p,d,q)(P,D,Q)m: adds seasonal AR, I, MA with period m
🎯 REAL INTERVIEW QUESTIONS & ANSWERS
Q1: What is stationarity and why does ARIMA require it?
Answer: A stationary series has: (1) Constant mean over time, (2) Constant variance over time, (3)
Autocovariance that depends only on lag, not time position. ARIMA requires stationarity because its
statistical foundations assume the process generating data has fixed statistical properties — without this, the
model parameters have no consistent meaning and predictions are unreliable. The 'I' in ARIMA (Integrated)
handles non-stationarity by differencing: d=1 removes linear trends, d=2 removes quadratic trends.
Seasonal differencing (SARIMA) handles seasonal non-stationarity.
Q2: How do you choose p, d, q parameters for ARIMA?
Answer: Step 1 — Choose d: run ADF test. If non-stationary, d=1 (difference once). Re-test. Step 2 — Plot
ACF: if ACF cuts off sharply after lag q → MA(q) process. Step 3 — Plot PACF: if PACF cuts off sharply
after lag p → AR(p) process. If both taper off gradually → ARMA. Step 4 — Use AIC/BIC criteria: fit multiple
ARIMA models, select the one minimizing AIC (rewards fit, penalizes parameters). Auto-arima (pmdarima
library) does all this automatically.
Q3: What is the difference between ARIMA and Prophet for forecasting?
Answer: ARIMA: statistical model, requires stationarity and careful parameter selection (p,d,q), cannot
handle multiple seasonalities easily, sensitive to outliers, needs expertise to tune. Prophet (Facebook/Meta):
decomposition model (trend + seasonality + holidays), handles multiple seasonalities automatically, robust
to missing data and outliers, handles holidays explicitly, very user-friendly. Use ARIMA for simple univariate
series with clear ARIMA structure. Use Prophet for business time series with multiple seasonalities and
holidays. For long-horizon/complex forecasting: N-BEATS or Temporal Fusion Transformer.
⚠️ COMMON MISTAKES TO AVOID
• ❌ Using ARIMA without checking stationarity — will give unreliable forecasts and warnings.
• ❌ Shuffling time series data for train/test split — NEVER shuffle! Always split by time: first 80% =
train, last 20% = test.
• ❌ Applying standard K-Fold CV to time series — use TimeSeriesSplit (always train on past, test on
future).
• ❌ Forgetting to check residuals after fitting ARIMA — residuals should be white noise (no
autocorrelation). Use Ljung-Box test.
• ❌ Not accounting for seasonality — if data has weekly/yearly patterns, use SARIMA or seasonal
decomposition.
✅ WHEN TO USE vs ❌ WHEN NOT TO USE
✅ Prophet: business series with multiple ❌ Standard K-Fold on time series — future data
seasonalities + holidays leaks into training
✅ LSTM/Transformer: multivariate series, complex ❌ Prophet when series has very irregular,
non-linear patterns unpredictable behavior
✅ TimeSeriesSplit: CV for any time-ordered data ❌ Shuffling time series data at any stage of the
pipeline
# Step 2: Decompose
decomp = seasonal_decompose(series, model='additive', period=12)
# [Link], [Link], [Link]
# Step 4: Forecast
forecast = [Link](steps=12)
conf_int = result.get_forecast(steps=12).conf_int()
📖 DEFINITION
Graph Neural Networks (GNNs) are deep learning models designed to operate on graph-structured data —
where entities (nodes) have relationships (edges). Traditional neural networks assume independent, grid-
like inputs. GNNs generalize to arbitrary connectivity, enabling learning on social networks, molecules,
knowledge graphs, and recommendation systems.
💡 EXPLANATION (200-250 words)
A graph G = (V, E) has nodes (V) and edges (E). Each node has a feature vector. The graph's structure is
encoded in the Adjacency Matrix A where A[i,j]=1 if there's an edge between nodes i and j.
Graph Convolution Network (GCN) — core idea: 'Message Passing'. Each node aggregates information
from its neighbors. After k layers, each node's representation reflects its k-hop neighborhood.
12. Each node starts with its own feature vector h⁰ᵢ.
13. In each layer: each node SENDS its current representation to its neighbors.
14. Each node AGGREGATES (sums/averages) messages received from neighbors.
15. Each node UPDATES its representation using the aggregated message.
16. After L layers: hˡᵢ encodes the structure and features of the L-hop neighborhood.
Applications of GNNs:
• Node classification: predict properties of each node (e.g., classify users in social network).
• Link prediction: predict if an edge should exist (recommendation systems).
• Graph classification: classify entire graphs (e.g., predict molecular properties).
• Anomaly detection in transaction graphs (fraud detection).
📐 MATHEMATICAL FORMULAS
Graph: G = (V, E) |V| = n nodes, |E| = m edges
Adjacency Matrix A: A[i,j] = 1 if edge(i,j) exists, else 0
Degree Matrix D: D[i,i] = Σⱼ A[i,j] (number of neighbors of node i)
Normalized Adjacency: Â = D⁻¹/²·(A+I)·D⁻¹/² (+I adds self-loops)
GCN Layer: H^(l+1) = σ(Â · H^(l) · W^(l))
H^(l) = node feature matrix at layer l, W^(l) = learnable weight
matrix
GraphSAGE Aggregate: h^(l)ᵥ = σ(W·CONCAT(h^(l-1)ᵥ, MEAN_{u∈N(v)}
h^(l-1)_u))
🎯 REAL INTERVIEW QUESTIONS & ANSWERS
Q1: Why can't we use standard CNNs or MLPs directly on graphs?
Answer: CNNs operate on regular grids (fixed number of neighbors in fixed positions). Graphs have irregular
structure: nodes have varying numbers of neighbors in no fixed order. MLPs operate on fixed-size
independent vectors — they ignore the graph structure (edges) entirely. GNNs solve this through message
passing, which is permutation-equivariant (the output doesn't depend on the arbitrary ordering of nodes) and
handles variable-sized neighborhoods naturally through aggregation functions.
Q2: What is the over-smoothing problem in deep GNNs?
Answer: In each GCN layer, nodes average their neighbors' features. After many layers (k >> depth), all
node representations in a connected component converge to the same vector — indistinguishable. This is
over-smoothing. It limits practical GNNs to 2-5 layers (unlike CNNs that can go 100+ layers). Solutions: (1)
Residual connections (GCNII), (2) Skip connections, (3) Graph attention (GAT) — learn which neighbors to
weight more, (4) Jumping Knowledge Networks — aggregate representations from all layers.
Q3: How are GNNs used in recommendation systems?
Answer: Model users and items as nodes. Interactions (clicks, purchases) as edges. The bipartite user-item
graph is fed into a GNN (e.g., PinSage, LightGCN). Through message passing, user node representations
incorporate the features of items they interacted with, and item representations incorporate user
preferences. After L layers, user and item embeddings capture higher-order interaction patterns (e.g., 'users
like you also liked X'). LightGCN (Pinterest, Alibaba) showed that removing nonlinear transformations in
graph convolution dramatically improves recommendation quality.
⚠️ COMMON MISTAKES TO AVOID
• ❌ Using more than 3-5 GCN layers without residual connections — over-smoothing destroys node
distinguishability.
• ⁻Not normalizing the adjacency matrix — without D⁻¹/²ÂD⁻¹/² normalization, high-degree nodes
dominate.
• ❌ Ignoring edge features — many real graphs (molecules, knowledge graphs) have important edge
attributes; use edge-aware GNNs.
• ❌ Training/test split that ignores graph structure — use transductive (same graph, split nodes) or
proper inductive (new graphs at test time) splits.
• ❌ Using dense adjacency matrix for large graphs — use sparse representations ([Link] or
PyG's SparseTensor).
✅ WHEN TO USE vs ❌ WHEN NOT TO USE
✅ Molecular property prediction (drug discovery) ❌ Very deep GNNs (>5 layers) without skip
connections
✅ Fraud detection in transaction graphs ❌ Dense adjacency storage for large graphs
(millions of nodes)
✅ Recommendation systems with user-item graphs ❌ When edge order matters — standard GNNs are
permutation-invariant
📖 DEFINITION
The Transformer is a deep learning architecture based entirely on self-attention mechanisms, introduced in
'Attention is All You Need' (Vaswani et al., 2017). It processes all tokens in parallel (unlike RNNs), captures
long-range dependencies directly through attention, and has become the dominant architecture for NLP
(BERT, GPT), vision (ViT), speech, and multimodal AI. Understanding Transformers is essential for any
senior DS/ML role today.
💡 EXPLANATION (200-250 words)
Core idea of Attention: when processing a word, look at ALL other words in the sequence and decide which
ones are most relevant — instead of just the previous word (like RNN).
Scaled Dot-Product Attention:
17. For each token, create three vectors: Query (Q), Key (K), Value (V) by multiplying input with learned
weight matrices.
18. Compute attention scores: how much should token i attend to token j? Score = Q_i · K_j (dot product).
19. Scale by √d_k (dimension of keys) — prevents softmax saturation for large dimensions.
20. Apply softmax to get attention weights (sum to 1 across all positions).
21. Output = weighted sum of Value vectors: Attention(Q,K,V) = softmax(QKᵀ/√d_k)·V
Multi-Head Attention: run h attention heads in parallel with different learned Q,K,V projections. Each head
learns to attend to different aspects (syntactic, semantic, positional). Concatenate and project outputs.
Positional Encoding: Transformers have no inherent sense of order (unlike RNNs). Add positional encoding
(sinusoidal or learned) to input embeddings to inject position information.
BERT: bidirectional encoder (sees full context both ways). Used for understanding tasks. GPT: causal
decoder (sees only left context). Used for generation.
📐 MATHEMATICAL FORMULAS
Attention: Attention(Q,K,V) = softmax(QKᵀ / √d_k) · V
Q = X·Wq, K = X·Wk, V = X·Wv [Wq,Wk,Wv are learned matrices]
Multi-Head: MultiHead(Q,K,V) = Concat(head₁,...,headₕ) · Wo
headᵢ = Attention(Q·Wqᵢ, K·Wkᵢ, V·Wvᵢ)
Positional Encoding: PE(pos,2i) = sin(pos/10000^(2i/d_model))
Transformer Block: x → LayerNorm(x + MultiHeadAttn(x)) → LayerNorm(+
FFN)
FFN: FFN(x) = max(0, x·W₁+b₁)·W₂+b₂ [two-layer MLP with ReLU/GELU]
🎯 REAL INTERVIEW QUESTIONS & ANSWERS
Q1: What is the computational complexity of self-attention and why is it a problem?
Answer: Self-attention computes QKᵀ which is an n×n matrix (n = sequence length). Complexity is O(n²·d) in
time and O(n²) in memory. For n=512 (BERT), this is manageable. For n=16K (long documents), it's
prohibitively expensive. Solutions: Sparse Attention (only attend to nearby tokens), Longformer (sliding
window + global attention), Linformer (low-rank approximation), Flash Attention (hardware-efficient exact
attention using tiling — doesn't reduce FLOPs but reduces memory from O(n²) to O(n), enabling much
longer contexts).
Q2: What is the difference between encoder-only, decoder-only, and encoder-decoder Transformers?
Answer: Encoder-only (BERT, RoBERTa): bidirectional attention — sees full context. Best for: classification,
NER, question answering, embedding generation. Decoder-only (GPT, LLaMA): causal/masked attention —
sees only left context. Best for: text generation, language modeling. Encoder-Decoder (T5, BART, original
Transformer): encoder processes source, decoder generates target with cross-attention to encoder. Best for:
translation, summarization, seq2seq tasks. Modern trend: decoder-only models (GPT architecture) scaled to
very large sizes (GPT-4, LLaMA) for general-purpose tasks.
Q3: What is BERT pre-training and what are its objectives?
Answer: BERT pre-trains on two tasks: (1) Masked Language Modeling (MLM): randomly mask 15% of input
tokens; model predicts the masked words. Forces bidirectional context learning — unlike GPT which only
looks left. (2) Next Sentence Prediction (NSP): given two sentences, predict if B follows A. Helps learn inter-
sentence relationships (less impactful — RoBERTa showed NSP can be removed). Fine-tuning: add a task-
specific head (e.g., classification layer) on top of [CLS] token, then fine-tune all weights on labeled data for a
few epochs. Transfer learning from BERT dramatically reduces labeled data requirements.
⚠️ COMMON MISTAKES TO AVOID
• ❌ Not adding positional encoding — Transformer has no notion of order without it; all permutations of
input give same output.
• ❌ Not using Layer Normalization — training Transformers without LayerNorm is extremely unstable.
• ❌ Using too small d_k — small key dimensions cause attention scores to be too large → softmax
saturation → vanishing gradients.
• ❌ Not using attention masking in decoders — future tokens must be masked during training to prevent
'cheating'.
• ❌ Fine-tuning all BERT layers without warmup — fine-tuning large models requires careful lr
scheduling (warmup + decay).
✅ WHEN TO USE vs ❌ WHEN NOT TO USE
✅ BERT/RoBERTa: text classification, NER, QA ❌ Very small datasets — Transformers overfit; use
LSTM or pretrained + freeze
✅ GPT: text generation, chatbots, code completion ❌ Very long sequences without efficient attention
(Longformer, Flash Attention)
✅ ViT: image tasks when large data available ❌ Simple tabular tasks — use XGBoost;
Transformers don't help
# Tokenize input
inputs = tokenizer(
['I love this movie!', 'This film was terrible.'],
padding=True, truncation=True, return_tensors='pt')
# Forward pass
with torch.no_grad():
outputs = model(**inputs)
logits = [Link]
probs = [Link](logits, dim=-1)
RoBERTa BERT without NSP, more data Better BERT for most
classification tasks