AI Foundations

Math & Statistics for ML

Every machine learning model is a mix of four kinds of math: statistics to describe data, probability to reason about uncertainty, linear algebra to compute, and calculus to learn. This page builds all of them from zero, with worked numbers and NumPy code, up to the exact formulas that run inside a transformer.

~185 min read 0 interview questions
In 30 seconds
  • A dataset is a matrix (rows = samples, columns = features); a neural network layer is a matrix multiply followed by a non-linear function.
  • Training = define a loss (usually a negative log-likelihood such as cross-entropy or MSE), compute its gradient with the chain rule (backpropagation), and step downhill (gradient descent, usually Adam).
  • Probability tells you what model outputs mean; Bayes' theorem explains base-rate traps, and MLE/MAP explain where losses and regularization come from.
  • Statistics tells you whether a result is real: sampling, confidence intervals, p-values, and A/B tests guard against fooling yourself with noise.
  • Information theory (entropy, cross-entropy, KL) is the language of classification losses, distillation, VAEs and RLHF; numerical tricks (log-sum-exp, stable softmax) keep it from overflowing.
  • Attention is just softmax(QKT/√dk)V: dot products for similarity, scaling for stable gradients, softmax for weights, a weighted sum for output.

The big picture: why ML needs math

Machine learning looks like magic from the outside, but inside it is a small number of mathematical ideas used over and over. If you understand these ideas well, every new model or paper becomes "the same pieces in a new arrangement" rather than something to memorize. This page is ordered so that a newcomer can read it top to bottom: we start with describing data, move to uncertainty, then to the machinery of computation and learning, and finish with the math inside large language models.

Analogy

Think of building and running a restaurant. Statistics is the accountant who summarizes last month's sales and tells you whether the new menu really increased revenue or you just had a lucky week. Probability is the forecaster who says "there is a 70% chance of a busy Friday". Linear algebra is the kitchen: the stoves and conveyor belts that process hundreds of orders in parallel. Calculus is the head chef tasting the soup and adjusting salt a little at a time until it is right. In ML, the accountant evaluates models, the forecaster interprets outputs, the kitchen runs the matrix multiplications on GPUs, and the chef is gradient descent tuning millions of weights.

Where each branch of math shows up

BranchCore questionWhere you see it in ML
Descriptive statisticsWhat does my data look like?EDA, feature scaling, outlier handling, monitoring data drift
ProbabilityHow likely is each outcome?Classifier outputs, Naive Bayes, generative models, sampling from LLMs
Inferential statisticsIs this difference real or noise?A/B tests, comparing models, confidence intervals on metrics
Linear algebraHow do we compute on many numbers at once?Layers, embeddings, attention, PCA, recommendation systems
CalculusHow does the output change if I nudge an input?Gradients, backpropagation, optimization
OptimizationHow do we find the best parameters?SGD, Adam, learning-rate schedules, regularization
Information theoryHow surprising or different are distributions?Cross-entropy loss, KL divergence, perplexity, decision trees

One neural network, all the math at once

Here is a tiny example that touches almost every section of this page. A student studied 7 hours, slept 8 hours and had a previous score of 6 out of 10. We put these three numbers in a row vector x = [7, 8, 6]. A layer with two hidden neurons has a 3×2 weight matrix W. Multiplying x by W produces two numbers, each a dot product of the input with one column of weights.

[7, 8, 6] × [[0.4, −0.2], [0.3, 0.5], [0.6, 0.1]] = [7(0.4) + 8(0.3) + 6(0.6), 7(−0.2) + 8(0.5) + 6(0.1)] = [8.8, 3.2] A [1×3] row times a [3×2] matrix gives a [1×2] row. Each output is one dot product.

We then squash each value with the sigmoid σ(z) = 1/(1 + e−z), giving [0.9998, 0.9608], and a second layer with weights [0.7, 0.3] combines them into 0.9998(0.7) + 0.9608(0.3) ≈ 0.988, which we read as a 98.8% probability of passing. That single forward pass used vectors, matrix multiplication and a non-linear function. Training would then compare 0.988 to the true label with a loss (information theory and probability), compute the gradient of that loss with respect to every weight (calculus), and update the weights (optimization). Stack 1,000 students as rows of a matrix and the same single multiplication processes all of them at once, which is exactly why GPUs are so good at ML.

  data (matrix)        linear algebra          calculus              optimization
 [n x features] ──▶  Z = XW + b  ──▶  A = f(Z) ──▶ loss L ──▶ dL/dW via chain rule ──▶ W = W - lr * dL/dW
                          ▲                          │
                          └──────────── repeat for many mini-batches ◀──────────┘
 probability: what outputs mean      statistics: is the final model really better?
How to study this page For each concept, make sure you can do three things: explain it in one plain sentence, compute a tiny example by hand, and say where it is used in ML. Interviewers test exactly those three levels.
Interview angle ML interviews rarely ask you to prove theorems. They ask you to explain intuition ("why do we divide by √dk?"), do quick calculations (Bayes on a medical test, the mean and standard deviation of a small list, a softmax by hand), and connect math to practice ("why does MSE assume Gaussian noise?"). The strongest candidates tie each formula to a concrete model behavior.

Descriptive statistics: summarizing data

Before training anything, you need to understand your data. Descriptive statistics compress a column of thousands of numbers into a handful of summaries: where the center is, how spread out the values are, what shape the distribution has, and which points are unusual. These summaries drive decisions such as how to scale features, whether to use the mean or median to fill missing values, and which rows might be data-entry errors.

Analogy

Describing a dataset is like describing a city's weather to a friend who has never visited. "Average 25 degrees" is the center (mean). "But it ranges from 10 at night to 40 in the afternoon" is the spread (range, standard deviation). "Most days are mild, with a few scorching heatwaves" is the shape (skew). "Once it snowed, which never happens" is an outlier. A single number never tells the whole story; the combination does, and ML practitioners need the combination before choosing preprocessing steps.

Measures of central tendency: mean, median, mode

We will use one running example: x = [22, 18, 14, 10, 15, 20, 25, 12] (n = 8).

Mean: x̄ = (1/n) Σi xi = (22+18+14+10+15+20+25+12)/8 = 136/8 = 17 The balance point of the data. Uses every value, so it is pulled by extreme values.
  • Median: sort the data, take the middle. Sorted: [10, 12, 14, 15, 18, 20, 22, 25]. With an even count, average the two middle values: (15 + 18)/2 = 16.5. For odd n it is simply the middle element.
  • Mode: the most frequent value. A dataset can be unimodal, multimodal (several values tie) or have no mode (all values unique, as here). Mode is the only center measure that works for categorical data ("most common city").
  • Weighted mean: Σ wixi / Σ wi. Used for class-weighted metrics and averaging over batches of unequal size.
  • Geometric mean: (Π xi)1/n, the right average for growth rates and ratios. BLEU is a geometric mean of n-gram precisions.
  • Harmonic mean: n / Σ(1/xi), the right average for rates. F1 is the harmonic mean of precision and recall.

Robustness. Add one outlier, 250, to the example. The mean jumps from 17 to (136 + 250)/9 ≈ 42.9, far away from every normal value, while the median only moves from 16.5 to 18. This is why the median is preferred for skewed quantities such as income, house prices, request latency and time-on-page, and why "median latency" and "p99 latency" are reported instead of the mean.

Use the mean when

  • Data is roughly symmetric, few outliers
  • You need a quantity with nice algebra (sums, expectations, gradients)
  • Imputing a normally distributed feature

Use the median when

  • Data is skewed (income, latency, prices)
  • Outliers or data-entry errors are likely
  • Imputing a skewed feature; reporting "typical" values

Measures of position: quantiles, percentiles, quartiles

Quantiles cut sorted data into equal-sized chunks. The median is the 0.5 quantile (half below, half above). Quartiles cut into four parts (Q1 = 25th percentile, Q2 = median, Q3 = 75th percentile), deciles into ten, percentiles into a hundred, and tertiles into three. They tell you the relative standing of a value: "this response time is at the 99th percentile" means 99% of requests were faster.

When the cut point falls between two data points, most libraries (NumPy's default "linear" method) interpolate. With 0-based indexing, the position of quantile q in sorted data of length n is p = q(n − 1); the value is x⌊p⌋ + (p − ⌊p⌋)(x⌊p⌋+1 − x⌊p⌋).

  1. Sort [10, 12, 14, 15, 18, 20, 22, 25], n = 8.
  2. Q1 position 0.25 × 7 = 1.75, between index 1 (12) and index 2 (14). Value = 12 + 0.75 × (14 − 12) = 13.5.
  3. Q3 position 0.75 × 7 = 5.25, between 20 and 22. Value = 20 + 0.25 × 2 = 20.5.
  4. IQR = Q3 − Q1 = 20.5 − 13.5 = 7. This is the spread of the middle 50% of the data.
  5. Tertile example For [15, 18, 67, 100, 21, 50], sorted [15, 18, 21, 50, 67, 100], the 1/3 quantile sits at position 5/3 ≈ 1.67, giving 18 + 0.67 × 3 = 20; the 2/3 quantile sits at 3.33, giving 50 + 0.33 × 17 ≈ 55.7.
import numpy as np
x = np.array([22, 18, 14, 10, 15, 20, 25, 12])
q1, med, q3 = np.percentile(x, [25, 50, 75])   # 13.5, 16.5, 20.5
iqr = q3 - q1                                   # 7.0
np.quantile([15, 18, 67, 100, 21, 50], [1/3, 2/3])  # [20.0, 55.67]
Common pitfall Different tools use different interpolation rules (NumPy has nine methods; Excel's PERCENTILE.INC and PERCENTILE.EXC differ). On small samples the answers differ noticeably. State the method, or use a large sample where it does not matter.

Box plots and the IQR outlier rule

A box plot draws the five-number summary: minimum, Q1, median, Q3, maximum. The box spans Q1 to Q3, a line marks the median, and "whiskers" extend to the most extreme points within 1.5 × IQR of the box. Points beyond the whiskers are drawn individually as potential outliers.

Lower fence = Q1 − 1.5 × IQR = 13.5 − 10.5 = 3     Upper fence = Q3 + 1.5 × IQR = 20.5 + 10.5 = 31 Any value below 3 or above 31 is flagged. The outlier 250 from before would clearly be flagged; all original points are inside.
          whisker      box (middle 50%)      whisker
   10 |-----------[ 13.5 ===|=== 20.5 ]------------| 25          o 250  (outlier)
                  Q1      median 16.5    Q3
     fences: 3 ............................................ 31

Measures of variability (spread)

Two datasets can share a mean and be completely different: [49, 50, 51] and [0, 50, 100] both average 50. Spread measures capture that difference.

MeasureFormulaExample valueNotes
Rangemax − min25 − 10 = 15Uses only two points; very sensitive to outliers
IQRQ3 − Q17Robust; ignores the outer 50%
Mean absolute deviation(1/n) Σ|xi − x̄|34/8 = 4.25Same units as data; less outlier-sensitive than variance
Population variance σ2(1/n) Σ(xi − μ)2186/8 = 23.25Squared units; heavily weights large deviations
Sample variance s2(1/(n−1)) Σ(xi − x̄)2186/7 ≈ 26.57Unbiased estimate of population variance
Standard deviation√varianceσ ≈ 4.82, s ≈ 5.15Back in original units
Coefficient of variationσ / μ4.82/17 ≈ 0.28Unit-free; compare spread across scales

The squared deviations for the example are 25, 1, 9, 49, 4, 9, 64, 25, which sum to 186. Squaring does two things: it stops positive and negative deviations from cancelling out (they always sum to exactly zero around the mean), and it makes a deviation of 8 count four times as much as a deviation of 4.

Shortcut: Var(X) = E[X2] − (E[X])2 "Mean of the squares minus square of the mean". Handy for streaming computation, but numerically unstable when the mean is large compared to the spread; use Welford's algorithm in production.

Why divide by n − 1 (Bessel's correction)?

The sample mean x̄ is computed from the same data, and it is by construction the point that minimizes the sum of squared deviations. So deviations from x̄ are systematically a little smaller than deviations from the true, unknown μ. Dividing by n − 1 instead of n exactly corrects that bias on average. Another way to say it: once you know x̄ and n − 1 of the deviations, the last deviation is determined, so only n − 1 are "free" (degrees of freedom). For n in the thousands the difference is negligible; for n = 5 it is 25%.

x = np.array([22, 18, 14, 10, 15, 20, 25, 12])
x.var()          # 23.25   population (ddof=0) - NumPy default
x.var(ddof=1)    # 26.57   sample - pandas .var() default!
x.std(), x.std(ddof=1)   # 4.82, 5.15
Common pitfall NumPy's np.std defaults to ddof=0 while pandas' Series.std defaults to ddof=1. The same column gives two different answers depending on the library. Always set ddof explicitly when it matters.

Shape: skewness and kurtosis

Skewness measures asymmetry: E[((X − μ)/σ)3]. Positive (right) skew means a long tail to the right, with mean > median (income, latency, file sizes). Negative (left) skew means a long left tail, mean < median (exam scores on an easy test, age at retirement). Zero skew means symmetric, like the normal distribution. For example, [1, 2, 2, 3, 3, 3, 4, 10] has skewness ≈ 1.8 because of the single 10.

Kurtosis measures tail heaviness: E[((X − μ)/σ)4]. A normal distribution has kurtosis 3, so "excess kurtosis" = kurtosis − 3 is usually reported. High excess kurtosis (leptokurtic, e.g. financial returns, Student-t) means extreme values happen far more often than a Gaussian would predict, which matters for risk models and for choosing robust losses.

  right (positive) skew          symmetric              left (negative) skew
      |\                            /\                              /|
      | \__                        /  \                          __/ |
      |    \_____                 /    \                   _____/    |
   mode < median < mean      mean = median = mode      mean < median < mode
Tip For strongly right-skewed positive features (prices, counts, durations), a log transform log(1 + x) often makes them roughly symmetric, which helps linear models and distance-based methods.

Z-scores and standardization

A z-score expresses a value as "how many standard deviations from the mean".

z = (x − μ) / σ Example: exam mean 70, standard deviation 10. A score of 85 has z = 1.5; a score of 55 has z = −1.5. Under a normal distribution about 93.3% of students scored below 85.

Z-scores let you compare apples and oranges (a height z-score vs. a weight z-score), and the z-score outlier rule flags |z| > 3 as unusual. Standardizing an entire feature (subtract the mean, divide by the standard deviation) gives it mean 0 and standard deviation 1, which is the default preprocessing for linear models, SVMs, k-NN, PCA and neural networks. Min-max normalization, x' = (x − min)/(max − min), instead squeezes values into [0, 1] and is common for pixel intensities.

Common pitfall Fit the scaler (mean, standard deviation, min, max) on the training set only, then apply the same numbers to validation and test data. Computing them on the full dataset leaks information from the test set into training.

Outliers: detecting and handling them

  • Detection: IQR fences (robust, no normality assumption), z-score > 3 (assumes roughly normal data, and the outlier itself inflates σ), modified z-score using the median and median absolute deviation (robust), Mahalanobis distance for multivariate data, and model-based methods such as Isolation Forest.
  • Handling: first ask whether it is an error (a negative age, a 999 sentinel) or a genuine rare event (a real fraud). Fix or drop errors. For genuine extremes, consider capping/winsorizing at the 1st/99th percentile, log-transforming, using robust statistics (median, IQR), robust losses (MAE, Huber), or tree models, which are largely insensitive to monotonic scaling.
  • Never drop outliers blindly in fraud or anomaly detection; there the outliers are the signal.
Interview angle Expect "mean vs. median for imputation?", "why n − 1?", "how would you detect outliers?" and a quick calculation of the mean, median and standard deviation of five numbers. A strong answer mentions robustness, skew, the IQR rule, and that the choice depends on whether outliers are errors or signal.

Probability foundations and Bayes' theorem

Probability is the mathematics of uncertainty. Almost every ML output is a probability statement: "92% spam", "the next token is 'Paris' with probability 0.41". To interpret those numbers, combine them, and avoid classic traps, you need a handful of rules.

Analogy

A weather forecaster who says "30% chance of rain" is not claiming it will rain 30% of the day; she means that on days that look like today, it rains about 3 times in 10. When you then see dark clouds (new evidence), you update that 30% upward. That is conditional probability and Bayes' theorem. In ML, the "days that look like today" are inputs with similar features, and the update from a prior to a posterior is exactly what a Bayesian classifier or a spam filter does when it sees a new word.

The vocabulary

  • Sample space S: all possible outcomes (a die: {1, 2, 3, 4, 5, 6}).
  • Event A: a subset of outcomes you care about ("even" = {2, 4, 6}).
  • Probability P(A): a number in [0, 1]. For equally likely outcomes, P(A) = favorable / total = 3/6.
  • Complement Ac: "not A". P(Ac) = 1 − P(A).
  • Axioms (Kolmogorov): P(A) ≥ 0; P(S) = 1; for mutually exclusive events, P(A ∪ B) = P(A) + P(B). Everything else is derived from these three.

The core rules

RuleFormulaUse when
Addition (general)P(A ∪ B) = P(A) + P(B) − P(A ∩ B)A or B (or both). Subtract the overlap so it is not counted twice.
MultiplicationP(A ∩ B) = P(A) · P(B | A)A and B happen together
IndependenceP(A ∩ B) = P(A) · P(B)Knowing A tells you nothing about B
ConditionalP(A | B) = P(A ∩ B) / P(B)Restrict attention to the world where B happened
Total probabilityP(B) = Σi P(B | Ai) P(Ai)Ai partition the space (e.g. sick/healthy)
Chain ruleP(A, B, C) = P(A) P(B | A) P(C | A, B)Factorizing a joint; this is how language models score a sentence
Complement trickP(at least one) = 1 − P(none)"At least one" questions

Worked example (complement trick). An LLM agent calls a tool that fails 5% of the time, independently. Over 10 calls, P(at least one failure) = 1 − 0.9510 = 1 − 0.599 = 0.401. A small per-step error rate compounds quickly in multi-step pipelines, which is why agent reliability degrades with chain length.

Joint, marginal and conditional probability

These three are easiest to understand from a table. Over 100 observed days:

Heavy trafficLight trafficRow total
Rainy301040
Sunny154560
Column total4555100
  • Joint P(Rainy, Heavy) = 30/100 = 0.30: both at once; read from a cell.
  • Marginal P(Rainy) = 40/100 = 0.40: one variable alone; read from a total. "Marginalizing out" traffic means summing over it: P(Rainy) = P(Rainy, Heavy) + P(Rainy, Light).
  • Conditional P(Heavy | Rainy) = 30/40 = 0.75: restrict to the rainy row.
  • Flipped conditional P(Rainy | Heavy) = 30/45 ≈ 0.67. Not the same! P(A | B) ≠ P(B | A) in general, and confusing the two is the "prosecutor's fallacy".

The joint always factorizes both ways: P(A, B) = P(A | B) P(B) = P(B | A) P(A). Rearranging that identity gives Bayes' theorem. In ML terms, a discriminative classifier (logistic regression, most neural nets) models the conditional P(y | x); a generative model (Naive Bayes, GMMs, VAEs, diffusion, LLMs over text) models a joint or the data distribution P(x) and can sample new data.

Independence and conditional independence

A and B are independent if P(A | B) = P(A). In the table, P(Heavy) = 0.45 but P(Heavy | Rainy) = 0.75, so rain and traffic are dependent. Conditional independence means A and B are independent once you know C: P(A, B | C) = P(A | C) P(B | C). Ice-cream sales and drownings are correlated, but conditionally independent given temperature. Naive Bayes assumes all features are conditionally independent given the class, which is almost never true but works surprisingly well for text.

Common pitfall Mutually exclusive is not the same as independent. If A and B cannot happen together (P(A ∩ B) = 0) and both have positive probability, they are strongly dependent: knowing A happened tells you B definitely did not.

Bayes' theorem

P(A | B) = P(B | A) · P(A) / P(B)     posterior = likelihood × prior / evidence P(A) prior: belief before evidence. P(B | A) likelihood: how probable the evidence is if A is true. P(B) evidence: total probability of the evidence, a normalizer computed with the law of total probability. P(A | B) posterior: updated belief.

Worked example 1: the medical test (base-rate fallacy)

A disease affects 1% of people. A test catches 95% of sick people (sensitivity) and wrongly flags 5% of healthy people (false-positive rate). You test positive. What is the chance you are sick?

  1. Prior P(sick) = 0.01, P(healthy) = 0.99.
  2. Likelihoods P(+ | sick) = 0.95, P(+ | healthy) = 0.05.
  3. Evidence P(+) = 0.95 × 0.01 + 0.05 × 0.99 = 0.0095 + 0.0495 = 0.059.
  4. Posterior P(sick | +) = 0.0095 / 0.059 ≈ 0.161, only about 16%.
  5. Second independent positive test Use 0.161 as the new prior: 0.95 × 0.161 / (0.95 × 0.161 + 0.05 × 0.839) ≈ 0.785. Evidence accumulates.

The intuition with counts: out of 10,000 people, 100 are sick and 95 of them test positive; of the 9,900 healthy people, 495 test positive. So 95 of 590 positives are truly sick, about 16%. The rare condition means false alarms from the huge healthy group swamp the true positives. This is exactly why fraud and anomaly detectors with seemingly high accuracy still produce mostly false alerts, and why precision collapses on imbalanced data.

Worked example 2: a spam filter

30% of emails are spam. 80% of spam contains the word "free"; 25% of all emails contain "free". Then P(spam | "free") = 0.8 × 0.3 / 0.25 = 0.96. Naive Bayes extends this to many words by multiplying the per-word likelihoods (in log space, adding log-likelihoods) under the conditional independence assumption.

def bayes(prior, sens, fpr):
    evidence = sens * prior + fpr * (1 - prior)
    return sens * prior / evidence

p1 = bayes(0.01, 0.95, 0.05)   # 0.161
p2 = bayes(p1, 0.95, 0.05)     # 0.785  (second positive test)

Counting: permutations and combinations

Many probability questions reduce to counting equally likely outcomes. Permutations count ordered arrangements: P(n, k) = n!/(n − k)!. Combinations count unordered selections: C(n, k) = n!/(k!(n − k)!). For example, the number of ways to pick 3 features out of 10 is C(10, 3) = 120; the number of 7-heads outcomes in 10 coin flips is also C(10, 7) = 120, so P(exactly 7 heads) = 120/1024 ≈ 0.117.

Interview angle The medical-test Bayes question is the single most common probability interview question. Do it with counts out of 10,000 so the interviewer sees the intuition, then give the formula. Follow-ups include "what if the prevalence were 10%?" (posterior jumps to about 68%) and "how does this relate to precision?" (the posterior P(sick | +) is exactly the precision of the test).

Random variables, expectation, variance and covariance

A random variable turns random outcomes into numbers so we can do arithmetic on them. Once we have numbers, we can ask for the average outcome (expectation), how much outcomes wobble (variance), and whether two quantities move together (covariance and correlation). These are the workhorses behind every loss function, every initialization scheme and PCA.

Analogy

A random variable is a scoreboard attached to a game of chance: roll a die, and the scoreboard shows the face value. Expectation is what the scoreboard averages over a very long evening of play. Variance is how much the scoreboard jumps around from roll to roll. Covariance is whether two scoreboards (say, points scored and crowd noise) tend to rise and fall together. In ML the "game" is drawing a random training example, and the loss you minimize is literally the expected value of the loss scoreboard over the data distribution.

Discrete vs. continuous

Discrete random variable

  • Countable values: die faces, click counts, token IDs
  • Described by a probability mass function (PMF): P(X = x)
  • PMF values sum to 1

Continuous random variable

  • Any value in a range: height, latency, a weight
  • Described by a probability density function (PDF) f(x); probabilities are areas: P(a ≤ X ≤ b) = ∫ab f(x) dx
  • P(X = exact value) = 0; density values can exceed 1

The cumulative distribution function (CDF) F(x) = P(X ≤ x) works for both. It rises from 0 to 1, and its inverse (the quantile function) answers "what value is exceeded only 10% of the time?". Integration is how we get from a density to a probability, which is the main use of integral calculus in ML: normalizing distributions, computing expectations, and areas such as ROC-AUC.

Expectation

E[X] = Σx x · p(x)  (discrete)     E[X] = ∫ x · f(x) dx  (continuous) A probability-weighted average. Fair die: (1+2+3+4+5+6)/6 = 3.5. Biased die with P(1) = 0.5, P(2..6) = 0.1 each: 0.5 + 0.1(2+3+4+5+6) = 2.5.
  • Linearity: E[aX + bY + c] = aE[X] + bE[Y] + c, always, even if X and Y are dependent. This makes many problems trivial: the expected number of fixed points in a random shuffle of n items is n × (1/n) = 1.
  • Function of a variable: E[g(X)] = Σ g(x)p(x). In general E[g(X)] ≠ g(E[X]); Jensen's inequality says for convex g, E[g(X)] ≥ g(E[X]). This is why the ELBO is a lower bound and why log of an average ≥ average of logs.
  • Products: E[XY] = E[X]E[Y] only if X and Y are uncorrelated (independence is sufficient).
  • In ML: MSE = E[(ŷ − y)2], cross-entropy = E[−log p(y | x)], an RL return is an expected reward. Training minimizes an empirical average that approximates this expectation.

Variance and standard deviation

Var(X) = E[(X − μ)2] = E[X2] − (E[X])2 Fair die: E[X2] = 91/6 ≈ 15.17, so Var = 15.17 − 3.52 = 35/12 ≈ 2.92 and σ ≈ 1.71.
  • Var(aX + b) = a2 Var(X): shifting does not change spread; scaling by a scales variance by a2.
  • Var(X + Y) = Var(X) + Var(Y) + 2 Cov(X, Y). For independent variables the covariance term vanishes.
  • Average of n independent copies: Var(x̄) = σ2/n. This one identity explains why larger batches give less noisy gradients, why ensembles help, and why standard errors shrink with √n.
  • Sum of n independent unit-variance terms has variance n. This is why attention scores are divided by √dk and why Xavier/He initialization scales weights by 1/√fan-in.

Covariance and correlation

Cov(X, Y) = E[(X − μX)(Y − μY)] = E[XY] − E[X]E[Y]     ρ(X, Y) = Cov(X, Y) / (σX σY) ∈ [−1, 1] Covariance has awkward units (metres × kilograms) and depends on scale; Pearson correlation ρ is unit-free.

Worked example. Hours studied X = [1, 2, 3, 4, 5], score Y = [52, 55, 61, 64, 68]. Means: 3 and 60. Deviations of X: [−2, −1, 0, 1, 2]; of Y: [−8, −5, 1, 4, 8]. Products: 16, 5, 0, 4, 16, sum 41. Sample covariance = 41/4 = 10.25. Sample standard deviations: √(10/4) ≈ 1.58 and √(170/4) ≈ 6.52. Correlation = 10.25/(1.58 × 6.52) ≈ 0.99, a near-perfect positive linear relationship.

  • ρ = +1 or −1: perfect linear relationship; ρ = 0: no linear relationship.
  • Zero correlation does not imply independence. If X is symmetric around 0 and Y = X2, then Cov(X, Y) = E[X3] = 0, yet Y is completely determined by X.
  • Correlation is not causation. A hidden confounder can drive both variables.
  • Spearman correlation is Pearson on ranks; it captures any monotonic relationship and is robust to outliers. Kendall's tau counts concordant vs. discordant pairs.
  • Pearson correlation between two mean-centered vectors equals their cosine similarity.

The covariance matrix

For d features, the covariance matrix Σ is d × d with variances on the diagonal and covariances off-diagonal. It is always symmetric and positive semi-definite (all eigenvalues ≥ 0). With a centered data matrix Xc (n × d), Σ = XcTXc/(n − 1). Its eigenvectors are the principal components (see PCA below), its trace is the total variance, and its inverse appears in the multivariate normal density and the Mahalanobis distance.

import numpy as np
X = np.array([1, 2, 3, 4, 5]); Y = np.array([52, 55, 61, 64, 68])
np.cov(X, Y)          # [[2.5, 10.25], [10.25, 42.5]]  (ddof=1 by default!)
np.corrcoef(X, Y)[0, 1]   # 0.994
data = np.random.randn(1000, 3)
Sigma = np.cov(data, rowvar=False)   # 3x3; rows are samples
Common pitfall np.cov treats each row as a variable by default. For the usual "rows are samples" layout, pass rowvar=False, otherwise you get an n × n matrix instead of d × d.
Interview angle Common probes: "Is zero correlation the same as independence?" (no, give the X, X2 example), "What is Var(X − Y)?" (Var X + Var Y − 2Cov), "Why is the covariance matrix positive semi-definite?" (vTΣv is the variance of the projection vTx, which cannot be negative), and "How does multicollinearity hurt linear regression?" (unstable, inflated coefficient variance because XTX is near-singular).

Probability distributions you must know

A distribution is the "shape" of randomness: which values are possible and how likely each one is. A small family of distributions covers most of ML, and each one comes with a story about how data is generated. Knowing the story tells you which distribution (and therefore which loss function) fits a problem.

Analogy

Distributions are like templates for different kinds of queues and games. A single coin flip is Bernoulli. Counting how many of 100 shoppers buy something is binomial. Counting how many customers walk in per hour is Poisson, and the waiting time between walk-ins is exponential. The heights of all the shoppers pile up in a bell curve, the normal distribution. When you model a problem, you pick the template whose story matches how your data is generated, and the ML loss follows from that choice.

Discrete distributions

DistributionStoryPMFMeanVarianceML use
Bernoulli(p)One yes/no trialpx(1−p)1−x, x ∈ {0,1}pp(1−p)Binary labels; sigmoid output; binary cross-entropy is its negative log-likelihood
Binomial(n, p)Number of successes in n independent trialsC(n,k) pk(1−p)n−knpnp(1−p)Conversions out of n visitors; A/B tests
Categorical(p1..K)One draw from K classespk––Softmax output; next-token prediction
MultinomialCounts per class over n drawsn!/Πxk! · Πpkxknpknpk(1−pk)Bag-of-words; topic models
Geometric(p)Trials until first success(1−p)k−1p1/p(1−p)/p2Retries until success
Poisson(λ)Count of rare events in a fixed intervalλke−λ/k!λλRequests per second, defects per batch; Poisson regression

Worked examples. Binomial: 10 fair coin flips, P(exactly 7 heads) = C(10,7)(0.5)10 = 120/1024 ≈ 0.117. Poisson: a server averages λ = 3 errors per hour; P(0 errors) = e−3 ≈ 0.050 and P(2 errors) = 9e−3/2 ≈ 0.224. The Poisson is the limit of a binomial with large n and small p (np = λ); a Poisson whose variance is much larger than its mean signals overdispersion, where a negative binomial fits better.

Continuous distributions

DistributionStoryDensityMeanVarianceML use
Uniform(a, b)All values in [a, b] equally likely1/(b−a)(a+b)/2(b−a)2/12Random init, random search, dropout masks
Normal(μ, σ2)Sum of many small independent effects(1/(σ√(2π))) e−(x−μ)2/(2σ2)μσ2Noise model behind MSE; init; VAE latents; diffusion noise
Exponential(λ)Waiting time between Poisson eventsλe−λx, x ≥ 01/λ1/λ2Time-to-event, survival, inter-arrival times
Laplace(μ, b)"Pointy" symmetric, heavier tails(1/2b) e−|x−μ|/bμ2b2Noise model behind MAE; prior behind L1
Student-t(ν)Normal with uncertain varianceheavy tails0 (ν > 1)ν/(ν−2) for ν > 2; infinite if 1 < ν ≤ 2t-tests; robust regression; t-SNE
Beta(α, β)A probability of a probability, on [0, 1]∝ xα−1(1−x)β−1α/(α+β)αβ/((α+β)2(α+β+1))Prior on a click rate; Thompson sampling
Dirichlet(α1..K)Multi-class Beta: a random probability vector∝ Π xkαk−1αk/Σα–Prior on topic mixtures (LDA), on class proportions

Exponential example. Customers arrive at λ = 2 per hour. Mean wait between arrivals is 1/2 hour, and P(wait > 1 hour) = e−2 ≈ 0.135. The exponential is memoryless: having already waited 30 minutes does not change the distribution of the remaining wait.

Beta as a conjugate prior. If your prior on a click-through rate is Beta(α, β) and you observe k clicks in n views, the posterior is Beta(α + k, β + n − k). You can think of α and β as "pseudo-counts" of prior successes and failures. The Dirichlet does the same for K categories (it is the conjugate prior of the categorical/multinomial), which is why add-one (Laplace) smoothing in Naive Bayes corresponds to a Dirichlet(1, ..., 1) prior.

The normal distribution in depth

The normal (Gaussian) distribution is the star of statistics because of the central limit theorem (sums and averages of many independent effects become normal) and because it is mathematically convenient: sums of independent normals are normal, it is fully described by two numbers, and it has maximum entropy for a given mean and variance.

  • 68-95-99.7 rule: about 68% of values lie within ±1σ, 95% within ±2σ (more precisely ±1.96σ), 99.7% within ±3σ.
  • Standard normal Z ~ N(0, 1); any normal converts with z = (x − μ)/σ.
  • Worked example: exam scores ~ N(70, 102). P(60 ≤ X ≤ 80) = P(−1 ≤ Z ≤ 1) ≈ 0.683. The 90th percentile is 70 + 1.28 × 10 = 82.8.
  • Anomaly example: legitimate transaction amounts ~ N(50, 202). A $150 charge has z = 5, and P(Z ≥ 5) ≈ 3 × 10−7, a strong anomaly signal (if the normal assumption holds, which for money it often does not; heavy tails are common).
  • Multivariate normal N(μ, Σ): density ∝ exp(−½(x − μ)TΣ−1(x − μ)). Contours are ellipses aligned with the eigenvectors of Σ. Used in Gaussian mixture models, Gaussian processes, VAE latents and diffusion.
from scipy import stats
stats.norm.cdf(1) - stats.norm.cdf(-1)     # 0.683
stats.norm.ppf(0.90, loc=70, scale=10)     # 82.8
stats.binom.pmf(7, n=10, p=0.5)            # 0.117
stats.poisson.pmf(2, mu=3)                 # 0.224
stats.expon.sf(1, scale=1/2)               # 0.135  P(T > 1)
rng = np.random.default_rng(0)
rng.normal(0, 1, size=(3, 4)); rng.beta(2, 5, size=10); rng.dirichlet([1, 1, 1])
Common pitfall Assuming everything is normal. Latency, income, word frequencies and many counts are skewed or heavy-tailed (log-normal, power-law, Zipf). Using a z-score outlier rule on such data flags too many or too few points. Plot a histogram or Q-Q plot before assuming normality.
Interview angle "Which distribution would you use to model X?" is a favorite: clicks out of views (binomial), arrivals per minute (Poisson), time between arrivals (exponential), a conversion-rate belief (Beta), a class label (Bernoulli/categorical). Strong candidates also link distributions to losses: Gaussian noise gives MSE, Laplace gives MAE, Bernoulli gives binary cross-entropy, categorical gives softmax cross-entropy, Poisson gives Poisson deviance.

Sampling, the law of large numbers and the central limit theorem

We almost never see a whole population; we see a sample and use it to estimate population quantities. Two theorems explain why this works. The law of large numbers (LLN) says averages settle down to the truth as the sample grows. The central limit theorem (CLT) says the error of that average is approximately normal, which lets us build confidence intervals and hypothesis tests for almost any kind of data.

Analogy

Tasting soup: you do not drink the whole pot to judge the salt, you stir it and taste one spoonful. Stirring is random sampling (without it, the spoonful is biased). A bigger spoon gives a more reliable taste (LLN). And if many cooks each tasted a spoonful and wrote down their saltiness score, those scores would form a bell curve around the true saltiness even if the salt crystals themselves are unevenly shaped (CLT). A mini-batch is a spoonful of the training data, and its average gradient is a noisy but unbiased taste of the full-data gradient.

Populations, samples, estimators

  • Parameter: a fixed but unknown population value (μ, σ, p). Statistic/estimator: a quantity computed from a sample (x̄, s, p̂) that estimates it.
  • Bias of an estimator = E[estimate] − true value. x̄ is unbiased for μ; the 1/n variance is biased; the 1/(n−1) variance is unbiased.
  • Standard error (SE) = standard deviation of the estimator across repeated samples. For the mean, SE = σ/√n (estimated by s/√n). For a proportion, SE = √(p(1−p)/n).
  • Sampling schemes: simple random, stratified (sample within each class to keep proportions, as in train_test_split(stratify=y)), cluster, systematic. Bootstrap resampling (sampling with replacement from your sample) estimates the variability of any statistic without formulas.
  • Sampling bias: survivorship bias, selection bias, non-response bias. No amount of data fixes a biased sampling process.

Law of large numbers

x̄n = (1/n) Σi=1n Xi → E[X]  as  n → ∞ For i.i.d. samples with finite mean. With 10 fair coin flips you might see 70% heads; with 1,000 you will almost surely see between 45% and 55%. With a million flips the standard error is only 0.05 percentage points, so the rate stays within about 0.2 points of 50% almost always; claiming "exactly 50.0% to one decimal" would be only about one standard error, not a near-certainty.

LLN justifies empirical risk minimization (the training-set average loss approximates the expected loss), Monte Carlo estimation (average many random samples to estimate an integral), and trusting evaluation metrics computed on large test sets.

Central limit theorem

x̄n ≈ N(μ, σ2/n)    equivalently    (x̄n − μ)/(σ/√n) → N(0, 1) For i.i.d. samples with finite variance, regardless of the original distribution's shape. Rule of thumb: n ≥ 30 is often enough for moderately skewed data; heavily skewed data needs more.

Worked example. A single die roll is uniform on 1..6 (mean 3.5, σ ≈ 1.71), nothing like a bell. Average 100 rolls, and repeat 10,000 times: the averages form a bell curve centered at 3.5 with standard deviation 1.71/√100 ≈ 0.171. So about 95% of those averages fall in 3.5 ± 0.34.

rng = np.random.default_rng(0)
means = rng.integers(1, 7, size=(10_000, 100)).mean(axis=1)
means.mean(), means.std()      # about 3.5 and 0.171 - and a histogram is bell-shaped
Common pitfall The CLT is about the distribution of the sample mean, not the data. Collecting more data does not make a skewed feature normal. Also, the CLT fails for distributions without finite variance (e.g. Cauchy, some power laws), where averages never settle.

Why this matters in ML

  • Mini-batch SGD: the batch-mean gradient is unbiased with variance σ2/B. Quadrupling the batch size only halves the gradient noise, which is part of why learning rate is often scaled with batch size.
  • Confidence intervals on metrics: accuracy on 1,000 test examples at 90% has SE = √(0.9 × 0.1/1000) ≈ 0.0095, so a 95% CI of about ±1.9 points. A "0.5 point improvement" on that test set is noise.
  • A/B tests: differences in conversion rates are approximately normal by the CLT, which gives the z-test below.
  • Initialization: a neuron's pre-activation is a sum of many weighted inputs and is approximately normal; its variance grows with fan-in, motivating 1/fan-in scaling.
Interview angle "Explain the CLT to a non-technical person" and "Why does it matter for A/B tests?" are common. Mention: any distribution, averages become normal, spread shrinks as 1/√n, and that is what lets us put error bars on almost anything. A follow-up is "how many samples do I need to halve my error bar?" Answer: four times as many.

Inferential statistics: confidence intervals, hypothesis tests and A/B testing

Inferential statistics answers "is this pattern real, or could it be luck?" It is how you decide whether a new model is actually better, whether a product change moved a metric, or whether a feature is related to the target. ML engineers use it every time they run an online experiment or compare two models on a finite test set.

Analogy

A hypothesis test works like a criminal trial. The defendant (your new feature) is presumed innocent, meaning it has no effect (the null hypothesis). The prosecution presents evidence (data). The jury asks: "If the defendant were innocent, how surprising would this evidence be?" (the p-value). Only if the evidence would be very surprising under innocence (p below a pre-agreed threshold, α) do they convict (reject the null). Convicting an innocent person is a Type I error; letting a guilty one go is a Type II error. "Not guilty" is not the same as "proven innocent", just as failing to reject the null does not prove there is no effect.

Confidence intervals

CI = estimate ± critical value × SE     mean: x̄ ± zα/2 · s/√n     proportion: p̂ ± zα/2 · √(p̂(1−p̂)/n) z0.025 = 1.96 for 95%, 1.645 for 90%, 2.576 for 99%. For small samples of a mean, replace z with the t critical value with n−1 degrees of freedom.

Worked example. Average session length from n = 100 users is 50 seconds, with s = 10. SE = 10/√100 = 1. The 95% CI is 50 ± 1.96, i.e. [48.04, 51.96] seconds.

Correct interpretation: if we repeated the sampling procedure many times, 95% of the intervals built this way would contain the true mean. It is not "there is a 95% probability the true mean is in this particular interval" (that is the Bayesian credible interval's interpretation). Wider intervals come from more variability, smaller samples, or higher confidence levels.

Bootstrap CI: resample the data with replacement B = 1,000+ times, recompute the statistic each time, and take the 2.5th and 97.5th percentiles. This works for medians, F1 scores, AUC and anything else without a neat SE formula.

Bootstrap versus cross-validation

Both reuse the sample, but they answer different questions. The bootstrap estimates the sampling distribution of a statistic (a confidence interval or standard error for accuracy, F1, a median, or the gap between two models). Cross-validation estimates the expected performance of a training procedure by repeatedly holding out folds and retraining. Use the bootstrap on a frozen model and a test set when you want error bars; use CV on the training data when you want to compare algorithms or tune hyperparameters. Do not treat a bootstrap of the training loss as a substitute for a held-out fold: every bootstrap draw still overlaps heavily with the original sample, so it is optimistic for generalization. Out-of-bag scores from bagged trees are the exception that works, because each tree is scored only on rows it did not see.

scores = np.array(per_example_correct)     # 0/1 per test example
boot = [rng.choice(scores, size=len(scores), replace=True).mean() for _ in range(2000)]
lo, hi = np.percentile(boot, [2.5, 97.5])   # 95% bootstrap CI for accuracy

Hypothesis testing step by step

  1. State hypotheses Null H0: no effect (μA = μB). Alternative H1: an effect (μA ≠ μB for two-sided, or > for one-sided).
  2. Choose α before looking at data, usually 0.05. This is the Type I error rate you accept.
  3. Pick a test statistic that measures the effect in units of noise, e.g. t = (difference) / SE.
  4. Compute the p-value P(statistic at least this extreme | H0 true).
  5. Decide If p ≤ α, reject H0. Otherwise, fail to reject. Always report the effect size and a CI, not just the p-value.

What a p-value is and is not

  • It is the probability of seeing data at least as extreme as yours if the null hypothesis were true.
  • It is not the probability that the null is true, not the probability the result is due to chance, and not a measure of effect size. With huge n, a trivial 0.01% lift can have p < 0.001; with tiny n, a large real effect can have p = 0.3.

Type I and Type II errors, power

H0 true (no effect)H0 false (real effect)
Reject H0Type I error (false positive), probability αCorrect: power = 1 − β
Fail to rejectCorrect (probability 1 − α)Type II error (false negative), probability β

Power (usually targeted at 0.8) increases with sample size, effect size and α, and decreases with variance. There is a trade-off: lowering α to avoid false positives raises β unless you collect more data. In classifier terms, Type I errors are false positives (hurting precision) and Type II errors are false negatives (hurting recall).

The common tests and when to use them

TestQuestionStatisticAssumptions / notes
One-sample t-testIs the mean equal to a value μ0?t = (x̄ − μ0)/(s/√n), df = n−1Roughly normal data or large n
Two-sample t-test (Welch)Do two independent groups have the same mean?t = (x̄1 − x̄2)/√(s12/n1 + s22/n2)Welch does not assume equal variances; prefer it by default
Paired t-testSame units measured twice (before/after, model A vs. B on the same examples)?One-sample t on the differencesMuch more powerful than unpaired when pairs are correlated
z-test for proportionsDo two conversion rates differ?z = (p̂1 − p̂2)/√(p̂(1−p̂)(1/n1 + 1/n2))Large counts (np, n(1−p) ≥ 10)
Chi-square test of independenceAre two categorical variables related?χ2 = Σ (O − E)2/EExpected counts ≥ 5 per cell; else Fisher's exact test
Chi-square goodness of fitDoes data follow a claimed distribution?Same formula vs. expected frequenciese.g. is a die fair?
ANOVA (F-test)Do 3+ group means differ?F = between-group variance / within-group varianceFollow with post-hoc tests
Mann-Whitney U / WilcoxonNon-parametric alternatives to the t-testsRank-basedSkewed data, ordinal data, outliers
McNemar's testDo two classifiers differ on the same test set?Uses the disagreement countsPaired binary outcomes
Kolmogorov-SmirnovDo two samples come from the same distribution?Max CDF differenceData-drift monitoring

t-test example. A new model's average latency over n = 25 requests is 52 ms with s = 5 ms. Is it different from the 50 ms target? t = (52 − 50)/(5/√25) = 2.0 with 24 degrees of freedom, two-sided p ≈ 0.057. At α = 0.05 we fail to reject, though the evidence is borderline; more data would settle it. The t-distribution has heavier tails than the normal to account for estimating σ from a small sample; with n > 30 or so, t and z are nearly identical.

A/B testing worked end to end

Control (A): 1,000 users, 100 conversions (10.0%). Treatment (B): 1,000 users, 120 conversions (12.0%). Is B better?

  1. Pooled rate p̂ = (100 + 120)/2000 = 0.11.
  2. Standard error √(0.11 × 0.89 × (1/1000 + 1/1000)) ≈ 0.0140.
  3. z statistic (0.12 − 0.10)/0.0140 ≈ 1.43.
  4. p-value two-sided ≈ 0.153. Not significant at 0.05, even though the lift is a relative 20%.
  5. Same answer via chi-square On the 2×2 table [[100, 900], [120, 880]], expected counts are 110 and 890 per row; χ2 = 2(102/110) + 2(102/890) ≈ 2.04 = z2, same p-value.
  6. Sample size needed To detect 10% → 12% with α = 0.05 and 80% power: n ≈ (1.96 + 0.84)2 × (0.10 × 0.90 + 0.12 × 0.88)/0.022 ≈ 3,840 users per group. The test above was underpowered.
from statsmodels.stats.proportion import proportions_ztest
z, p = proportions_ztest(count=[120, 100], nobs=[1000, 1000])   # z=1.43, p=0.153
from scipy import stats
chi2, p, dof, expected = stats.chi2_contingency([[100, 900], [120, 880]], correction=False)
t, p = stats.ttest_ind(a, b, equal_var=False)   # Welch t-test
t, p = stats.ttest_rel(model_a_scores, model_b_scores)   # paired

A/B testing pitfalls

  • Peeking: checking the p-value daily and stopping when it dips below 0.05 inflates the false-positive rate far above 5%. Fix the sample size in advance or use sequential testing methods.
  • Multiple comparisons: test 20 metrics at α = 0.05 and you expect one false "win". Use Bonferroni (α/m) or control the false discovery rate (Benjamini-Hochberg).
  • Sample ratio mismatch: if a 50/50 split produced 52/48, randomization or logging is broken; a chi-square test detects it.
  • Novelty and primacy effects, weekly seasonality (run full weeks), network effects between users, and Simpson's paradox when segments have different mixes.
  • Statistical vs. practical significance: always report the effect size with a confidence interval and translate it into business impact.
Common pitfall Declaring a model better because its test accuracy is 0.3 points higher. On 2,000 test examples, the standard error of accuracy is about 0.7 points, so the difference is well within noise. Use a paired test (McNemar, or paired bootstrap on the same examples) and multiple random seeds.
Interview angle Expect to explain a p-value precisely, define Type I/II errors and power, compute a quick CI, and design an A/B test: hypothesis, primary metric, guardrail metrics, randomization unit, sample size from a minimum detectable effect, duration, and how you will avoid peeking and multiple-testing traps.

Linear algebra: vectors and matrices

Linear algebra is the engine room of ML. Every data point is a vector, every dataset and weight layer is a matrix, and nearly all computation in a neural network is matrix multiplication. GPUs exist in ML because they do matrix multiplications extremely fast in parallel. If you can read shapes and reason about matrix products, you can read most model code.

Analogy

A vector is like a GPS coordinate, but with as many coordinates as you have features: a house is [area, bedrooms, age], a word is 768 numbers in "meaning space". A matrix is a machine that takes a vector in and outputs a transformed vector: it can stretch, rotate, squash or project space, like a photo-editing filter applied to every point at once. A neural network layer is one such machine, and a deep network is a pipeline of machines with a non-linear "bend" between each so the pipeline cannot collapse into a single machine.

Scalars, vectors, matrices and your data

  • Scalar: a single number (a learning rate, a loss value).
  • Vector: an ordered list of numbers, a point or direction in n-dimensional space. A 28×28 grayscale image flattened is a vector in 784 dimensions; a word embedding is a vector in 768 or 4096 dimensions.
  • Matrix: a rectangular grid, m rows × n columns; element aij is row i, column j. A dataset of 3 houses with 4 columns (area, bedrooms, age, price) is a 3×4 matrix; a grayscale image is an H×W matrix and a color image is three stacked matrices (R, G, B).

Vector operations

OperationFormulaExample with a = [2, 3, 1], b = [4, −1, 5]Intuition
Additiona + b = [a1+b1, ...][6, 2, 6]Walk along a, then b
Scalar multiplyc·a2a = [4, 6, 2]Stretch or shrink
Dot producta·b = Σ aibi = |a||b|cos θ8 − 3 + 5 = 10How aligned two vectors are
L2 norm (length)||a||2 = √(Σ ai2)√14 ≈ 3.74Straight-line length
L1 norm||a||1 = Σ|ai|6City-block length
L∞ normmax |ai|3Largest coordinate
Unit vectora / ||a||[0.53, 0.80, 0.27]Direction only

The dot product is the single most important operation in ML. A neuron computes w·x + b. A linear classifier's decision is the sign of a dot product. Attention scores are dot products of queries and keys. Recommendation scores are dot products of user and item vectors: with Alice's tastes [action 0.9, romance 0.1, sci-fi 0.8] and a movie's profile [5.0, 0.5, 1.0], the predicted affinity is 4.5 + 0.05 + 0.8 = 5.35. Geometrically, a positive dot product means the vectors point roughly the same way, zero means they are orthogonal (perpendicular), negative means they point in opposite directions.

Norms in ML: L2 norms appear in weight decay (penalizing ||w||22), gradient clipping (rescale if ||g|| > threshold) and normalizing embeddings before cosine similarity. L1 norms appear in Lasso (penalizing ||w||1, which drives weights to exactly zero). The general Lp norm is (Σ|ai|p)1/p; the Frobenius norm of a matrix is the L2 norm of all its entries flattened.

Matrix multiplication

C = AB,   Cij = Σk Aik Bkj     (m × n) · (n × p) → (m × p) The inner dimensions must match; each output entry is the dot product of a row of A with a column of B. Cost: m · n · p multiply-adds.

Worked example. [[1, 2], [3, 4]] × [[5, 6], [7, 8]]: top-left = 1·5 + 2·7 = 19, top-right = 1·6 + 2·8 = 22, bottom-left = 3·5 + 4·7 = 43, bottom-right = 3·6 + 4·8 = 50. Result [[19, 22], [43, 50]]. Reversing the order gives [[23, 34], [31, 46]], a different answer.

  • Not commutative: AB ≠ BA in general (and BA may not even be defined).
  • Associative: (AB)C = A(BC). The order of evaluation can change cost dramatically: for a 1000×1000 A, B and a vector x, computing A(Bx) costs 2 million operations while (AB)x costs a billion.
  • Distributive: A(B + C) = AB + AC.
  • Element-wise (Hadamard) product A ⊙ B multiplies matching entries; it requires equal shapes and is used in gating (LSTM gates, SwiGLU). In NumPy, A * B is element-wise and A @ B is matrix multiplication.
  • Three views of Ax: dot products of each row of A with x; a linear combination of A's columns weighted by x's entries; a transformation of the vector x.

In a neural network, a batch of B inputs with d features is a B×d matrix X. A dense layer with h outputs has a d×h weight matrix W and a bias vector of length h: Z = XW + b is B×h. The bias is broadcast across rows. One matrix multiply processes the whole batch, which is why batching is so efficient on GPUs. Matrix factorization in recommender systems uses the same idea: a sparse users×movies rating matrix R is approximated by P (users×k) times Q (k×movies), and every unseen rating is predicted by one dot product.

import numpy as np
A = np.array([[1, 2], [3, 4]]); B = np.array([[5, 6], [7, 8]])
A @ B        # [[19, 22], [43, 50]]
A * B        # [[ 5, 12], [21, 32]]  element-wise
X = np.random.randn(32, 784)     # batch of 32 flattened images
W = np.random.randn(784, 128) * np.sqrt(2 / 784)   # He init
b = np.zeros(128)
Z = X @ W + b                    # (32, 128); b broadcasts over the batch
H = np.maximum(0, Z)             # ReLU

Transpose, identity, inverse, determinant, trace, rank

ConceptDefinitionExampleML relevance
Transpose ATSwap rows and columns; (AT)ij = Aji; (AB)T = BTAT[[1,2],[3,4]]T = [[1,3],[2,4]]QKT in attention; xTy as a dot product; backprop uses WT
Identity I1s on the diagonal; AI = IA = AI2 = [[1,0],[0,1]]Residual connections: y = x + F(x); ridge adds λI
Inverse A−1AA−1 = I; only for square, full-rank matrices2×2: (1/(ad−bc))[[d, −b], [−c, a]]Normal equation; Gaussian densities; rarely computed explicitly
Determinant det AVolume scaling factor of the transformation; det = 0 means space is squashed flatdet [[a,b],[c,d]] = ad − bcInvertibility check; Gaussian normalizer; normalizing flows
Trace tr ASum of diagonal = sum of eigenvaluestr [[1,2],[3,4]] = 5Total variance = tr(Σ); ||A||F2 = tr(ATA)
RankNumber of linearly independent rows (equivalently columns); the dimension of the output space[[1,2],[2,4]] has rank 1 (row 2 = 2 × row 1)Low-rank structure enables LoRA, matrix factorization, PCA compression

Worked inverse. A = [[2, 1], [1, 2]]: det = 2·2 − 1·1 = 3, so A−1 = (1/3)[[2, −1], [−1, 2]]. Check: row 1 of A times column 1 of A−1 = (2·2 + 1·(−1))/3 = 1. For [[1, 2], [2, 4]], det = 4 − 4 = 0: the matrix maps the whole plane onto a line, information is lost, and no inverse exists. Such a matrix is called singular.

Linear independence and span: vectors are linearly independent if none can be written as a combination of the others. The span is every point reachable by combining them. A basis is a minimal set that spans the space; in d dimensions any basis has d vectors. Duplicate or perfectly correlated features make a data matrix rank-deficient, which is the linear-algebra face of multicollinearity.

Special matrices: symmetric (A = AT, e.g. covariance matrices; they have real eigenvalues and orthogonal eigenvectors), orthogonal (QTQ = I; columns are orthonormal; pure rotations or reflections that preserve lengths and angles, used in orthogonal initialization and appearing in SVD), diagonal (scale each axis independently), positive definite (xTAx > 0 for all non-zero x; a bowl-shaped quadratic; Hessians of strictly convex functions), and sparse (mostly zeros; user-item matrices, one-hot features, TF-IDF matrices).

Solving linear systems and least squares

A system Ax = b has a unique solution x = A−1b when A is square and invertible. In ML we usually have more equations (samples) than unknowns (features), so there is no exact solution; we minimize the squared residual instead. That is linear regression.

w* = argminw ||Xw − y||2  ⇒  XTXw = XTy  ⇒  w* = (XTX)−1XTy The "normal equation". (XTX)−1XT is the pseudoinverse X+ for a tall full-rank X. Ridge regression uses (XTX + λI)−1XTy, which is always invertible for λ > 0.

Geometrically, Xw* is the orthogonal projection of y onto the column space of X: the residual is perpendicular to every feature column. In practice, you never form the inverse. Libraries solve with QR decomposition or SVD (np.linalg.lstsq), which is faster and far more numerically stable. For millions of rows or features, iterative methods (gradient descent) beat any closed form, since forming XTX costs O(nd2) and inverting it O(d3).

X = np.c_[np.ones(len(x)), x]          # add bias column
w, *_ = np.linalg.lstsq(X, y, rcond=None)   # stable least squares
# avoid: np.linalg.inv(X.T @ X) @ X.T @ y  (squares the condition number)
np.linalg.solve(A, b)                  # for square systems; never inv(A) @ b
Common pitfall Computing inv(X.T @ X). Forming XTX squares the condition number (the ratio of largest to smallest singular value), so a mildly ill-conditioned problem becomes numerically hopeless. Use lstsq, solve, QR or regularization.
Interview angle Typical questions: "What are the shapes in this layer?", "Is matrix multiplication commutative?", "When does a matrix have no inverse?", "What does rank mean intuitively?", and "Derive the normal equation." Be ready to say that neural networks without non-linearities collapse to a single matrix, because W2(W1x) = (W2W1)x.

Eigenvalues, SVD and PCA

Matrices can look complicated, but most of them have a few "natural axes" along which their behavior is simple. Eigen-decomposition and the singular value decomposition (SVD) find those axes. Principal component analysis (PCA) uses them to compress data by keeping only the directions where the data varies most. The same ideas power recommendation systems, latent semantic analysis, image compression, and the low-rank tricks used to fine-tune LLMs.

Analogy

Push a door anywhere and it swings in a complicated way; push exactly along its hinge axis and it only moves along that line. Eigenvectors are those special directions where a matrix acts like simple stretching, and the eigenvalue is how much it stretches. For PCA, imagine photographing a flat, elongated cloud of fireflies: turning the camera so its long side lines up with the cloud's longest direction captures the most detail with the fewest pixels. PCA rotates your feature axes to line up with the directions of greatest spread and then drops the thin directions that carry little information.

Eigenvalues and eigenvectors

A v = λ v     (v ≠ 0)     found by solving det(A − λI) = 0 v is an eigenvector (its direction is unchanged by A), λ is the eigenvalue (the stretch factor; negative flips direction, 0 collapses it).

Worked example. A = [[2, 1], [1, 2]]. The characteristic equation is (2 − λ)2 − 1 = 0, so λ = 3 or λ = 1. For λ = 3: (A − 3I)v = 0 gives v = [1, 1] (check: A[1, 1] = [3, 3] = 3[1, 1]). For λ = 1: v = [1, −1] (A[1, −1] = [1, −1]). The trace 4 equals 3 + 1 and the determinant 3 equals 3 × 1, which is always true: trace = sum of eigenvalues, determinant = product of eigenvalues.

  • Eigendecomposition: A = QΛQ−1 (eigenvectors as columns of Q, eigenvalues on the diagonal of Λ). For symmetric A, Q is orthogonal: A = QΛQT (the spectral theorem).
  • Powers: Ak = QΛkQ−1. Repeated multiplication blows up along eigenvalues with |λ| > 1 and dies along |λ| < 1. This is exactly the vanishing/exploding gradient story in RNNs, where the same weight matrix is applied at every time step.
  • Definiteness: all eigenvalues > 0 means positive definite (a bowl); mixed signs means indefinite (a saddle). The Hessian's eigenvalues classify critical points in optimization.
  • Other uses: PageRank is the leading eigenvector of a link matrix; spectral clustering uses eigenvectors of a graph Laplacian; the condition number of a symmetric positive definite matrix is λmax/λmin and controls how fast gradient descent converges.

Singular value decomposition (SVD)

A = U Σ VT     A: m×n, U: m×m orthogonal, Σ: m×n diagonal (σ1 ≥ σ2 ≥ ... ≥ 0), V: n×n orthogonal Works for any matrix, square or not. Any linear map = rotate (VT), scale along axes (Σ), rotate again (U). The singular values are the square roots of the eigenvalues of ATA.
  • Rank = number of non-zero singular values.
  • Truncated SVD: keep the top k singular values and vectors, Ak = UkΣkVkT. By the Eckart-Young theorem, this is the best possible rank-k approximation in both Frobenius and spectral norm.
  • Compression example: a 100×100 grayscale image has 10,000 numbers. Keeping k = 10 needs 100×10 + 10 + 10×100 = 2,010 numbers, about 80% smaller, and often preserves most visible structure because natural images are approximately low rank.
  • Uses: pseudoinverse and stable least squares; PCA; latent semantic analysis (SVD of a term-document matrix); collaborative filtering; denoising; and understanding LoRA, which assumes the fine-tuning weight update ΔW is approximately low rank and learns it as B (d×r) times A (r×d) with r as small as 8, cutting trainable parameters from d2 to 2dr.

PCA step by step

  1. Center (and usually standardize) Subtract each feature's mean. Standardize too if features have different units, otherwise the feature with the largest scale dominates.
  2. Covariance matrix Σ = XcTXc/(n − 1), a d×d symmetric matrix.
  3. Eigen-decompose The eigenvectors of Σ are the principal components (orthogonal directions); each eigenvalue is the variance of the data along its direction.
  4. Sort and choose k Rank components by eigenvalue. Explained variance ratio of component i = λi/Σλ. Pick k to reach, say, 95% cumulative variance, or use the "elbow" of a scree plot.
  5. Project Z = XcVk gives n×k coordinates. Reconstruct approximately with Z VkT + mean.

Worked example. Students scored in math, science and English give eigenvalues 5.2, 3.1 and 0.4 (total 8.7). Explained variance: 60%, 36% and 4%. Keeping the first two components retains 96% of the variance while dropping a third of the features. For the 2D covariance matrix [[2, 1], [1, 2]], PC1 is the direction [1, 1]/√2 with variance 3, explaining 3/(3 + 1) = 75% of the total.

from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
Xs = StandardScaler().fit_transform(X)
pca = PCA(n_components=0.95).fit(Xs)          # keep 95% of variance
Z = pca.transform(Xs)
pca.explained_variance_ratio_

# PCA from scratch via SVD (numerically preferred over eigh of the covariance)
Xc = X - X.mean(axis=0)
U, S, Vt = np.linalg.svd(Xc, full_matrices=False)
explained_var = S**2 / (len(X) - 1)
Z = Xc @ Vt[:k].T

PCA is good for

  • Removing correlated/redundant features
  • Speeding up downstream models; reducing noise
  • Visualizing the global structure of data
  • Whitening inputs

PCA limitations

  • Linear only; misses curved manifolds (use kernel PCA, t-SNE, UMAP, autoencoders)
  • Unsupervised: high variance is not the same as predictive of the label
  • Sensitive to scaling and outliers
  • Components are harder to interpret than raw features

t-SNE and UMAP are non-linear alternatives for visualization. t-SNE matches Gaussian neighborhoods in high dimensions to Student-t neighborhoods in 2D; it produces clean clusters, but cluster sizes and distances between clusters are not meaningful. UMAP preserves more global structure and scales better. Neither should be used as input features for a downstream model without care, since the embedding is not stable or invertible.

Common pitfall Running PCA without standardizing mixed-unit features (salary in dollars next to age in years); PC1 simply becomes "salary". Also, fitting PCA on the full dataset before the train/test split leaks test information.
Interview angle "Explain PCA" should hit: center the data, covariance matrix, eigenvectors are directions of maximum variance, eigenvalues are variances, keep the top k, project. Follow-ups: "Why are components orthogonal?" (eigenvectors of a symmetric matrix), "How do PCA and SVD relate?" (the right singular vectors of centered X are the PCs; λi = σi2/(n−1)), and "When would PCA hurt?" (when low-variance directions carry the signal).

Tensors, shapes and broadcasting

In deep learning code, "tensor" simply means a multi-dimensional array. Most bugs in model code are shape bugs, so reading and reasoning about shapes is a core practical skill. Broadcasting is the set of rules that lets you combine arrays of different shapes without writing loops, and it is the source of both elegant code and silent errors.

Analogy

Think of a warehouse. A scalar is one box. A vector is a shelf of boxes. A matrix is a whole rack of shelves. A 3D tensor is a row of racks, and a 4D tensor is several aisles of racks. Broadcasting is like applying the same price sticker to every box on a shelf: you do not need one sticker per box, the rule "stretch this one sticker across the shelf" is implied. Adding a bias vector to every row of a batch is exactly that sticker being stretched across all samples.

Common tensor shapes

RankShapeTypical meaning
0-D()A scalar loss
1-D(F,)A bias vector, a single embedding
2-D(B, F)Batch × features (tabular data, MLP activations)
3-D(B, T, D)Batch × tokens × embedding dimension (NLP, transformers)
4-D(B, C, H, W)Batch × channels × height × width (images in PyTorch; TensorFlow uses B, H, W, C)
4-D(B, h, T, dk)Multi-head attention: batch × heads × tokens × head dimension

Broadcasting rules

Compare shapes from the rightmost dimension leftward. Two dimensions are compatible if they are equal, or one of them is 1, or one is missing (treated as 1). The size-1 dimension is virtually stretched (no memory copy) to match.

  • (32, 784) + (784,) → (32, 784): the bias is added to each of 32 rows.
  • (B, 1, H, W) * (B, C, H, W) → (B, C, H, W): one mask applied to all channels.
  • (3, 1) + (1, 4) → (3, 4): an outer-sum table, handy for pairwise distances.
  • (32, 784) + (50,) → error: 784 vs. 50.
x = np.random.randn(5, 3)
mu, sd = x.mean(axis=0), x.std(axis=0)     # shapes (3,)
z = (x - mu) / sd                          # (5,3) - (3,) broadcasts: column-wise standardize
# pairwise squared distances between rows of A (n,d) and B (m,d) without loops
D2 = (A**2).sum(1)[:, None] + (B**2).sum(1)[None, :] - 2 * A @ B.T   # (n, m)

# the classic silent bug
y_true = np.array([1., 2., 3.])            # (3,)
y_pred = np.array([[1.], [2.], [3.]])      # (3,1)
(y_pred - y_true).shape                    # (3,3) !  MSE is now wrong, no error raised

Reshaping operations

  • reshape / view: same data, new shape; the total size must stay equal. (B, 28, 28) → (B, 784). Use -1 to infer one dimension.
  • transpose / permute: reorder axes. (B, H, W, C) → (B, C, H, W). In attention, (B, T, h, dk) → (B, h, T, dk) so each head is a separate batch of matrix multiplies.
  • squeeze / unsqueeze (NumPy expand_dims, or indexing with None): remove or add size-1 axes.
  • concatenate vs. stack: concatenate joins along an existing axis; stack creates a new axis. Stacking 32 vectors of shape (F,) gives (32, F).
  • einsum: a compact notation for tensor contractions. np.einsum('bhqd,bhkd->bhqk', Q, K) computes attention scores for all heads at once.
  • Reductions with axis: x.sum(axis=0) collapses rows (per-feature totals); keepdims=True keeps the axis so the result still broadcasts correctly, which is essential in softmax.
Common pitfall Mixing up (N,) and (N, 1) arrays. Subtracting one from the other broadcasts to (N, N) and silently produces a wrong loss. Assert shapes in your code, and use keepdims=True on reductions.
Interview angle Interviewers hand you shapes and ask for the output shape of a layer, an attention computation or a broadcasted operation, or show buggy code where a loss looks fine but is wrong. Walking right-to-left through the broadcasting rules out loud is the winning approach. See Python for ML for more NumPy practice.

Distance and similarity metrics

Much of ML is "find things that are similar": nearest-neighbor classification, clustering, retrieval for RAG, recommendation, deduplication and anomaly detection. The choice of distance or similarity metric defines what "similar" means, so the wrong metric silently ruins an otherwise good pipeline.

Analogy

There are many ways to say two places are "close". As the crow flies is Euclidean distance. The number of city blocks a taxi drives on a grid is Manhattan distance. Whether two people are walking in the same direction, regardless of how far each has walked, is cosine similarity. How many letters you would have to change to turn one street name into another is edit distance. Each metric answers a different question; in ML you pick the one that matches what "similar" should mean for your data.

The main metrics (A = [1, 3], B = [4, 7])

MetricFormulaExampleWhen to use
Euclidean (L2)√(Σ(ai − bi)2)√(9 + 16) = 5Dense, scaled, low-to-moderate dimensional data; k-means, k-NN
Manhattan (L1)Σ|ai − bi|3 + 4 = 7Grid-like features, robustness to single large differences, higher dimensions
Chebyshev (L∞)max |ai − bi|4"Worst coordinate" tolerance checks
Minkowski (Lp)(Σ|ai − bi|p)1/pp = 1, 2, ∞ give the aboveTunable hyperparameter in k-NN
Cosine similarity(a·b)/(||a|| ||b||)25/(√10 · √65) ≈ 0.981Text embeddings, TF-IDF vectors, anything where direction matters more than magnitude
Cosine distance1 − cosine similarity0.019Vector databases, clustering embeddings
Dot producta·b4 + 21 = 25Retrieval when magnitude carries meaning (popularity); maximum inner product search
Mahalanobis√((x − μ)TΣ−1(x − μ))–Correlated features; multivariate anomaly detection
HammingNumber of differing positions"1011" vs "1001" = 1Binary codes, hashes, equal-length strings
Jaccard similarity|A ∩ B| / |A ∪ B|{m1, m3} vs {m1, m2} = 1/3Sets, tags, shingled documents; IoU in object detection
Edit (Levenshtein)Minimum insert/delete/substitute operationskitten → sitting = 3Spell-check, fuzzy matching

Cosine vs. Euclidean. A 100-word and a 1,000-word document on the same topic have count vectors pointing in almost the same direction but with very different lengths: cosine says "very similar", Euclidean says "far apart". For L2-normalized vectors the two agree in ranking, because ||a − b||2 = 2 − 2 cos θ. That identity is why vector databases often normalize embeddings and then use fast inner-product search.

Mahalanobis intuition. It measures distance in units of standard deviation along each principal direction of the data. A point 3 units away along a tightly clustered direction is far more anomalous than a point 3 units away along a loose direction, and Mahalanobis captures that while Euclidean does not. With Σ = I it reduces to Euclidean distance.

Distributional "distances": KL divergence (asymmetric), Jensen-Shannon divergence (symmetric, bounded), Wasserstein or earth mover's distance (used in WGANs and drift detection), and the Kolmogorov-Smirnov statistic. These compare whole distributions rather than two points.

from numpy.linalg import norm
a, b = np.array([1, 3]), np.array([4, 7])
norm(a - b), norm(a - b, 1), norm(a - b, np.inf)   # 5.0, 7.0, 4.0
cos = a @ b / (norm(a) * norm(b))                  # 0.981
# batch cosine similarity: normalize once, then one matrix multiply
E = emb / norm(emb, axis=1, keepdims=True)
sims = E @ E.T                                     # (n, n)

The curse of dimensionality

In high dimensions, distances between random points concentrate: the nearest and farthest neighbors end up at nearly the same distance, so "nearest" loses meaning. Volume grows exponentially, so data becomes sparse, and a fixed-size neighborhood contains almost no points. Remedies include dimensionality reduction (PCA, learned embeddings), feature selection, using cosine similarity on meaningful embeddings, and models that do not rely on raw distances.

Common pitfall Running k-NN or k-means on unscaled features. A feature measured in thousands (income) completely dominates one measured in single digits (number of children). Standardize first, and check whether cosine suits the data better.
Interview angle "Why cosine for embeddings?" (magnitude often reflects frequency or length, not meaning; normalized vectors make cosine and Euclidean equivalent), "What happens to distances in high dimensions?" (concentration), and "Is cosine distance a true metric?" (no, it violates the triangle inequality; angular distance arccos(cos θ)/π is a metric). For how retrieval uses these metrics in practice, see NLP fundamentals.

Calculus: derivatives, gradients and the chain rule

Linear algebra lets a network compute; calculus lets it learn. A derivative tells you how much an output changes when you nudge an input. With millions of weights, the gradient collects one such sensitivity per weight into a vector that points uphill on the loss surface. Step the other way and the loss goes down. The chain rule lets us compute all those sensitivities efficiently through many layers, which is backpropagation.

Analogy

You are blindfolded on a hillside and want to reach the valley floor. You cannot see, but you can feel the slope under your feet. If the ground tilts down to the left, you step left; when it feels flat, you might be at the bottom. The slope you feel is the derivative (with many directions, the gradient), and repeatedly stepping downhill is gradient descent. The size of each step is the learning rate. The landscape is the loss function, and your position is the current set of weights.

Derivatives: the slope detector

f'(x) = limh→0 [f(x + h) − f(x)] / h The instantaneous rate of change. For f(x) = x2, f'(x) = 2x: at x = 3 the slope is 6 (steep uphill), at x = 0 it is 0 (the minimum), at x = −2 it is −4 (downhill to the right).
RuleFormulaExample
Constant(c)' = 0(7)' = 0
Power(xn)' = n xn−1(x3)' = 3x2
Sum(f + g)' = f' + g'(x2 + 3x)' = 2x + 3
Product(fg)' = f'g + fg'(x2 sin x)' = 2x sin x + x2 cos x
Quotient(f/g)' = (f'g − fg')/g2(x/(1+x))' = 1/(1+x)2
Chain[f(g(x))]' = f'(g(x)) · g'(x)((x2+1)3)' = 3(x2+1)2 · 2x
Exponential(ex)' = ex(e3x)' = 3e3x
Logarithm(ln x)' = 1/x(ln(x2))' = 2/x

Optimization by hand. A coffee shop's daily profit at price p is −20p2 + 200p − 300. Setting the derivative −40p + 200 to zero gives p = $5 and a profit of $200; at $4 or $6 profit is $180. The second derivative −40 < 0 confirms a maximum. Training a model is the same idea with millions of "prices", except we cannot solve the equation in closed form, so we walk towards it iteratively.

ML's must-know derivatives

  • Sigmoid: σ(x) = 1/(1 + e−x), σ'(x) = σ(x)(1 − σ(x)). Derivation: σ = (1 + e−x)−1, chain rule gives e−x/(1 + e−x)2, which factors into σ(1 − σ). Its maximum is 0.25 at x = 0; at x = 5 it is only 0.0066. That flatness causes vanishing gradients.
  • Tanh: tanh'(x) = 1 − tanh2(x), maximum 1 at 0.
  • ReLU: derivative 1 for x > 0, 0 for x < 0; undefined at exactly 0, where frameworks use a subgradient (0). Hitting exactly 0 is rare, so this does not matter in practice.
  • Softmax + cross-entropy: for logits z, softmax p and one-hot target y, ∂L/∂z = p − y. Beautifully simple: the gradient is "predicted minus true". The same is true for sigmoid + binary cross-entropy and for linear output + MSE (up to a constant).
  • MSE: d/dŷ (ŷ − y)2 = 2(ŷ − y).
  • L2 penalty: d/dw (λw2) = 2λw, which shrinks each weight towards 0 proportionally (weight decay). L1 penalty: d/dw (λ|w|) = λ sign(w), a constant push that can drive weights exactly to 0.

Partial derivatives and the gradient

With several inputs, a partial derivative asks "how does the output change if I nudge just this one input and hold the others fixed?". The gradient stacks all partial derivatives into a vector.

f(w1, w2) = w12 + 3w1w2 + w22    ∂f/∂w1 = 2w1 + 3w2    ∂f/∂w2 = 3w1 + 2w2 At (1, 2): ∇f = [8, 7]. The gradient points in the direction of steepest increase and its length is the rate of increase in that direction; −∇f is the steepest descent direction.

The directional derivative in unit direction u is ∇f · u, which is maximized when u points along ∇f (by the Cauchy-Schwarz inequality). The gradient is perpendicular to the contour lines (level sets) of the function. In a network with a billion weights, the gradient is a vector with a billion entries, one per weight.

Worked training step. A one-weight house-price model predicts ŷ = w · area + b. For a 1,500 sq ft house that sold for $300,000, with w = 100, b = 50,000, the prediction is $200,000 and the squared-error loss is (−100,000)2 = 1010. Then ∂L/∂w = 2(ŷ − y) · area = −3 × 108 and ∂L/∂b = 2(ŷ − y) = −2 × 105. Both are negative, so increasing w and b reduces loss. Notice how the gradient for w is 1,500 times larger than for b purely because of the feature's scale, which is why unscaled features make gradient descent zig-zag and need a tiny learning rate.

The chain rule: the heart of backpropagation

If y = f(u) and u = g(x): dy/dx = (dy/du) · (du/dx)     multivariable: ∂L/∂xi = Σj (∂L/∂uj)(∂uj/∂xi) Multiply local derivatives along a path; sum over all paths when a variable feeds several downstream quantities.

For a composition L = f(g(h(x))), dL/dx = f' · g' · h'. A neural network is a long composition, so the gradient of the loss with respect to an early weight is a product of many local derivatives. Computing these products from the output backwards, and reusing shared intermediate results, is backpropagation (next section).

Jacobian and Hessian

  • Jacobian J: for a vector function f: Rn → Rm, the m×n matrix of all first partial derivatives, Jij = ∂fi/∂xj. Example: f(x, y) = [x2y, 5x + sin y] has J = [[2xy, x2], [5, cos y]]. The chain rule for vector functions is a product of Jacobians; backprop computes vector-Jacobian products without ever materializing the full Jacobian. The softmax Jacobian is diag(p) − ppT.
  • Hessian H: for a scalar function, the n×n matrix of second partial derivatives, Hij = ∂2f/∂xi∂xj. It describes curvature. For f = w12 + 3w1w2 + w22, H = [[2, 3], [3, 2]], with eigenvalues 5 and −1. Mixed signs mean the origin (where the gradient is zero) is a saddle point, not a minimum.
  • Second-derivative test: at a point with zero gradient, H positive definite (all eigenvalues > 0) means local minimum, negative definite means local maximum, mixed signs mean saddle.
  • Cost: for n = 109 parameters, the Hessian has 1018 entries, so it is never formed. Methods use Hessian-vector products, diagonal approximations or quasi-Newton approximations (L-BFGS) instead.

Taylor series: why small gradient steps work

f(x + Δ) ≈ f(x) + f'(x)Δ + ½ f''(x)Δ2 + ...     multivariate: f(w + Δ) ≈ f(w) + ∇fTΔ + ½ ΔTHΔ Near any point, a smooth function looks like a line (first order) and more precisely like a parabola (second order).

Example: ex = 1 + x + x2/2 + x3/6 + ... At x = 1: one term gives 1, two give 2, three give 2.5, five give 2.708, versus the true 2.718.

  • Gradient descent comes from the first-order approximation: with Δ = −η∇f, f decreases by about η||∇f||2, as long as η is small enough that the linear approximation holds.
  • Newton's method minimizes the second-order approximation exactly: Δ = −H−1∇f. It converges in very few steps near a minimum but is too expensive for large networks and is attracted to saddle points.
  • Learning-rate limit: along a direction with curvature λ, gradient descent is stable only if η < 2/λ. The sharpest direction (largest Hessian eigenvalue) caps the learning rate for the whole model.

Integration in one paragraph

Integration is the reverse of differentiation and computes areas: ∫03 x2 dx = [x3/3]03 = 9. In ML it appears mostly in probability: a density integrates to 1, P(a ≤ X ≤ b) is an area, E[X] = ∫ x f(x) dx, and the Bayesian evidence P(data) = ∫ P(data | θ)P(θ) dθ is usually intractable, which is why we use Monte Carlo sampling and variational approximations. ROC-AUC is the integral of the ROC curve, computed numerically with the trapezoidal rule.

import torch
w = torch.tensor([1.0, 2.0], requires_grad=True)
f = w[0]**2 + 3*w[0]*w[1] + w[1]**2
f.backward()
w.grad                       # tensor([8., 7.])

# numerical gradient check (central difference) - use to test hand-written gradients
def num_grad(f, x, h=1e-5):
    g = np.zeros_like(x)
    for i in range(len(x)):
        e = np.zeros_like(x); e[i] = h
        g[i] = (f(x + e) - f(x - e)) / (2 * h)
    return g
Common pitfall Confusing "gradient is zero" with "at the minimum". In high-dimensional non-convex losses, most zero-gradient points are saddle points, and plateaus with tiny gradients are common. Check curvature, or rely on optimizers with momentum and noise that roll off saddles.
Interview angle Expect "derive the sigmoid derivative", "what is the gradient of softmax cross-entropy with respect to the logits?" (p − y), "what is the difference between the Jacobian and Hessian?", and "why do we move opposite to the gradient?". A bonus point is explaining the learning-rate bound η < 2/λmax via the Taylor expansion.

Backpropagation and vanishing/exploding gradients

Backpropagation is the algorithm that computes the gradient of the loss with respect to every weight in a network. It is nothing more than the chain rule applied systematically from the output layer backwards, caching intermediate values from the forward pass so that nothing is computed twice. It costs roughly the same as two or three forward passes, no matter how many weights there are, which is what makes training billion-parameter models feasible.

Analogy

A relay team finishes a race late. To fix it, the coach walks backwards from the finish line: the last runner lost 2 seconds, and some of that was because the handoff from runner three was slow, which in turn was partly runner two's fault. Each runner gets blame in proportion to how much their segment affected the final time. Backprop is that blame assignment: the loss is the late finish, each layer is a runner, and each weight receives a gradient proportional to its contribution to the error.

Worked example: a tiny two-layer network

One input x = 0.5, a hidden weight w1 = 0.8, an output weight w2 = 1.2, sigmoid activations, target y = 1 and loss L = ½(ŷ − y)2.

  1. Forward: hidden z1 = x · w1 = 0.4, h = σ(0.4) = 0.599.
  2. Forward: output z2 = h · w2 = 0.718, ŷ = σ(0.718) = 0.672.
  3. Loss L = ½(0.672 − 1)2 = 0.0537.
  4. Output error ∂L/∂ŷ = ŷ − y = −0.328; ∂ŷ/∂z2 = ŷ(1 − ŷ) = 0.220; so δ2 = ∂L/∂z2 = −0.0722.
  5. Gradient for w2 ∂L/∂w2 = δ2 · h = −0.0722 × 0.599 = −0.0432.
  6. Pass error backwards ∂L/∂h = δ2 · w2 = −0.0867; δ1 = ∂L/∂z1 = −0.0867 × h(1 − h) = −0.0867 × 0.240 = −0.0208.
  7. Gradient for w1 ∂L/∂w1 = δ1 · x = −0.0104.
  8. Update (learning rate 0.5) w1 = 0.8 + 0.0052 = 0.805; w2 = 1.2 + 0.0216 = 1.222. Both increase, pushing ŷ towards 1.

Notice that the early weight's gradient (−0.0104) is smaller than the later one's (−0.0432), because it was multiplied by an extra sigmoid derivative (at most 0.25) and weight. Repeat that over 30 layers and early layers receive almost no signal.

Backprop in matrix form

For a dense layer Z = XW + b with upstream gradient G = ∂L/∂Z (shape B×h):

∂L/∂W = XTG  (d×h)     ∂L/∂b = Σrows G  (h)     ∂L/∂X = G WT  (B×d) Shapes always tell you where the transposes go: the gradient of a parameter has the same shape as the parameter. Through an element-wise activation A = f(Z), multiply element-wise: ∂L/∂Z = ∂L/∂A ⊙ f'(Z).
# one training step of a 2-layer MLP with softmax cross-entropy, in NumPy
Z1 = X @ W1 + b1;  A1 = np.maximum(0, Z1)
Z2 = A1 @ W2 + b2
P = np.exp(Z2 - Z2.max(1, keepdims=True)); P /= P.sum(1, keepdims=True)
loss = -np.log(P[np.arange(B), y]).mean()

G2 = P.copy(); G2[np.arange(B), y] -= 1; G2 /= B      # dL/dZ2 = (p - onehot)/B
dW2 = A1.T @ G2;  db2 = G2.sum(0)
G1 = (G2 @ W2.T) * (Z1 > 0)                          # ReLU derivative
dW1 = X.T @ G1;   db1 = G1.sum(0)
for p, g in [(W1, dW1), (b1, db1), (W2, dW2), (b2, db2)]:
    p -= lr * g

Automatic differentiation (PyTorch autograd, JAX, TensorFlow) builds a computational graph during the forward pass and applies exactly these rules in reverse. Reverse mode is efficient when there are many inputs (weights) and one scalar output (the loss); forward mode is efficient in the opposite case. The trade-off is memory: activations from the forward pass must be stored for the backward pass, which is why activation checkpointing (recompute instead of store) exists for large models.

Vanishing and exploding gradients

Backprop multiplies one local factor per layer. If those factors are typically below 1 the product shrinks exponentially (vanishing); if above 1 it grows exponentially (exploding).

Layers N0.25N (sigmoid's best case)1.5N (poor init)
50.000987.6
109.5 × 10−757.7
209.1 × 10−133,325
507.9 × 10−316.4 × 108 (NaN soon)

Symptoms: vanishing shows as early layers' weights barely changing, a loss that plateaus early, and tiny gradient norms in lower layers. Exploding shows as loss spikes, NaN or inf values, and huge gradient norms.

ReLU-family activations

Derivative 1 for positive inputs, so active paths pass gradients unchanged. GELU and SiLU are smooth variants used in transformers.

Careful initialization

Xavier/Glorot (variance 2/(fan-in + fan-out)) for tanh; He/Kaiming (variance 2/fan-in) for ReLU. Keeps activation and gradient variance roughly constant across layers.

Residual connections

y = x + F(x) gives ∂y/∂x = I + ∂F/∂x, an identity "highway" for gradients. Enables 100+ layer ResNets and deep transformers.

Normalization layers

BatchNorm, LayerNorm and RMSNorm keep activations at a stable scale between layers, which smooths the loss landscape.

Gradient clipping

If ||g|| > c, rescale g to norm c. Standard for RNNs and LLM training (c = 1.0 is common).

Gating

LSTM and GRU gates create additive memory paths so gradients survive long sequences.

Common pitfall Initializing all weights to the same value (for example zero). Every neuron in a layer then computes the same output and receives the same gradient, so they stay identical forever: the symmetry is never broken. Biases can start at zero; weights must be random.
Interview angle Be ready to backprop through a two-layer network on a whiteboard, state why backprop costs O(number of weights) rather than O(weights squared), and list at least four fixes for vanishing gradients with the reason each works. For deeper coverage of architectures, see Deep learning.

Optimization: gradient descent, momentum, Adam and schedules

Optimization is the procedure that turns gradients into better weights. The basic recipe is always the same, take a step against the gradient, but the details (how much data per step, how to smooth noisy gradients, how to adapt step sizes per parameter, and how to change the learning rate over time) decide whether training is fast, stable and ends in a solution that generalizes.

Analogy

Plain gradient descent is a cautious hiker who looks at the slope under their feet and takes one step at a time. Momentum turns the hiker into a heavy ball rolling downhill: it builds speed in consistent directions and does not get stuck on small bumps. Adam is a smart ball that also adjusts its step size for each direction: short steps across steep, narrow ravines and long steps along gentle, flat valleys. A learning-rate schedule is the plan to walk briskly early on and take small careful steps as you near the camp site.

The update rule and the learning rate

wt+1 = wt − η ∇L(wt) η is the learning rate. Example: L = w2, gradient 2w, η = 0.1, start w = 5. Each step multiplies w by 0.8: 5 → 4 → 3.2 → ... after 10 steps w ≈ 0.54, after 20 steps w ≈ 0.058.
  • Too small (η = 0.0001): about 10,000 steps to make the same progress; may stall on plateaus.
  • Just right (η = 0.1): smooth convergence.
  • Too large (η = 1.5): each step multiplies w by 1 − 2(1.5) = −2, so 5 → −10 → 20 → −40: divergence. For this loss the stability limit is η < 1, which is 2/curvature.

Batch, stochastic and mini-batch gradient descent

VariantData per stepProsCons
Batch (full) GDAll n examplesExact gradient, smooth convergenceSlow per step; impossible for huge datasets
Stochastic GD1 exampleCheap steps; noise can escape shallow minimaVery noisy; poor hardware utilization
Mini-batch GDB examples (32 to thousands)Good GPU use; noise level controlled by BBatch size becomes a hyperparameter

In practice "SGD" almost always means mini-batch SGD. The mini-batch gradient is an unbiased estimate of the full gradient with variance proportional to 1/B. Some gradient noise is helpful: it tends to steer training towards flatter minima that generalize better. A common heuristic when increasing the batch size by k is to increase the learning rate by about k (linear scaling), with warmup.

Momentum and Nesterov

vt = β vt−1 + gt     wt+1 = wt − η vt     (β ≈ 0.9) v is an exponentially weighted running sum of past gradients (effective memory of about 1/(1 − β) = 10 steps). Oscillating components cancel out; consistent components accumulate, up to 10× the step size.

In a long narrow valley, plain GD bounces between the walls and creeps along the floor. Momentum damps the bouncing and accelerates along the floor. Nesterov momentum evaluates the gradient at the "look-ahead" point w − ηβv, which corrects overshooting a little earlier.

Adaptive methods: AdaGrad, RMSProp, Adam, AdamW

  • AdaGrad: divides the step by the square root of the sum of all past squared gradients. Great for sparse features (rare words get larger steps), but the denominator only grows, so learning eventually stalls.
  • RMSProp: uses an exponential moving average of squared gradients instead, s = 0.9s + 0.1g2, and steps by ηg/(√s + ε). Parameters with large, noisy gradients get smaller steps.
  • Adam combines momentum (first moment) and RMSProp (second moment) with bias correction:
mt = β1mt−1 + (1−β1)gt    vt = β2vt−1 + (1−β2)gt2    m̂t = mt/(1−β1t)    v̂t = vt/(1−β2t)    wt+1 = wt − η m̂t/(√v̂t + ε) Defaults: β1 = 0.9, β2 = 0.999, ε = 10−8, η = 10−3 (LLM pre-training often uses η around 10−4 to 6 × 10−4 with β2 = 0.95).

Why bias correction? m and v start at 0, so early averages are biased towards 0. At t = 1, m1 = 0.1g but m̂1 = g; v1 = 0.001g2 but v̂1 = g2. So the first update is about η · sign(g): every parameter moves by roughly η regardless of its gradient's scale, which shows Adam's scale invariance.

AdamW decouples weight decay from the adaptive update: w = w − η(m̂/(√v̂ + ε) + λw). With plain Adam, an L2 term added to the loss gets divided by √v̂, so heavily updated weights are barely regularized. AdamW is the default for transformers. Other optimizers you may hear about: Adafactor (memory-light second moments), LAMB/LARS (layer-wise scaling for huge batches), Lion (sign-based), and second-order-inspired methods such as Shampoo.

SGD + momentum

  • Fewer hyperparameters, less memory (one buffer)
  • Often generalizes slightly better on vision tasks
  • Needs careful learning-rate tuning and schedules

Adam / AdamW

  • Works well out of the box; robust to feature scale
  • Default for transformers, NLP, most new work
  • Two extra buffers per parameter (3× parameter memory for optimizer state in FP32)

Learning-rate schedules

ScheduleFormula / behaviorTypical use
Step decayMultiply by 0.1 every N epochsClassic CNN recipes
Exponential decayη0 γtSimple smooth decay
Linear warmupηpeak · min(t/Twarm, 1)First 1-5% of steps in almost all transformer training
Cosine annealingηmin + ½(ηmax − ηmin)(1 + cos(πt/T))Default for vision and LLMs (after warmup)
Warm restartsPeriodically reset to a high LREscaping sharp minima; snapshot ensembles
One-cycleRamp up to a high max LR, then anneal well below the startFast CNN training
Reduce on plateauCut LR when validation loss stops improvingSmall projects, fine-tuning
Inverse square root∝ 1/√t after warmupOriginal transformer paper

Why warmup? At the start, weights are random, Adam's second-moment estimates are unreliable, and gradients can be large. A full learning rate at step 0 often causes an early divergence. Ramping up over a few hundred or thousand steps lets statistics settle. Why decay? Late in training, a smaller step reduces the noise floor so the model can settle into a minimum instead of bouncing around it.

import torch
opt = torch.optim.AdamW(model.parameters(), lr=3e-4, betas=(0.9, 0.95), weight_decay=0.1)
sched = torch.optim.lr_scheduler.OneCycleLR(opt, max_lr=3e-4, total_steps=10_000, pct_start=0.03)
for x, y in loader:
    loss = loss_fn(model(x), y)
    opt.zero_grad(); loss.backward()
    torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
    opt.step(); sched.step()

Convexity and the loss landscape

A function is convex if the line segment between any two points on its graph lies above the graph: f(θx + (1−θ)y) ≤ θf(x) + (1−θ)f(y). Equivalently (for twice-differentiable functions) its Hessian is positive semi-definite everywhere. For convex functions every local minimum is a global minimum, and gradient descent with a suitable learning rate is guaranteed to find it. Linear regression with MSE, logistic regression with cross-entropy, ridge/lasso and SVMs are convex. Neural networks are not.

  • Local minima: in high dimensions, most local minima of large networks have loss values close to the global minimum; bad local minima are rarely the practical problem.
  • Saddle points and plateaus: far more common than local minima in high dimensions; momentum and gradient noise help escape them.
  • Sharp vs. flat minima: flat minima (low curvature) tend to generalize better; small batches, weight decay and techniques such as sharpness-aware minimization favor them.
  • Condition number: the ratio of largest to smallest curvature. High condition numbers produce zig-zagging; feature scaling, normalization layers and adaptive optimizers all effectively reduce it.

Regularization, seen as optimization

Regularization adds a complexity penalty to the loss: Ltotal = Ldata + λR(w). With L2 (ridge, weight decay), R = ||w||22, which shrinks all weights smoothly. With L1 (lasso), R = ||w||1, which pushes small weights exactly to zero, producing sparse models and built-in feature selection. Example with λ = 0.01 and weights [3.0, 0.1, 0.5, 2.0]: the L1 penalty is 0.01 × 5.6 = 0.056, the L2 penalty is 0.01 × 13.26 ≈ 0.133, and L2 punishes the large weight 3.0 disproportionately. Geometrically, the L1 constraint region is a diamond whose corners lie on the axes, so the loss contours usually touch it at a corner where some weights are zero; the L2 region is a circle with no corners. Other regularizers include dropout, early stopping, data augmentation and label smoothing. The MLE/MAP section below shows that L2 and L1 are Gaussian and Laplace priors in disguise.

Common pitfall Tuning the learning rate on a linear grid (0.001, 0.002, 0.003). Learning rates matter on a log scale; search 10−5 to 10−1 in multiplicative steps, or run a quick learning-rate range test.
Interview angle Common questions: "Compare SGD, momentum, RMSProp and Adam", "Why does Adam need bias correction?", "What is the difference between Adam with L2 and AdamW?", "Why warmup?", "Is the neural network loss convex? Why does training still work?". Tie each answer to a concrete behavior such as oscillation, plateaus or divergence. For how these fit into full training pipelines, see Machine learning.

Information theory: entropy, cross-entropy and KL divergence

Information theory measures surprise and uncertainty. It gives us the most widely used loss in deep learning (cross-entropy), the standard way to compare two distributions (KL divergence), the evaluation metric for language models (perplexity), and the split criterion in decision trees (information gain). The key idea is simple: rare events carry more information than common ones.

Analogy

Think of a weather app in a desert city that says "sunny" every day. The message carries almost no information because you already expected it; low surprise, low entropy. In a city where rain and sun are 50/50, each forecast tells you something; high entropy. Now suppose you pack for a trip using a guidebook that describes the wrong city. Cross-entropy is the average surprise you feel using the wrong guidebook, and KL divergence is the extra surprise compared with using the right one. In ML the right guidebook is the true label distribution and the wrong one is the model's predicted probabilities.

Information content and entropy

I(x) = −log p(x)     H(X) = −Σx p(x) log p(x) = E[−log p(X)] Base 2 gives bits, natural log gives nats (1 nat ≈ 1.44 bits). Deep learning libraries use natural logs.
  • Fair coin: H = −(0.5 log2 0.5 + 0.5 log2 0.5) = 1 bit, the maximum for two outcomes.
  • Biased coin (90% heads): H = −(0.9 log2 0.9 + 0.1 log2 0.1) ≈ 0.47 bits: more predictable.
  • Certain outcome: H = 0. Uniform over K outcomes: H = log2 K (a fair die: 2.58 bits). Entropy is maximized by the uniform distribution.
  • Entropy is the minimum average number of bits needed to encode samples from the distribution (Shannon's source coding theorem), which is why it connects to compression.
  • In ML: the entropy of a model's predicted distribution measures its uncertainty (useful for active learning and uncertainty-based routing); entropy regularization encourages exploration in RL; decision trees choose splits that reduce entropy.

Cross-entropy: the classification loss

H(P, Q) = −Σx p(x) log q(x)     one-hot label: L = −log q(correct class) P is the true distribution, Q the model's prediction. With a one-hot P only the true class term survives.

Worked example. The label is "cat". If the model predicts [cat 0.9, dog 0.1], the loss is −ln 0.9 = 0.105. If it predicts [cat 0.2, dog 0.8], the loss is −ln 0.2 = 1.609. If it predicts cat with 0.01, the loss is 4.6; as the probability goes to 0 the loss goes to infinity. Cross-entropy punishes confident mistakes very heavily, which pushes models towards calibrated probabilities.

Binary cross-entropy: L = −[y log p + (1 − y) log(1 − p)], used with a sigmoid output. Categorical cross-entropy: L = −Σ yk log pk, used with softmax. Class labels as strings are first converted to integer indices or one-hot vectors. The minus sign exists because log-probabilities are negative; negating turns "maximize the log-probability of the correct class" into "minimize a positive loss".

Why cross-entropy, not MSE, for classification?

  • It is the negative log-likelihood of a Bernoulli/categorical model (principled)
  • Gradient w.r.t. logits is p − y: strong signal when very wrong
  • Convex in the logits for logistic regression

What goes wrong with MSE + sigmoid

  • Gradient includes σ'(z), which is near 0 when the model is confidently wrong, so learning stalls
  • Non-convex for logistic regression
  • Bounded penalty for confident mistakes

KL divergence

DKL(P || Q) = Σx p(x) log(p(x)/q(x)) = H(P, Q) − H(P)  ≥ 0 Zero only when P = Q. Not symmetric, and it does not satisfy the triangle inequality, so it is a divergence rather than a distance.

Worked example (nats). P = [0.5, 0.5], Q = [0.9, 0.1]. DKL(P||Q) = 0.5 ln(0.5/0.9) + 0.5 ln(0.5/0.1) = −0.294 + 0.805 = 0.511. DKL(Q||P) = 0.9 ln 1.8 + 0.1 ln 0.2 = 0.529 − 0.161 = 0.368. Different values, so the order matters.

  • Cross-entropy = entropy + KL. Since H(P) of the labels is fixed, minimizing cross-entropy is exactly minimizing KL from the data distribution to the model.
  • Forward KL D(P||Q) (used by MLE) is "mean-seeking" or "mass-covering": Q is heavily penalized for assigning near-zero probability where P has mass, so it spreads out to cover all modes. Reverse KL D(Q||P) (used in variational inference) is "mode-seeking": Q prefers to fit one mode well and ignore others.
  • Where KL appears: VAE loss (KL between the encoder's Gaussian and a standard normal prior, closed form ½Σ(μ2 + σ2 − log σ2 − 1)); knowledge distillation (student matches the teacher's temperature-softened distribution); RLHF and DPO (a KL penalty keeps the tuned policy close to the reference model to prevent reward hacking); data-drift monitoring.
  • Jensen-Shannon divergence: JS(P, Q) = ½KL(P||M) + ½KL(Q||M) with M = (P + Q)/2. Symmetric and bounded by ln 2; the original GAN objective implicitly minimizes it.

Mutual information and information gain

I(X; Y) = Σx,y p(x, y) log [p(x, y)/(p(x)p(y))] = H(Y) − H(Y | X) = DKL(PXY || PXPY) How much knowing X reduces uncertainty about Y. Zero if and only if X and Y are independent; unlike correlation, it captures non-linear dependence.

Worked example. In the weather/traffic table (rain 0.4, heavy traffic 0.45, joint rainy-heavy 0.30), the mutual information is about 0.18 bits: knowing the weather removes about 0.18 of the 0.99 bits of uncertainty about traffic. Information gain in decision trees is exactly mutual information between a split and the label: Gain = H(parent) − Σ(ni/n)H(childi). The Gini impurity 1 − Σpk2 is a cheaper alternative with similar behavior. MI is also used for feature selection and in contrastive learning (the InfoNCE loss is a lower bound on mutual information).

Perplexity

PPL = exp( −(1/N) Σi ln p(tokeni | context) ) = ecross-entropy The effective number of equally likely choices the model is "confused between" at each step. Lower is better; a perfect model has PPL = 1.

Worked example. A language model assigns probabilities 0.5, 0.25 and 0.1 to three true next tokens. Mean negative log-likelihood = (0.693 + 1.386 + 2.303)/3 = 1.461 nats, so PPL = e1.461 ≈ 4.31: the model was as unsure as choosing uniformly among about 4.3 tokens. A model with a training loss of 2.0 nats per token has perplexity e2 ≈ 7.4. Perplexities are only comparable between models that use the same tokenizer and test set.

def entropy(p):  p = np.asarray(p); return -(p * np.log2(p)).sum()
entropy([0.5, 0.5]), entropy([0.9, 0.1])        # 1.0, 0.469 bits
P, Q = np.array([0.5, 0.5]), np.array([0.9, 0.1])
kl = (P * np.log(P / Q)).sum()                  # 0.511 nats
import torch.nn.functional as F
loss = F.cross_entropy(logits, targets)         # takes raw logits; applies log-softmax internally
kd = F.kl_div(F.log_softmax(s/T, -1), F.softmax(t/T, -1), reduction='batchmean') * T*T
Common pitfall Applying softmax and then passing probabilities to a loss that expects logits (torch.nn.CrossEntropyLoss, or Keras with from_logits=True). The model then effectively applies softmax twice, gradients shrink and training quietly underperforms. Also, F.kl_div expects log-probabilities as its first argument.
Interview angle Frequent questions: "What is cross-entropy and why use it?", "Relationship between cross-entropy, entropy and KL?", "Is KL symmetric?", "What is perplexity and how does it relate to the loss?", and "Why does minimizing cross-entropy equal maximum likelihood?". Show one numeric example (−ln 0.9 = 0.105 vs. −ln 0.1 = 2.30) to make it concrete.

Maximum likelihood (MLE) and maximum a posteriori (MAP)

MLE and MAP are the two philosophies behind almost every loss function. MLE picks the parameters that make the observed data most probable. MAP does the same but also multiplies in a prior belief about the parameters. Once you see this, many "recipes" stop being arbitrary: cross-entropy is MLE for a categorical model, MSE is MLE for Gaussian noise, and weight decay is a Gaussian prior.

Analogy

A detective (MLE) asks only: "Which suspect makes the evidence most likely?" A seasoned detective (MAP) also weighs background knowledge: "Suspect B fits the evidence slightly better, but B has an airtight alibi from past cases, so A is more plausible overall." With plenty of evidence both detectives agree; with little evidence, the background knowledge (the prior) stops the detective from jumping to extreme conclusions. In ML the prior is regularization, and it matters most when data is scarce.

MLE

θ̂MLE = argmaxθ P(D | θ) = argmaxθ Σi log p(xi | θ) = argminθ −Σi log p(xi | θ) For i.i.d. data the likelihood is a product; taking logs turns it into a sum (numerically stable and easy to differentiate) without moving the argmax, since log is monotonic.

Coin example. 70 heads in 100 flips. Log-likelihood = 70 log p + 30 log(1 − p). Setting the derivative 70/p − 30/(1 − p) to zero gives p̂ = 0.7, the observed fraction. Gaussian example. For data from N(μ, σ2), the MLE of μ is the sample mean and the MLE of σ2 is the 1/n (biased) variance. MLE estimators are consistent and asymptotically efficient, but they can overfit with small data: a coin that landed heads 3 times out of 3 gets p̂ = 1.

Losses are negative log-likelihoods

Assumed noise / output modelNegative log-likelihood becomesImplication
y ~ N(f(x), σ2)(1/2σ2)Σ(y − f(x))2 + const = MSEMSE assumes Gaussian, constant-variance noise; predicts the conditional mean
y ~ Laplace(f(x), b)(1/b)Σ|y − f(x)| + const = MAERobust to outliers; predicts the conditional median
y ~ Bernoulli(σ(f(x)))Binary cross-entropyLogistic regression is MLE
y ~ Categorical(softmax(f(x)))Categorical cross-entropyEvery classifier and every LLM's pre-training loss
y ~ Poisson(exp(f(x)))Σ(ef − y f) + constCount regression

The choice of loss is therefore an implicit assumption about how the targets are generated. If your regression residuals are heavy-tailed, MSE's Gaussian assumption is wrong and a Laplace (MAE) or Huber loss is more appropriate.

MAP

θ̂MAP = argmaxθ P(D | θ) P(θ) = argminθ [ −log P(D | θ) − log P(θ) ] From Bayes: the posterior is proportional to likelihood times prior; the evidence P(D) does not depend on θ and drops out of the argmax.
  • Gaussian prior P(w) ∝ exp(−||w||2/(2τ2)) gives −log P(w) = ||w||2/(2τ2) + const: this is L2 regularization, with λ = 1/(2τ2) (up to the noise-variance scaling). A tight prior (small τ) means strong regularization.
  • Laplace prior P(w) ∝ exp(−|w|/b) gives L1 regularization; the Laplace density's sharp peak at zero is why L1 produces exact zeros.
  • Beta prior on a coin: with prior Beta(2, 2) (a gentle belief that the coin is roughly fair) and 7 heads in 10 flips, the posterior is Beta(9, 5). MAP = (7 + 1)/(10 + 2) = 0.667 versus MLE = 0.7; the posterior mean is 9/14 ≈ 0.643. With 3 heads out of 3, MAP gives 4/5 = 0.8 instead of MLE's overconfident 1.0.
  • As data grows, the likelihood dominates the prior, and MAP converges to MLE.

MLE / MAP (point estimates)

  • One best parameter value
  • Cheap: just optimization
  • No uncertainty estimate for the parameters

Full Bayesian inference

  • Keeps the whole posterior P(θ | D)
  • Predictions average over parameters: calibrated uncertainty
  • The integral is usually intractable: MCMC, variational inference, ensembles, MC dropout as approximations
Common pitfall Calling the likelihood a probability distribution over θ. P(D | θ) as a function of θ does not integrate to 1; it only becomes a distribution over θ after multiplying by a prior and normalizing (the posterior).
Interview angle "Show that minimizing MSE is MLE under Gaussian noise" and "Show that L2 regularization is MAP with a Gaussian prior" are classic whiteboard questions. Write the Gaussian log-density, drop constants, and the squared error appears. Then add the log of a Gaussian prior and the ||w||2 term appears.

Numerical stability: log-sum-exp, stable softmax and precision

Math on paper uses real numbers with infinite precision; computers use floating-point numbers with a limited range and precision. Naive implementations of softmax, log-likelihoods and variance can overflow to infinity, underflow to zero or produce NaN. A few standard tricks prevent this, and knowing them is a strong signal in interviews.

Analogy

Imagine measuring mountain heights with a ruler that only reads up to 10 metres. Instead of measuring each mountain from sea level, you measure how far each peak is below the tallest one, and remember the tallest one's height separately. Every reading now fits on the ruler, and you can reconstruct the true heights. The log-sum-exp trick does exactly this: subtract the largest value before exponentiating so nothing overflows, then add it back.

Floating-point limits

FormatBits (exponent / mantissa)Approx. maxDecimal precisionTypical use
FP328 / 233.4 × 1038~7 digitsDefault training, optimizer states, master weights
FP165 / 1065,504~3 digitsMixed precision; needs loss scaling to avoid gradient underflow
BF168 / 73.4 × 1038~2-3 digitsLLM training: FP32's range, less precision, usually no loss scaling
INT8 / INT4integer127 / 7–Quantized inference (4-8× smaller)

In FP32, e89 already overflows to infinity, and e−104 underflows to 0. In FP16, e12 ≈ 162,755 already overflows. Logits of 100 or more are common, so naive exponentiation is dangerous.

The log-sum-exp trick

log Σi exi = m + log Σi exi − m,    m = maxi xi Algebraically identical (factor em out of the sum). After shifting, the largest exponent is e0 = 1 and all others are ≤ 1, so no overflow, and the sum is at least 1, so the log never sees 0.

Example. x = [1000, 999]. Naively, e1000 overflows and the answer is inf. With the trick: 1000 + log(e0 + e−1) = 1000 + log(1.368) = 1000.313.

Stable softmax and log-softmax

softmax(x)i = exi − m / Σj exj − m     log_softmax(x)i = xi − logsumexp(x) Softmax is invariant to adding a constant to every logit, so subtracting the max changes nothing mathematically.
def softmax(x, axis=-1):
    z = x - x.max(axis=axis, keepdims=True)       # shift for stability
    e = np.exp(z)
    return e / e.sum(axis=axis, keepdims=True)

def log_softmax(x, axis=-1):
    m = x.max(axis=axis, keepdims=True)
    return x - m - np.log(np.exp(x - m).sum(axis=axis, keepdims=True))

softmax(np.array([1000., 999.]))     # [0.731, 0.269]   naive version returns [nan, nan]
from scipy.special import logsumexp, expit   # expit = numerically safe sigmoid

This is why frameworks fuse softmax and cross-entropy into one operation that takes raw logits: computing log(softmax(x)) in two steps can produce log(0) = −inf when a probability underflows, while xy − logsumexp(x) never does. The same applies to sigmoid + BCE (BCEWithLogitsLoss), which uses the identity log(1 + ez) = max(z, 0) + log(1 + e−|z|).

Work in log space

The probability of a 1,000-token sentence is a product of 1,000 probabilities around 0.1, i.e. about 10−1000, far below FP32's smallest positive number. Sums of logs (−2,303 nats here) are perfectly representable. Every language model, HMM, Naive Bayes implementation and beam search works with log-probabilities for this reason.

Other stability tricks

  • Epsilon in denominators and logs: normalization layers use √(σ2 + ε) with ε ≈ 10−5; Adam uses √v̂ + ε; clip probabilities to [ε, 1 − ε] before taking logs.
  • Loss scaling in FP16 mixed precision: multiply the loss by a large factor (for example 1,024) so small gradients do not underflow, then unscale before the optimizer step; dynamic scalers back off when inf/NaN appears.
  • Stable variance: Welford's online algorithm instead of E[X2] − E[X]2, which suffers catastrophic cancellation when the mean is large.
  • log1p and expm1: log(1 + x) and ex − 1 for tiny x lose all precision if computed directly.
  • Attention scaling and masking: dividing by √dk keeps logits moderate; masks use a large negative number (or −inf with care) so masked positions get zero weight; fused attention kernels (FlashAttention-style) use an online softmax with running max for stability and memory efficiency.
  • Condition numbers: prefer solvers (QR, Cholesky, SVD) to explicit inverses; add a small ridge λI to near-singular matrices.
Common pitfall Writing np.log(sigmoid(z)) or np.log(softmax(x)) yourself. For large-magnitude logits this produces −inf and then NaN gradients. Use the fused, log-space functions that libraries provide.
Interview angle "Implement softmax" is a common coding question, and the interviewer is waiting to see whether you subtract the max. Follow-ups: "Why doesn't subtracting the max change the result?", "Why does PyTorch's cross-entropy take logits?", "Why do LLMs train in BF16 instead of FP16?" (same exponent range as FP32, so no overflow and usually no loss scaling).

The activation function and loss function zoos

Activation functions add the non-linearity that lets neural networks represent curved decision boundaries; loss functions define what "good" means. Each comes with a mathematical shape, a derivative that determines how gradients flow, and a set of typical failure modes. Picking them correctly is a mix of math and convention, and interviewers love to probe the reasoning.

Analogy

Activation functions are like the valves in a plumbing network. A plain pipe (linear) just passes water through, and any number of pipes joined together is still just a pipe. Valves that open only above some pressure (ReLU), open smoothly (sigmoid, GELU) or let a trickle through when closed (Leaky ReLU) let the network route water in complex patterns. The loss function is the inspector's scorecard at the outlet, and different inspectors punish different mistakes: one squares every error (MSE), one counts them linearly (MAE), one cares mostly about confident wrong answers (cross-entropy).

Why non-linearity is essential

Without activations, a stack of layers collapses: W3(W2(W1x)) = (W3W2W1)x, a single linear map that cannot even solve XOR. With a non-linear function between layers, a network with enough hidden units can approximate any continuous function on a bounded domain (the universal approximation theorem); depth makes such approximations far more parameter-efficient.

Activation functions

ActivationFormulaRangeDerivativeNotes and use
Sigmoid1/(1 + e−x)(0, 1)σ(1 − σ), max 0.25Binary output, gates (LSTM). Saturates and is not zero-centered, so it is poor in hidden layers.
Tanh(ex − e−x)/(ex + e−x) = 2σ(2x) − 1(−1, 1)1 − tanh2, max 1Zero-centered; RNN hidden states. Still saturates.
ReLUmax(0, x)[0, ∞)0 or 1Cheap; no saturation for x > 0; sparse activations. "Dying ReLU": neurons stuck with negative input get zero gradient forever.
Leaky ReLU / PReLUx if x > 0 else αx (α ≈ 0.01, learned in PReLU)(−∞, ∞)1 or αKeeps a small gradient for negatives; GANs.
ELUx if x > 0 else α(ex − 1)(−α, ∞)smoothSmooth negative side, mean closer to 0.
GELUx · Φ(x) (Φ = standard normal CDF)≈ (−0.17, ∞)smoothBERT, GPT family, ViT. GELU(−1) ≈ −0.159, GELU(2) ≈ 1.954.
SiLU / Swishx · σ(x)≈ (−0.28, ∞)smooth, non-monotonicEfficientNet; with gating (SwiGLU) in Llama-style FFNs.
Softplusln(1 + ex)(0, ∞)σ(x)Smooth ReLU; produces positive outputs such as variances.
Softmaxezi/Σezjprobability vectordiag(p) − ppTMulti-class output, attention weights. Not a hidden-layer activation.

Choosing: hidden layers of CNNs and MLPs: ReLU (or variants). Transformers: GELU or SwiGLU. RNN/LSTM: tanh for states, sigmoid for gates. Output layer: sigmoid for binary or multi-label, softmax for multi-class, identity for regression, softplus or exp for positive targets, tanh for bounded targets in [−1, 1].

Gated linear units. SwiGLU computes (xW1 ⊙ SiLU(xW2))W3: one branch decides how much of the other to let through. It uses three weight matrices instead of two, so the hidden size is usually reduced to about 8d/3 to keep parameters constant.

Regression losses

LossFormulaBehavior
MSE (L2)(1/n)Σ(ŷ − y)2Smooth, strongly penalizes big errors, outlier-sensitive; optimal prediction is the mean
RMSE√MSESame minimizer, reported in the target's units
MAE (L1)(1/n)Σ|ŷ − y|Robust; gradient has constant magnitude (non-smooth at 0); optimal prediction is the median
Huber½e2 if |e| ≤ δ, else δ(|e| − ½δ)Quadratic near zero, linear in the tails; best of both
Log-coshΣ log(cosh(ŷ − y))Smooth approximation of Huber; twice differentiable
Quantile (pinball)max(τe, (τ − 1)e), e = y − ŷPredicts the τ-th quantile; prediction intervals, p90 latency forecasts

Example. Predictions [$320K, $190K] vs. actual [$300K, $200K]: errors +20K and −10K. MSE = (400M + 100M)/2 = 250M (RMSE ≈ 15.8K); MAE = (20K + 10K)/2 = 15K. Add one wild error of 200K and the MSE explodes while the MAE grows modestly.

Classification and ranking losses

LossFormulaUse
Binary cross-entropy−[y log p + (1−y) log(1−p)]Binary and multi-label classification (one sigmoid per label)
Categorical cross-entropy−Σ yk log pk = −log ptrueMulti-class with softmax; LLM next-token loss
Label smoothingTrue class (1 − ε) + ε/K; others ε/KReduces overconfidence, improves calibration
Focal loss−α(1 − pt)γ log ptClass imbalance; down-weights easy examples (object detection)
Hingemax(0, 1 − y·f(x)), y ∈ {−1, +1}SVMs; zero loss once the margin exceeds 1
Contrastive / InfoNCE−log [esim(q,k+)/τ / Σk esim(q,k)/τ]Embedding models, CLIP, SimCLR, retrieval
Tripletmax(0, d(a, p) − d(a, n) + margin)Face recognition, metric learning
KL divergenceΣ p log(p/q)Distillation, VAEs, RLHF penalty
CTCSum over all valid alignmentsSpeech recognition with unaligned sequences
import torch.nn as nn
nn.MSELoss(); nn.L1Loss(); nn.HuberLoss(delta=1.0)
nn.BCEWithLogitsLoss(pos_weight=torch.tensor([9.0]))   # logits in; weight positives for imbalance
nn.CrossEntropyLoss(label_smoothing=0.1)                # logits in; integer class targets
Common pitfall Using softmax + categorical cross-entropy for a multi-label problem (an image can contain both a cat and a dog). Softmax forces the classes to compete and sum to 1; multi-label needs an independent sigmoid per class with binary cross-entropy.
Interview angle Expect "Why ReLU over sigmoid in hidden layers?", "What is the dying ReLU problem and how do you fix it?", "Why GELU in transformers?", "MSE vs. MAE vs. Huber?", "Which loss for imbalanced classification?", and "Softmax vs. sigmoid outputs?". Each answer should mention the derivative, because the derivative is what determines training behavior.

The math of generative AI: softmax temperature, attention and positional encoding

Large language models are built from the pieces above: embeddings (vectors), matrix multiplications, softmax, dot-product similarity, normalization, residual connections and cross-entropy training. This section walks through the specific formulas that make a transformer work, at the level needed to explain them in an interview. The architecture itself is covered in depth on the Transformers & LLMs page.

Analogy

Attention works like a library visit. You arrive with a question (the query). Every shelf has a label (the key). You compare your question to every label and give each shelf a relevance score (dot product), turn the scores into a budget of attention that adds up to 100% (softmax), and then take home a mix of the books (values) weighted by that budget. Multi-head attention is sending several researchers at once, each with a different kind of question (grammar, meaning, who-refers-to-whom). Positional encoding is writing the page number on every word so the librarians know the order. Temperature is how adventurous you are when picking the next book to read.

Tokens, embeddings and logits

Text is split into tokens, each mapped to an integer ID, and each ID selects a row of an embedding matrix E of shape V × d (vocabulary size by model dimension). A 100,000-token vocabulary with d = 4,096 is already 410 million parameters. After the transformer layers, the final hidden vector h is multiplied by an output matrix (often tied to E) to produce one logit per vocabulary entry: a raw, unnormalized score. Softmax turns the logits into a probability distribution over the next token, and training minimizes cross-entropy against the actual next token.

Softmax with temperature

pi = ezi/T / Σj ezj/T T < 1 sharpens the distribution (differences between logits are amplified); T > 1 flattens it; T → 0 approaches greedy argmax; T → ∞ approaches uniform.
Logits [2, 1, 0]Token AToken BToken C
T = 0.5 (logits become [4, 2, 0])0.8670.1170.016
T = 1.00.6650.2450.090
T = 2.0 (logits become [1, 0.5, 0])0.5060.3070.186
T = 100.3670.3320.301

Temperature changes the probabilities, but not their ranking, so greedy decoding gives the same token at any positive temperature. T = 0 is implemented as argmax (dividing by zero is avoided). Negative temperatures would invert the ranking and are not used. Typical settings: 0 to 0.3 for code, extraction and factual answers; about 0.7 for general chat; 0.9 to 1.2 for creative writing. Temperature is also used in knowledge distillation (a teacher's softmax at T = 2 to 5 reveals "dark knowledge" about which wrong classes are similar) and in contrastive losses (a small τ such as 0.07 sharpens similarity distributions).

Sampling strategies as probability operations

  • Greedy: pick argmax p. Deterministic; can loop or be bland.
  • Top-k: keep the k highest-probability tokens, renormalize them to sum to 1, sample. A fixed k is too many when the model is confident and too few when it is uncertain.
  • Top-p (nucleus): keep the smallest set of tokens whose cumulative probability reaches p (for example 0.9), renormalize, sample. The set size adapts to the model's confidence, so top-p behaves like a "dynamic k".
  • Combined: filters are applied in sequence, so the surviving set is the intersection. With probabilities C = 0.22, F = 0.18, D = 0.16, A = 0.13, ... top-k = 2 keeps {C, F}; top-p = 0.95 would keep eight tokens; the intersection is {C, F}, so top-k is the binding constraint.
  • Beam search: keep the b best partial sequences by total log-probability. Good for translation; tends to be bland for open-ended text. Length normalization divides the log-probability by length to avoid favoring short outputs.
  • Repetition penalties: reduce the logits of tokens already generated. Min-p sampling keeps tokens whose probability is at least a fraction of the top token's probability.

Scaled dot-product attention

Attention(Q, K, V) = softmax( Q KT / √dk ) V     Q = XWQ, K = XWK, V = XWV X: (T × d) token representations. WQ, WK: (d × dk); WV: (d × dv), all learned by backpropagation. QKT is a T × T matrix of scores; softmax is applied to each row; the output is T × dv.
  1. Project Each token produces a query ("what am I looking for?"), a key ("what do I contain?") and a value ("what information do I pass on?").
  2. Score Dot product of every query with every key: high when they point in similar directions.
  3. Scale Divide by √dk to keep scores in a range where softmax still has useful gradients.
  4. Mask (optional) Add −∞ (in practice a large negative number) to disallowed positions, e.g. future tokens in a decoder, so their weights become exactly 0 after softmax.
  5. Normalize Row-wise softmax: each token's weights over all tokens are positive and sum to 1.
  6. Mix Multiply by V: each output is a weighted average of value vectors.

Worked example (3 tokens, dk = 2). Q = K = [[1, 0], [0, 1], [1, 1]], V = [[2, 0], [0, 3], [1, 1]]. For the third token, the raw scores against the three keys are [1, 1, 2]. Divided by √2 they become [0.707, 0.707, 1.414]. Softmax gives [0.248, 0.248, 0.503]. The output is 0.248[2, 0] + 0.248[0, 3] + 0.503[1, 1] = [1.00, 1.25]: mostly its own value, blended with the others.

Why √dk? If the components of q and k are independent with mean 0 and variance 1, then q·k = Σ qiki is a sum of dk terms each with variance 1, so its variance is dk and its standard deviation √dk. With dk = 64, raw scores have a typical magnitude around 8; softmax of such values is nearly one-hot, its Jacobian diag(p) − ppT is nearly zero, and gradients vanish. Dividing by √dk = 8 restores unit variance. The factor is not a guess; it is exactly the standard deviation of the dot product.

Why softmax before multiplying by V? The scores decide where to look; V decides what to retrieve. Normalizing the weights first makes the output a convex combination of value vectors, keeping its scale stable regardless of sequence length. Cost: computing QKT takes O(T2d) time and O(T2) memory per head, the reason long contexts are expensive and why efficient kernels and approximations exist.

def attention(Q, K, V, mask=None):
    d_k = Q.shape[-1]
    scores = Q @ K.swapaxes(-1, -2) / np.sqrt(d_k)         # (..., T, T)
    if mask is not None:
        scores = np.where(mask, scores, -1e9)             # causal / padding mask
    w = softmax(scores, axis=-1)                          # rows sum to 1
    return w @ V, w

T = 4
causal = np.tril(np.ones((T, T), dtype=bool))             # token i sees tokens 0..i

Multi-head attention

MultiHead(X) = Concat(head1, ..., headh) WO     headi = Attention(XWQ(i), XWK(i), XWV(i)) Each head uses dk = d/h, so total compute is similar to one full-width head. With d = 512 and h = 8, each head has dk = 64. WO (d × d) mixes the heads' outputs back together.

A single softmax can only produce one weighting pattern per token; multiple heads let the model attend to different relationships at once (neighboring tokens, subject-verb links, coreference, copying earlier tokens). The four projection matrices WQ, WK, WV, WO contribute 4d2 parameters per layer; the feed-forward block (d → 4d → d) contributes about 8d2, which is why FFNs hold roughly two-thirds of a transformer's parameters. Heads must be initialized randomly and independently, otherwise they would receive identical gradients and remain copies. Grouped-query attention (GQA) and multi-query attention (MQA) share key/value projections across groups of heads, shrinking the KV cache used during generation, whose size is 2 × layers × KV heads × dk × sequence length × bytes per value (about 0.5 MB per token for a 7B model with 32 layers, 32 heads of 128 dimensions, in FP16).

Positional encoding

Self-attention is permutation-equivariant: shuffle the input tokens and the outputs shuffle the same way. It has no built-in notion of order, yet "dog bites man" and "man bites dog" mean different things. Positional information must be injected.

PE(pos, 2i) = sin(pos / 100002i/d)     PE(pos, 2i+1) = cos(pos / 100002i/d) Sinusoidal encoding, added to the token embeddings. Each pair of dimensions is a sine/cosine wave with its own frequency, from fast (one cycle every ~6 positions) to extremely slow (wavelength ~62,832 positions).

Example: for the first pair of dimensions (i = 0), position 1 gets [sin 1, cos 1] = [0.841, 0.540] and position 2 gets [sin 2, cos 2] = [0.909, −0.416]. Using sine and cosine together means each pair is a point on a circle; moving k positions forward is a fixed rotation of that point, so PE(pos + k) is a linear function of PE(pos). That lets attention learn relative offsets. The multiple frequencies act like the hands of a clock (seconds, minutes, hours) so every position gets a unique combination.

SchemeHow it worksUsed in
Sinusoidal (absolute)Fixed sin/cos vectors added to embeddingsOriginal transformer
Learned absoluteA trainable vector per positionBERT, GPT-2; cannot go beyond the trained maximum length
Relative bias / ALiBiAdd a penalty to attention scores proportional to distanceT5 (learned buckets), ALiBi models; extrapolates to longer sequences
RoPE (rotary)Rotate query and key vectors by position-dependent anglesLlama, Mistral, Qwen, Gemma and most modern LLMs

Rotary position embedding (RoPE)

RoPE splits each query and key vector into pairs of dimensions and rotates pair i by the angle mθi, where m is the token's position and θi = 10000−2i/d.

[x'2i, x'2i+1] = [x2i cos mθi − x2i+1 sin mθi,   x2i sin mθi + x2i+1 cos mθi] A 2D rotation matrix R(mθ) applied to each pair. Key property: (Rmq)·(Rnk) = q·(Rn−mk), so the attention score depends only on the relative distance n − m.

Because rotations preserve length, RoPE does not change vector norms; it only changes angles. It is applied to Q and K (not V) inside every attention layer rather than added once at the input. Low-frequency pairs encode long-range position, high-frequency pairs encode local order. Context-extension methods (position interpolation, NTK-aware scaling, YaRN) rescale the angles so a model trained on, say, 4K tokens can handle much longer inputs with a little fine-tuning.

def rope(x, pos, base=10000.0):
    # x: (T, d) with d even; pos: (T,)
    d = x.shape[-1]
    theta = base ** (-np.arange(0, d, 2) / d)            # (d/2,)
    ang = pos[:, None] * theta[None, :]                  # (T, d/2)
    cos, sin = np.cos(ang), np.sin(ang)
    x1, x2 = x[:, 0::2], x[:, 1::2]
    out = np.empty_like(x)
    out[:, 0::2] = x1 * cos - x2 * sin
    out[:, 1::2] = x1 * sin + x2 * cos
    return out

Normalization and the rest of the block

LayerNorm(x) = γ ⊙ (x − μ)/√(σ2 + ε) + β     RMSNorm(x) = γ ⊙ x / √(mean(x2) + ε) Statistics are computed over the features of each token, so they work at any batch size. BatchNorm computes them over the batch and is standard in CNNs but awkward for variable-length sequences. RMSNorm drops the mean subtraction and is cheaper; most modern LLMs use it.

A transformer block is: x = x + Attention(Norm(x)); x = x + FFN(Norm(x)) (the pre-norm arrangement). The residual additions keep a direct gradient path through dozens of layers, and the normalizations keep activations at a stable scale. For generation, the model runs this stack for each new token, reusing cached keys and values from earlier tokens.

Common pitfall Thinking temperature changes what the model "knows" or that low temperature prevents hallucinations. Temperature only reshapes the output distribution. If the most likely token is wrong, greedy decoding will confidently output it. Grounding (retrieval) and better models address hallucinations; temperature addresses randomness.
Interview angle Top questions: "Write the attention formula and explain each term", "Why divide by √dk?" (variance of a dot product grows with dk; keeps softmax out of saturation), "Why multi-head?", "Why do we need positional encoding and how does RoPE work?", "What does temperature do mathematically?", and "Top-k vs. top-p?". Being able to compute a 3-token attention example or a temperature-scaled softmax by hand is a strong differentiator.

Quick revision

  • Mean uses every value and is pulled by outliers; the median is robust and preferred for skewed data such as income or latency.
  • Quartiles split sorted data into four parts; IQR = Q3 − Q1; the box-plot outlier rule flags points beyond Q1 − 1.5·IQR or Q3 + 1.5·IQR.
  • Variance is the mean squared deviation; standard deviation is its square root, in the data's units.
  • Sample variance divides by n − 1 (Bessel's correction) because deviations from the sample mean are systematically too small.
  • Right skew: long right tail, mean > median. Excess kurtosis > 0: heavier tails than a normal distribution.
  • z = (x − μ)/σ; fit scalers on training data only to avoid leakage.
  • P(A ∪ B) = P(A) + P(B) − P(A ∩ B); P(A ∩ B) = P(A)P(B | A); independence means P(A ∩ B) = P(A)P(B).
  • P(A | B) ≠ P(B | A); Bayes: posterior = likelihood × prior / evidence.
  • 1% prevalence, 95% sensitivity, 5% false-positive rate: a positive test means only about 16% chance of disease (base-rate fallacy).
  • Linearity of expectation holds even for dependent variables; Var(aX + b) = a2Var(X).
  • Var(X + Y) = Var X + Var Y + 2Cov(X, Y); the variance of a mean of n i.i.d. values is σ2/n.
  • Correlation is covariance scaled to [−1, 1]; zero correlation does not imply independence (X and X2).
  • Bernoulli (p, p(1−p)), binomial (np, np(1−p)), Poisson (λ, λ), exponential (1/λ, 1/λ2), uniform ((a+b)/2, (b−a)2/12).
  • Normal: 68-95-99.7 within 1, 2, 3 standard deviations; 1.96 for a two-sided 95% interval.
  • Beta is the conjugate prior for a Bernoulli/binomial rate; Dirichlet for categorical; posterior = prior pseudo-counts + observed counts.
  • LLN: sample means converge to the true mean. CLT: sample means are approximately normal with standard error σ/√n, whatever the data's shape.
  • A 95% CI means 95% of intervals built this way contain the true value, not a 95% probability for this interval.
  • A p-value is P(data at least this extreme | H0), not P(H0 | data).
  • Type I = false positive (α); Type II = false negative (β); power = 1 − β, increased by larger n, larger effects, lower variance.
  • Use Welch's t-test for two means, paired tests for the same units, chi-square for categorical association, z-test for proportions.
  • A/B pitfalls: peeking, multiple comparisons, underpowered tests, sample-ratio mismatch, novelty effects.
  • Bootstrap puts error bars on a statistic (resample with replacement); CV estimates how well a training procedure generalises (retrain on folds). They are not interchangeable.
  • Student-t variance is ν/(ν−2) only for ν > 2; the mean exists only for ν > 1.
  • Label smoothing: true class gets (1 − ε) + ε/K, every other class gets ε/K.
  • Matrix product (m×n)(n×p) = (m×p); not commutative but associative; (AB)T = BTAT.
  • Only square, full-rank matrices (det ≠ 0) are invertible; rank = number of independent rows or columns.
  • Normal equation w = (XTX)−1XTy; in practice use lstsq/QR/SVD, never an explicit inverse.
  • Av = λv; trace = sum of eigenvalues, determinant = product; symmetric matrices have real eigenvalues and orthogonal eigenvectors.
  • SVD A = UΣVT works for any matrix; truncated SVD is the best low-rank approximation.
  • PCA: center/standardize, covariance, eigenvectors = directions of max variance, keep top k by explained variance.
  • Broadcasting compares shapes right to left; dimensions must match or be 1; (N,) minus (N, 1) silently becomes (N, N).
  • Cosine similarity ignores magnitude; for unit vectors, squared Euclidean distance = 2 − 2cos θ.
  • The gradient points in the direction of steepest ascent; gradient descent steps along −∇L.
  • Chain rule: multiply local derivatives along a path, sum over paths; backprop applies it from the loss backwards.
  • σ'(x) = σ(1 − σ) ≤ 0.25; the softmax + cross-entropy gradient with respect to logits is p − y.
  • Hessian eigenvalues all positive = local minimum; mixed signs = saddle point; learning rate must satisfy η < 2/λmax.
  • Vanishing gradients: fix with ReLU-family activations, He/Xavier init, residuals, normalization; exploding: gradient clipping.
  • Momentum averages gradients; RMSProp scales by recent gradient magnitude; Adam combines both with bias correction; AdamW decouples weight decay.
  • Warmup avoids early divergence; cosine decay lets the model settle; tune learning rates on a log scale.
  • Convex losses have one global minimum; neural network losses are non-convex but mostly have good minima and many saddles.
  • Entropy H = −Σp log p; cross-entropy = entropy + KL; KL ≥ 0 and is not symmetric.
  • Perplexity = ecross-entropy per token; a loss of 2.0 nats means perplexity about 7.4.
  • MSE = Gaussian MLE, MAE = Laplace MLE, cross-entropy = categorical MLE; L2 = Gaussian prior, L1 = Laplace prior (MAP).
  • Stable softmax subtracts the max; log-sum-exp = m + log Σex − m; work with log-probabilities; pass logits to fused losses.
  • BF16 has FP32's range with less precision, so LLMs train in BF16 without loss scaling; FP16 needs loss scaling.
  • Temperature divides logits before softmax: T < 1 sharpens, T > 1 flattens; it never changes the argmax.
  • Attention = softmax(QKT/√dk)V; dividing by √dk keeps score variance at 1 so softmax does not saturate.
  • Attention is order-blind; sinusoidal, learned, ALiBi or RoPE encodings add position; RoPE rotates Q and K so scores depend on relative distance.

Glossary

A/B test
A randomized experiment comparing a control and a treatment on a pre-chosen metric using a hypothesis test.
Adam
An optimizer that combines momentum (a running mean of gradients) with per-parameter step sizes from a running mean of squared gradients, plus bias correction.
AdamW
Adam with weight decay applied directly to the weights rather than through the loss; the default for transformers.
Backpropagation
Computing gradients of the loss for all parameters by applying the chain rule backwards through the computation graph.
Bayes' theorem
P(A | B) = P(B | A)P(A)/P(B): how to update a prior belief into a posterior after seeing evidence.
Bessel's correction
Dividing by n − 1 instead of n to get an unbiased sample variance.
Bias (of an estimator)
The difference between an estimator's expected value and the true parameter.
Bootstrap
Estimating the variability of a statistic by recomputing it on many resamples drawn with replacement.
Broadcasting
Rules that let array operations combine different shapes by virtually stretching size-1 dimensions.
Central limit theorem
The distribution of a sample mean approaches a normal distribution with standard deviation σ/√n as n grows.
Chain rule
The derivative of a composition is the product of the derivatives of its parts.
Condition number
Ratio of the largest to smallest singular value (or curvature); high values mean numerical instability and slow gradient descent.
Conditional probability
P(A | B) = P(A ∩ B)/P(B): the probability of A within the world where B happened.
Confidence interval
A range built by a procedure that captures the true parameter in a stated fraction (e.g. 95%) of repeated samples.
Conjugate prior
A prior that yields a posterior in the same family, e.g. Beta for a binomial rate.
Convex function
A function whose chords lie above its graph; every local minimum is global.
Correlation
Covariance divided by the product of standard deviations; measures linear association on a [−1, 1] scale.
Cosine similarity
The dot product of two vectors divided by the product of their lengths; the cosine of the angle between them.
Covariance
E[(X − μX)(Y − μY)]: whether two variables move together, in their product units.
Covariance matrix
A symmetric positive semi-definite matrix of pairwise feature covariances with variances on the diagonal.
Cross-entropy
−Σp log q: the average surprise of true outcomes under predicted distribution q; the standard classification loss.
Determinant
A scalar giving the volume scaling of a linear map; zero means the matrix is singular.
Dot product
The sum of element-wise products of two vectors; measures alignment and underlies neurons and attention.
Eigenvector / eigenvalue
A direction v that a matrix only scales, Av = λv; λ is the scale factor.
Entropy
−Σp log p: the average uncertainty or information content of a distribution.
Expectation
The probability-weighted average of a random variable.
Gradient
The vector of partial derivatives; points in the direction of steepest increase.
Gradient clipping
Rescaling the gradient when its norm exceeds a threshold, to prevent exploding updates.
Hessian
The matrix of second partial derivatives, describing the curvature of a function.
Hypothesis test
A procedure that decides whether data provide enough evidence to reject a null hypothesis at level α.
i.i.d.
Independent and identically distributed: samples drawn independently from the same distribution.
Independence
Two events or variables where knowing one gives no information about the other: P(A ∩ B) = P(A)P(B).
Interquartile range (IQR)
Q3 − Q1, the spread of the middle half of the data.
Jacobian
The matrix of first partial derivatives of a vector-valued function.
KL divergence
Σp log(p/q): the extra surprise from using q instead of the true p; non-negative and asymmetric.
Kurtosis
A measure of tail heaviness; the normal distribution has kurtosis 3 (excess kurtosis 0).
Law of large numbers
Sample averages converge to the expected value as the sample size grows.
Learning rate
The step-size multiplier in gradient descent.
Likelihood
P(data | parameters) viewed as a function of the parameters.
Log-sum-exp trick
Computing log Σexi as m + log Σexi−m with m = max x to avoid overflow.
Logit
A raw, unnormalized model score that softmax or sigmoid turns into a probability; also log(p/(1 − p)).
MAP estimation
Choosing parameters that maximize likelihood times prior; equivalent to regularized MLE.
Marginal probability
The probability of one variable obtained by summing (or integrating) a joint distribution over the others.
Maximum likelihood (MLE)
Choosing parameters that make the observed data most probable.
Median
The middle value of sorted data; the 0.5 quantile.
Momentum
An optimizer technique that accumulates an exponentially weighted sum of past gradients to smooth and accelerate updates.
Mutual information
How much knowing one variable reduces uncertainty about another; zero only under independence.
Norm
A measure of vector length, e.g. L1 (sum of absolute values) or L2 (Euclidean length).
Null hypothesis
The default claim of no effect or no difference that a test tries to reject.
Orthogonal matrix
A square matrix with orthonormal columns (QTQ = I); preserves lengths and angles.
p-value
The probability, assuming the null hypothesis, of a result at least as extreme as the one observed.
Perplexity
The exponential of the average per-token cross-entropy; the effective number of choices a language model is unsure between.
Positional encoding
Information added to token representations so attention can use word order.
Power (statistical)
The probability that a test detects a real effect of a given size; 1 − β.
Principal component analysis (PCA)
Linear dimensionality reduction that projects data onto the top eigenvectors of its covariance matrix.
Quantile
A cut point below which a given fraction of sorted data falls (percentiles, quartiles, deciles).
Rank
The number of linearly independent rows or columns of a matrix.
RoPE
Rotary position embedding: rotating query and key vector pairs by position-dependent angles so attention depends on relative position.
Saddle point
A point with zero gradient that is a minimum in some directions and a maximum in others.
Scaled dot-product attention
softmax(QKT/√dk)V: weighting value vectors by normalized query-key similarity.
Singular value decomposition (SVD)
Factorizing any matrix as UΣVT with orthogonal U, V and non-negative singular values.
Skewness
A measure of asymmetry of a distribution; positive means a longer right tail.
Softmax
A function that turns a vector of logits into positive probabilities summing to 1: ezi/Σezj.
Standard deviation
The square root of variance, expressed in the data's units.
Standard error
The standard deviation of an estimator across repeated samples, e.g. σ/√n for the mean.
Temperature
A divisor applied to logits before softmax that controls how sharp or flat the output distribution is.
Tensor
A multi-dimensional array, such as a (batch, tokens, features) activation.
Type I / Type II error
Rejecting a true null (false positive) / failing to reject a false null (false negative).
Variance
The expected squared deviation from the mean.
z-score
The number of standard deviations a value lies from the mean.

Interview questions

Fundamentals

What is the difference between the mean, median and mode, and when would you use each?

The mean is the sum divided by the count; it uses every value and is pulled towards outliers. The median is the middle of the sorted data and is robust to outliers. The mode is the most frequent value and is the only one of the three that works for categorical data.

Use the mean for roughly symmetric data and when you need nice algebra (expectations, gradients). Use the median for skewed data (income, latency, house prices) or when outliers are likely. Use the mode for categories ("most common device type") or for imputing a categorical feature. Example: for [10, 12, 14, 15, 18, 20, 22, 25] the mean is 17 and the median is 16.5; adding 250 moves the mean to about 42.9 but the median only to 18.

Compute the mean, variance and standard deviation of [22, 18, 14, 10, 15, 20, 25, 12].

Mean = 136/8 = 17. Deviations: 5, 1, −3, −7, −2, 3, 8, −5; squared: 25, 1, 9, 49, 4, 9, 64, 25, sum 186.

  • Population variance = 186/8 = 23.25, standard deviation ≈ 4.82.
  • Sample variance = 186/7 ≈ 26.57, standard deviation ≈ 5.15.
  • Mean absolute deviation = (5+1+3+7+2+3+8+5)/8 = 4.25; range = 25 − 10 = 15.

Say which variance you mean: NumPy defaults to ddof=0, pandas to ddof=1.

Why do we divide by n − 1 for the sample variance?

Because we measure deviations from the sample mean, which is computed from the same data and is the point that minimizes the sum of squared deviations. Deviations from x̄ are therefore systematically smaller than deviations from the unknown true mean μ, so dividing by n underestimates the variance. Dividing by n − 1 corrects this bias exactly in expectation (E[s2] = σ2). The intuition is degrees of freedom: once x̄ is fixed, only n − 1 deviations are free. The correction matters for small n and is negligible for large n. Note that the standard deviation s is still slightly biased even with n − 1, because the square root is non-linear.

What are percentiles, quartiles and the IQR? How are they used to find outliers?

A percentile is the value below which a given percentage of the data falls; quartiles are the 25th (Q1), 50th (median) and 75th (Q3) percentiles. The IQR = Q3 − Q1 is the spread of the middle 50%.

Tukey's rule flags points below Q1 − 1.5·IQR or above Q3 + 1.5·IQR as potential outliers; box plots draw exactly these fences as whiskers. For [10, 12, 14, 15, 18, 20, 22, 25], Q1 = 13.5, Q3 = 20.5, IQR = 7, fences at 3 and 31. The rule is robust because quartiles themselves are not influenced by extreme values, unlike a z-score rule where the outlier inflates σ.

What is a z-score and why do we standardize features?

z = (x − μ)/σ tells you how many standard deviations a value lies from the mean; an exam score of 85 with mean 70 and σ 10 has z = 1.5.

Standardizing puts features on a common scale (mean 0, standard deviation 1). This matters for gradient-based models (otherwise large-scale features dominate gradients and cause zig-zagging), distance-based models (k-NN, k-means, SVM with RBF kernel), regularized models (so the penalty treats all coefficients fairly) and PCA. Tree-based models do not need it. Always fit the mean and standard deviation on the training set only.

What is skewness? What does a right-skewed distribution look like?

Skewness measures asymmetry: the third standardized moment E[((X − μ)/σ)3]. A right (positively) skewed distribution has a long tail on the right, most values clustered on the left, and typically mode < median < mean. Examples: income, response latency, file sizes, number of purchases. Left skew is the mirror image. For ML, strong skew can hurt linear models and distance metrics; a log or Box-Cox transform often fixes it, and the median is a better summary than the mean.

What is the difference between independent and mutually exclusive events?

Independent events do not influence each other: P(A ∩ B) = P(A)P(B), e.g. two separate coin flips. Mutually exclusive events cannot happen together: P(A ∩ B) = 0, e.g. rolling a 1 and a 6 on the same die. If both events have positive probability, mutually exclusive events are strongly dependent, because knowing A happened tells you B certainly did not. So the two ideas are almost opposites.

State Bayes' theorem and name each term.

P(A | B) = P(B | A) · P(A) / P(B).

  • P(A): prior, belief before the evidence.
  • P(B | A): likelihood, how probable the evidence is if A is true.
  • P(B): evidence or marginal likelihood, computed as Σ P(B | Ai)P(Ai); it normalizes the result.
  • P(A | B): posterior, the updated belief.

It is used in Naive Bayes classifiers, spam filters, medical diagnosis, Bayesian optimization and whenever you need to flip a conditional probability.

A disease affects 1% of people; a test has 95% sensitivity and a 5% false-positive rate. You test positive. What is the probability you have the disease?

About 16%. P(+) = 0.95 × 0.01 + 0.05 × 0.99 = 0.059, so P(sick | +) = 0.0095/0.059 ≈ 0.161.

With counts: of 10,000 people, 100 are sick and 95 test positive; of 9,900 healthy people, 495 test positive. So 95 of 590 positives are sick. The low base rate means false positives from the large healthy group dominate. A second independent positive test raises the probability to about 78%. The posterior here is exactly the precision of the test at this prevalence.

What is conditional probability? Give an example where P(A | B) differs from P(B | A).

P(A | B) = P(A ∩ B)/P(B): the probability of A restricted to cases where B occurred. In a table of 100 days, 40 rainy, 45 with heavy traffic and 30 both: P(heavy | rain) = 30/40 = 0.75, but P(rain | heavy) = 30/45 ≈ 0.67. A more dramatic example: P(speaks English | is a US president) is about 1, but P(is a US president | speaks English) is nearly 0. Bayes' theorem converts one into the other using the marginals.

What is a random variable? Discrete vs. continuous?

A random variable maps each random outcome to a number, e.g. the face value of a die roll. A discrete random variable takes countable values and has a probability mass function P(X = x) whose values sum to 1 (clicks, token IDs). A continuous random variable takes values in an interval and has a probability density function; probabilities are areas under the density, P(X = exact value) = 0, and density values can exceed 1 (height, latency). Both have a CDF F(x) = P(X ≤ x).

What is expected value? Compute it for a fair die.

The expected value is the probability-weighted average: E[X] = Σ x p(x) (or ∫ x f(x) dx). For a fair die, (1+2+3+4+5+6)/6 = 3.5, a value the die can never show, which illustrates that expectation is a long-run average rather than a typical outcome. Expectation is linear: E[aX + bY] = aE[X] + bE[Y] even if X and Y are dependent. In ML, training minimizes the expected loss over the data distribution, approximated by the average loss over the training set.

What is the difference between covariance and correlation?

Covariance E[(X − μX)(Y − μY)] indicates whether two variables move together, but its magnitude depends on units (metres × kilograms) and scale. Correlation divides covariance by both standard deviations, giving a unit-free number in [−1, 1] that measures the strength of the linear relationship. So correlation is comparable across variable pairs while covariance is not. Both only capture linear relationships, and neither implies causation.

Does zero correlation imply independence?

No. Correlation only measures linear association. If X is symmetric around zero (say uniform on [−1, 1]) and Y = X2, then Cov(X, Y) = E[X3] − E[X]E[X2] = 0, yet Y is a deterministic function of X. Independence implies zero correlation, but not the reverse. The one notable exception: for jointly Gaussian variables, zero correlation does imply independence. To detect non-linear dependence use mutual information, Spearman correlation (monotonic) or distance correlation.

Describe the normal distribution and the 68-95-99.7 rule.

The normal distribution N(μ, σ2) is a symmetric bell curve fully described by its mean and variance, with density (1/(σ√(2π)))e−(x−μ)2/(2σ2). About 68% of values lie within 1σ of the mean, 95% within 2σ (1.96σ exactly) and 99.7% within 3σ. It is ubiquitous because of the central limit theorem, and it underlies MSE (Gaussian noise), weight initialization, VAE latents and diffusion noise.

What are the Bernoulli and binomial distributions?

Bernoulli(p) models a single yes/no trial: P(1) = p, P(0) = 1 − p, mean p, variance p(1 − p). Binomial(n, p) counts successes in n independent Bernoulli trials: P(k) = C(n, k)pk(1 − p)n−k, mean np, variance np(1 − p). Example: P(7 heads in 10 fair flips) = 120/1024 ≈ 0.117. A binary classifier's sigmoid output parameterizes a Bernoulli, and binary cross-entropy is its negative log-likelihood; conversions out of n visitors in an A/B test are binomial.

When would you use a Poisson distribution?

To model counts of events in a fixed interval when events occur independently at a constant average rate λ: requests per second, errors per hour, arrivals per day. P(k) = λke−λ/k!, and both the mean and variance equal λ. With λ = 3, P(0) ≈ 0.050 and P(2) ≈ 0.224. The waiting time between Poisson events is exponential. If the observed variance is much larger than the mean (overdispersion), use a negative binomial instead.

What is the central limit theorem and why does it matter?

The CLT says that the mean of n independent, identically distributed samples with finite variance is approximately normal with mean μ and standard deviation σ/√n as n grows, regardless of the shape of the original distribution. It matters because it lets us build confidence intervals and hypothesis tests (z/t tests, A/B tests) for almost any metric using normal-distribution math. It also explains why mini-batch gradient noise shrinks as 1/√B and why averaging (ensembles, repeated measurements) reduces variance. Caveat: it is about the sample mean, not the data itself, and it needs finite variance.

What is a p-value?

The probability of observing data at least as extreme as what you saw, assuming the null hypothesis is true. A small p-value means the data would be surprising under the null, which is evidence against it. It is not the probability that the null is true, not the probability that the result is due to chance, and not a measure of effect size or importance. With huge samples, trivially small effects produce tiny p-values, so always report effect sizes and confidence intervals alongside.

Explain Type I and Type II errors.

A Type I error is rejecting a true null hypothesis: a false positive, such as declaring a useless feature effective. Its probability is α, the significance level. A Type II error is failing to reject a false null: a false negative, missing a real effect. Its probability is β, and power = 1 − β. For a fixed sample size, lowering α increases β; only more data, larger effects or lower variance reduce both. In classification, Type I corresponds to false positives (hurting precision) and Type II to false negatives (hurting recall).

What is a vector and what is the dot product?

A vector is an ordered list of numbers representing a point or direction in space, such as a feature vector or an embedding. The dot product a·b = Σaibi = |a||b|cos θ measures how aligned two vectors are: positive if they point similarly, zero if orthogonal, negative if opposite. Example: [2, 3, 1]·[4, −1, 5] = 8 − 3 + 5 = 10. It is the core operation of ML: every neuron computes w·x + b, attention scores are query-key dot products, and recommenders score user-item dot products.

What is the difference between L1 and L2 norms?

L1 = Σ|xi| (city-block length); L2 = √(Σxi2) (straight-line length). For [2, 3, 1], L1 = 6 and L2 = √14 ≈ 3.74. As regularizers, L1 (Lasso) drives many weights exactly to zero, producing sparse models and feature selection, while L2 (Ridge, weight decay) shrinks all weights smoothly and handles correlated features more gracefully. As losses, L1 (MAE) is robust to outliers and L2 (MSE) penalizes large errors heavily.

What are the rules for multiplying two matrices?

An (m × n) matrix can multiply an (n × p) matrix; the inner dimensions must match and the result is (m × p). Entry Cij is the dot product of row i of A and column j of B. Example: [[1, 2], [3, 4]] × [[5, 6], [7, 8]] = [[19, 22], [43, 50]]. Matrix multiplication is associative and distributive but not commutative (AB ≠ BA in general). In NumPy, @ is matrix multiplication while * is element-wise.

What is a matrix transpose and an identity matrix?

The transpose AT swaps rows and columns: (AT)ij = Aji, so a 3×2 matrix becomes 2×3; note (AB)T = BTAT. The identity matrix I has ones on the diagonal and zeros elsewhere, and AI = IA = A: it is the "do nothing" transformation. Transposes appear in attention (QKT), in the normal equation and in backprop (gradients flow through WT). Identity appears in residual connections and ridge regression (XTX + λI).

When does a matrix have an inverse?

Only when it is square and full rank, equivalently when its determinant is non-zero, when all its eigenvalues are non-zero, and when its columns are linearly independent. For a 2×2 matrix [[a, b], [c, d]], the inverse is (1/(ad − bc))[[d, −b], [−c, a]]. A singular matrix, such as [[1, 2], [2, 4]] with determinant 0, collapses space onto a lower dimension, losing information that cannot be undone. In ML this happens with duplicate or perfectly collinear features, making XTX non-invertible.

What is a derivative and what does it mean in ML?

A derivative is the instantaneous rate of change of a function: how much the output changes per tiny change in the input, geometrically the slope of the tangent line. For f(x) = x2, f'(x) = 2x, so the slope at x = 3 is 6 and at x = 0 is 0 (the minimum). In ML, the derivative of the loss with respect to a weight tells us which direction and how strongly to adjust that weight to reduce the loss. With many weights, the collection of partial derivatives is the gradient.

What is gradient descent?

An iterative optimization algorithm: start with (usually random) parameters, compute the gradient of the loss, and update w ← w − η∇L, stepping opposite to the gradient because the gradient points uphill. The learning rate η sets the step size: too small is slow, too large overshoots or diverges. Example: L = w2, η = 0.1, starting at 5: each step multiplies w by 0.8, giving 4, 3.2, ... and about 0.06 after 20 steps. Variants differ in how much data they use per step (batch, stochastic, mini-batch) and how they adapt the step (momentum, Adam).

What is the difference between a loss function and a cost function?

Strictly, the loss is the error on a single example, such as (ŷ − y)2, and the cost (or objective) is the aggregate over the dataset, typically the mean loss plus any regularization term. In practice, and in libraries such as PyTorch and Keras, "loss" is used for both, and the value you call backward() on is the batch-averaged cost. The quantity being minimized is always the cost.

What is the sigmoid function and why is it used for binary classification?

σ(z) = 1/(1 + e−z) maps any real number into (0, 1): σ(0) = 0.5, σ(2) ≈ 0.88, σ(−2) ≈ 0.12. It converts a raw score (logit) into a probability for the positive class, which is exactly what binary cross-entropy expects. It is smooth and differentiable with the convenient derivative σ(1 − σ). Its inverse is the log-odds (logit) function, which is why logistic regression is a linear model of log-odds. It is poor in hidden layers because it saturates and has a maximum derivative of only 0.25.

What does softmax do? Is it a loss function?

Softmax converts a vector of logits into a probability distribution: pi = ezi/Σezj. All outputs are positive and sum to 1, and larger logits get exponentially more mass: [2, 1, 0] becomes [0.665, 0.245, 0.090]. It is not a loss; it is an output activation. Categorical cross-entropy is the loss computed on its output, and libraries fuse the two into one stable operation that takes raw logits. Softmax is also used inside attention to turn scores into weights.

What is entropy in information theory?

Entropy H(X) = −Σ p(x) log p(x) is the expected surprise, or average uncertainty, of a distribution. A fair coin has 1 bit of entropy; a coin with 90% heads has about 0.47 bits; a certain outcome has 0. It is maximized by the uniform distribution (log2 K bits for K outcomes). In ML it measures model uncertainty, drives decision-tree splits (information gain), appears in entropy bonuses in RL, and is the baseline in the identity cross-entropy = entropy + KL.

What is cross-entropy loss, intuitively?

It is −log of the probability the model assigned to the correct class, averaged over examples. Correct and confident gives low loss (−ln 0.9 = 0.105); wrong and confident gives very high loss (−ln 0.1 = 2.30; −ln 0.01 = 4.6). The negative sign turns "maximize the log-probability of the truth" into a positive quantity to minimize. It is the negative log-likelihood of a categorical model, so minimizing it is maximum likelihood estimation. It is used for binary (with sigmoid), multi-class (with softmax) and LLM next-token training.

Going deeper

Explain the law of large numbers vs. the central limit theorem.

The LLN is about convergence of a value: as n grows, the sample mean converges to the true mean. The CLT is about the shape of the fluctuations: for large n, the sample mean's error is approximately normal with standard deviation σ/√n. LLN tells you averaging works; CLT tells you how uncertain the average is and lets you build confidence intervals. Example: the mean of 100 die rolls is near 3.5 (LLN), and across repetitions those means form a bell curve with standard deviation about 0.171 (CLT).

How do you interpret a 95% confidence interval?

If you repeated the entire sampling and interval-building procedure many times, about 95% of the intervals produced would contain the true parameter. For any single computed interval, the parameter is either in it or not; the 95% describes the procedure, not this interval. Saying "there is a 95% probability the true mean is in [48, 52]" is the interpretation of a Bayesian credible interval, not a frequentist confidence interval. Example: mean 50, s = 10, n = 100 gives 50 ± 1.96 × 1 = [48.04, 51.96].

When would you use a t-test instead of a z-test?

Use a t-test when the population standard deviation is unknown and estimated from the sample, especially for small samples. The t-distribution has heavier tails than the normal to reflect the extra uncertainty from estimating σ, and it approaches the normal as degrees of freedom grow (by about n = 30 the difference is small). Use a z-test when σ is known or for large-sample proportion tests. Example: n = 25, mean 52 vs. target 50, s = 5 gives t = 2.0 on 24 degrees of freedom, p ≈ 0.057, whereas a z-test would give p ≈ 0.046: the choice can flip a borderline decision.

What is the difference between a paired and an unpaired t-test?

An unpaired (two-sample) t-test compares two independent groups, such as users in control vs. treatment. A paired t-test compares two measurements on the same units, such as the same patients before and after, or two models evaluated on the same test examples; it runs a one-sample t-test on the per-unit differences. Pairing removes between-unit variability, so it is much more powerful when measurements are correlated. Comparing two models' per-example scores with an unpaired test wastes that power and can miss real differences.

What is a chi-square test used for? Walk through one.

The chi-square test of independence checks whether two categorical variables are associated; the goodness-of-fit version checks whether counts match an expected distribution. Statistic: χ2 = Σ(O − E)2/E with expected counts E = row total × column total / grand total.

Example: control 100 conversions / 900 non-conversions, treatment 120 / 880. Expected is 110 / 890 per row. χ2 = 2(100/110) + 2(100/890) ≈ 2.04 on 1 degree of freedom, p ≈ 0.15: no significant association. For a 2×2 table this equals the square of the two-proportion z statistic. Requirements: independent observations and expected counts of at least about 5 per cell (otherwise Fisher's exact test).

How do you calculate the sample size for an A/B test?

Decide the baseline rate, the minimum detectable effect (MDE), α and power. For two proportions, n per group ≈ (z1−α/2 + z1−β)2 × (p1(1−p1) + p2(1−p2)) / (p1 − p2)2.

Example: 10% baseline, detect 12%, α = 0.05 (z = 1.96), power 0.8 (z = 0.84): n ≈ 7.84 × 0.1956 / 0.0004 ≈ 3,840 per group. Halving the MDE roughly quadruples n. Then convert n into a duration using traffic, round up to full weeks for seasonality, and commit to it before starting to avoid peeking.

What is the multiple comparisons problem and how do you handle it?

If you run many tests at α = 0.05, the chance of at least one false positive grows quickly: with 20 independent tests it is 1 − 0.9520 ≈ 64%. This happens when testing many metrics, segments, variants or hyperparameters. Fixes: Bonferroni (test each at α/m, simple but conservative), Holm's step-down method, Benjamini-Hochberg to control the false discovery rate (better when testing many hypotheses), pre-registering one primary metric, and validating discoveries on fresh data.

What is statistical power and what affects it?

Power is the probability that a test rejects the null when a real effect of a specified size exists (1 − β), conventionally targeted at 0.8. It increases with larger sample size, larger true effect, lower variance in the metric, a higher α and using one-sided or paired designs when justified. Variance-reduction techniques (such as using pre-experiment covariates, CUPED) increase power without more traffic. An underpowered test mostly produces "no significant difference" results, and the significant results it does produce tend to overestimate the effect.

What is the bootstrap and when would you use it?

The bootstrap estimates the sampling distribution of a statistic by resampling the observed data with replacement many times (for example 1,000 to 10,000) and recomputing the statistic each time. The spread of those values estimates the standard error, and their 2.5th and 97.5th percentiles give a 95% confidence interval. Use it when there is no simple formula, e.g. for a median, F1, AUC, a ratio metric, or the difference in accuracy between two models (resample test examples and compute both models' scores on the same resample, a paired bootstrap). It assumes the sample is representative and the observations are independent.

When would you use the bootstrap instead of cross-validation?

They answer different questions. Cross-validation retrains the model on each fold and estimates the expected performance of a training procedure (algorithm plus preprocessing plus hyperparameters). The bootstrap resamples a fixed set of scores or the raw observations to estimate the sampling distribution of a statistic: a confidence interval for accuracy, F1, AUC, or the paired difference between two frozen models. Use CV on the training data to choose models; use a paired bootstrap (or McNemar) on a sealed test set to decide whether the winner is really better. A bootstrap of training accuracy is optimistic, because every resample still overlaps the original training rows. Out-of-bag scores from bagged trees are the exception that works.

How does MSE relate to maximum likelihood?

Assume y = f(x) + ε with ε ~ N(0, σ2). The likelihood of one example is (1/(σ√(2π)))exp(−(y − f(x))2/(2σ2)). The negative log-likelihood of the dataset is (1/(2σ2))Σ(y − f(x))2 + n log(σ√(2π)). With σ fixed, minimizing it is exactly minimizing the sum of squared errors. So MSE implicitly assumes Gaussian, constant-variance noise and estimates the conditional mean. Similarly, MAE corresponds to Laplace noise and estimates the conditional median.

Why is cross-entropy preferred over MSE for classification?

First, it is the correct likelihood: cross-entropy is the negative log-likelihood of a Bernoulli or categorical model. Second, gradients: with sigmoid + MSE, the gradient with respect to the logit contains σ'(z), which is nearly 0 when the model is confidently wrong, so learning stalls exactly when it should be fastest. With sigmoid + cross-entropy the gradient is simply p − y, large when very wrong. Third, for logistic regression, cross-entropy is convex in the parameters while MSE is not. Finally, cross-entropy heavily penalizes confident mistakes, encouraging calibrated probabilities.

Derive the derivative of the sigmoid function.

σ(x) = (1 + e−x)−1. By the chain rule, σ'(x) = −(1 + e−x)−2 · (−e−x) = e−x/(1 + e−x)2. Write this as [1/(1 + e−x)] · [e−x/(1 + e−x)] = σ(x)(1 − σ(x)). At x = 0 it is 0.25 (its maximum), at x = 2 about 0.105, at x = 5 about 0.0066. The small maximum is why stacking sigmoid layers causes vanishing gradients.

What is the gradient of softmax cross-entropy with respect to the logits?

For logits z, p = softmax(z) and one-hot target y, L = −Σyk log pk. Using ∂pk/∂zj = pk(δkj − pj), the gradient simplifies to ∂L/∂zj = pj − yj. Example: p = [0.7, 0.2, 0.1] with the true class first gives a gradient of [−0.3, 0.2, 0.1]: raise the true class's logit, lower the others in proportion to their probability. This clean form is why softmax and cross-entropy are always paired and fused in implementations.

What is the chain rule and how does backpropagation use it?

The chain rule says the derivative of a composition is the product of local derivatives: if L = f(g(x)), dL/dx = f'(g(x))g'(x); with branching, you sum over all paths. A network is a long composition, so ∂L/∂w for an early weight is the product of the derivatives of every later operation. Backpropagation computes these products starting from the loss and moving backwards, storing each layer's upstream gradient so it is reused rather than recomputed. This gives all gradients in time proportional to one forward pass, rather than one pass per weight.

What are the Jacobian and the Hessian?

The Jacobian of a vector function f: Rn → Rm is the m×n matrix of first derivatives ∂fi/∂xj; e.g. f(x, y) = [x2y, 5x + sin y] gives [[2xy, x2], [5, cos y]]. Backprop is a sequence of vector-Jacobian products. The Hessian of a scalar function is the n×n symmetric matrix of second derivatives, describing curvature; its eigenvalues classify stationary points (all positive = minimum, mixed = saddle) and bound the stable learning rate. Newton's method uses the inverse Hessian, but for large models it is too big to form, so approximations are used.

Compare batch, stochastic and mini-batch gradient descent.

Batch GD computes the exact gradient over the whole dataset per step: smooth but slow and memory-hungry. Stochastic GD uses one example per step: cheap and noisy, with poor hardware utilization, though the noise can help escape saddles. Mini-batch GD uses B examples (typically 32 to a few thousand): it balances noise and efficiency and makes good use of GPUs; this is what everyone means by "SGD" in practice. Gradient noise scales as 1/√B, so larger batches allow larger learning rates but can generalize slightly worse without tuning.

How does momentum help gradient descent?

Momentum keeps an exponentially weighted running sum of past gradients, v = βv + g, and steps along v (β ≈ 0.9). In directions where gradients consistently agree, steps accumulate and speed up (up to 1/(1 − β) = 10×); in directions where gradients oscillate, such as across a narrow ravine, they cancel out. The result is faster progress along shallow valleys, less zig-zagging, and the ability to roll through small bumps, plateaus and saddle points. Nesterov momentum evaluates the gradient at the look-ahead position for slightly better correction.

Explain the Adam optimizer, including bias correction.

Adam keeps a moving average of gradients m (momentum, β1 = 0.9) and of squared gradients v (per-parameter scale, β2 = 0.999). The update is w ← w − ηm̂/(√v̂ + ε), so each parameter's step is normalized by its recent gradient magnitude. Because m and v start at zero, early estimates are biased towards zero; dividing by (1 − βt) corrects this. At t = 1, m̂ = g and v̂ = g2, so the first step is about η·sign(g). Adam is robust to gradient scale and needs little tuning, which is why it (as AdamW) is the default for transformers; it costs two extra buffers per parameter.

What is the difference between L2 regularization and weight decay in Adam (AdamW)?

For plain SGD, adding λ||w||2/2 to the loss is identical to decaying weights by ηλw each step. In Adam, however, the L2 gradient λw is added to g and then divided by √v̂, so parameters with large historical gradients receive almost no regularization while rarely updated ones are regularized strongly: not the intended behavior. AdamW decouples the two: it performs the adaptive update from the data gradient, then separately subtracts ηλw. This gives consistent regularization and better generalization, which is why AdamW is standard for transformer training.

Why do we use learning-rate warmup and decay?

Warmup: at the start, weights are random, gradients can be large and Adam's second-moment estimates are based on few samples, so a full learning rate can cause immediate divergence or push the model into a bad region. Ramping the LR up linearly over the first 1-5% of steps lets things stabilize. Decay: later in training, the noise in mini-batch gradients keeps the model bouncing around a minimum; lowering the LR (cosine, linear or step decay) reduces that noise floor and lets it settle into a lower loss. Warmup plus cosine decay is the standard LLM schedule.

What is convexity and why does it matter in optimization?

A function is convex if the line between any two points on its graph lies on or above the graph; equivalently its Hessian is positive semi-definite everywhere. For convex functions every local minimum is global, so gradient descent with an appropriate learning rate is guaranteed to find the optimum regardless of initialization. Linear regression (MSE), logistic regression (cross-entropy), ridge, lasso and SVMs are convex. Neural networks are non-convex because of the non-linear activations and weight symmetries, so results depend on initialization, optimizer and learning rate, though in practice most minima found are good.

What are eigenvalues and eigenvectors, intuitively and with an example?

An eigenvector of a square matrix A is a non-zero vector whose direction is unchanged by A: Av = λv, where λ (the eigenvalue) is the stretch factor. Example: A = [[2, 1], [1, 2]] has eigenvector [1, 1] with λ = 3 and [1, −1] with λ = 1: A stretches the diagonal direction threefold and leaves the anti-diagonal alone. The trace (4) equals the sum of eigenvalues and the determinant (3) their product. In ML, eigenvectors of the covariance matrix are the principal components, and eigenvalues of the Hessian describe curvature.

Explain PCA step by step.
  1. Center each feature (and standardize if units differ).
  2. Compute the covariance matrix Σ = XcTXc/(n − 1).
  3. Find its eigenvectors and eigenvalues; eigenvectors are orthogonal directions, eigenvalues are the variance along each.
  4. Sort by eigenvalue and keep the top k, choosing k by cumulative explained variance (e.g. 95%) or a scree-plot elbow.
  5. Project: Z = XcVk.

Example: eigenvalues 5.2, 3.1, 0.4 explain 60%, 36% and 4%; keeping two components retains 96% of the variance. In practice PCA is computed via SVD of Xc for numerical stability.

What is SVD and how is it related to PCA?

The singular value decomposition factors any m×n matrix as A = UΣVT, with orthogonal U and V and non-negative singular values on the diagonal of Σ, sorted in decreasing order. For a centered data matrix Xc, the right singular vectors V are exactly the principal components, and the covariance eigenvalues are λi = σi2/(n − 1). Truncating to the top k singular values gives the best rank-k approximation (Eckart-Young), which powers compression, denoising, latent semantic analysis and matrix-factorization recommenders. SVD avoids forming XTX and is more numerically stable than eigendecomposing the covariance.

What is the rank of a matrix and why does low rank matter in ML?

Rank is the number of linearly independent rows (or columns), i.e. the dimension of the space the matrix can map onto. [[1, 2], [2, 4]] has rank 1 because the second row is twice the first. A low-rank matrix can be stored and computed as a product of two thin matrices: a d×d rank-r matrix needs 2dr numbers instead of d2. This idea underlies matrix-factorization recommenders (users × k and k × items), PCA/truncated SVD compression, and LoRA, which fine-tunes LLMs by learning a low-rank update ΔW = BA with r around 8-64. Rank deficiency in a data matrix signals redundant (collinear) features.

When would you use cosine similarity instead of Euclidean distance?

Use cosine when the direction of a vector carries the meaning and its magnitude does not: text embeddings, TF-IDF or bag-of-words vectors (a long and a short document on the same topic point the same way), user preference vectors. Euclidean is appropriate when absolute differences in magnitude matter and features are scaled comparably, e.g. physical measurements, k-means on standardized features. For L2-normalized vectors the two give the same ranking since ||a − b||2 = 2 − 2cos θ. Cosine also degrades less in high dimensions for embedding data.

What is KL divergence and why is it not a distance?

DKL(P||Q) = Σp log(p/q) measures the expected extra surprise from using Q to model data that actually follows P. It is always ≥ 0 and zero only when P = Q. It is not a distance because it is asymmetric (D(P||Q) ≠ D(Q||P); with P = [0.5, 0.5] and Q = [0.9, 0.1], they are 0.511 and 0.368 nats) and it violates the triangle inequality. It can also be infinite if Q assigns zero probability where P does not. Jensen-Shannon divergence is a symmetric, bounded alternative. KL appears in VAEs, distillation and RLHF.

What is perplexity and how does it relate to cross-entropy?

Perplexity is the exponential of the average per-token negative log-likelihood (cross-entropy in nats): PPL = exp(−(1/N)Σ ln p(tokeni | context)). It is the effective number of equally likely choices the model is uncertain between. If a model assigns 0.5, 0.25 and 0.1 to three true tokens, the mean NLL is 1.461 and PPL ≈ 4.31. A training loss of 2.0 corresponds to PPL ≈ 7.4. Lower is better; comparisons are only valid with the same tokenizer and evaluation data, and low perplexity does not guarantee helpful or factual outputs.

What is the difference between MLE and MAP?

MLE chooses θ maximizing P(D | θ), the likelihood of the data. MAP chooses θ maximizing P(D | θ)P(θ), which includes a prior belief. In log form, MAP = MLE loss plus −log prior, i.e. a regularization term: a Gaussian prior gives L2, a Laplace prior gives L1. With a Beta(2, 2) prior and 7 heads in 10 flips, MLE gives 0.7 while MAP gives 8/12 ≈ 0.667. With little data, MAP avoids extreme estimates (MLE says p = 1 after 3 heads in 3 flips); with lots of data the two converge. Neither gives uncertainty; full Bayesian inference keeps the whole posterior.

Why do we subtract the maximum before computing softmax?

To prevent overflow: ex exceeds FP32's range for x above about 88 (and FP16's for x above about 11), producing inf and then NaN. Softmax is invariant to adding the same constant to every logit, because the factor e−c cancels in numerator and denominator, so subtracting the max gives an identical result. After the shift, the largest exponent is e0 = 1 and the denominator is at least 1, so neither overflow nor division by zero can occur. The same idea gives the log-sum-exp trick: logΣexi = m + logΣexi−m; for [1000, 999] the answer is 1000.313 rather than inf.

Why do neural networks need non-linear activation functions?

Without them, stacked linear layers collapse into one linear map: W2(W1x + b1) + b2 = (W2W1)x + (W2b1 + b2). Depth would add no expressive power, and the network could not model even XOR. A non-linear activation between layers lets the network bend and fold space, and with enough units it can approximate any continuous function on a bounded domain (universal approximation). The choice of activation also determines gradient flow, which is why ReLU-family and GELU/SiLU activations dominate hidden layers.

What is the dying ReLU problem and how can you fix it?

A ReLU neuron outputs 0 and has zero gradient for all negative inputs. If a large update (often from a high learning rate) pushes its bias and weights so that its pre-activation is negative for every input, it never activates again and never receives gradient: it is "dead". A large fraction of dead units wastes capacity. Fixes: lower the learning rate, use He initialization, add normalization layers, or use variants with non-zero negative slope (Leaky ReLU, PReLU, ELU) or smooth ones (GELU, SiLU). Monitoring the fraction of zero activations per layer detects the problem.

What does the temperature parameter do in LLM sampling?

It divides the logits before softmax: pi = ezi/T/Σezj/T. T < 1 sharpens the distribution (more deterministic), T > 1 flattens it (more diverse), T → 0 approaches greedy argmax and T → ∞ approaches uniform. For logits [2, 1, 0]: T = 0.5 gives [0.867, 0.117, 0.016], T = 1 gives [0.665, 0.245, 0.090], T = 2 gives [0.506, 0.307, 0.186]. It never changes the ranking of tokens. Use low T (0-0.3) for code, extraction and factual tasks, around 0.7 for chat and higher for creative writing. It is usually set via the API, typically between 0 and 1 or 2.

What is the difference between top-k and top-p sampling?

Top-k keeps the k most probable tokens, renormalizes their probabilities to sum to 1, and samples. Top-p (nucleus) keeps the smallest set of tokens whose cumulative probability reaches p, renormalizes and samples. Top-k uses a fixed candidate count, which is too permissive when the model is confident and too restrictive when it is uncertain; top-p adapts the candidate count to the shape of the distribution, acting like a dynamic k. They can be combined (the survivors are the intersection) together with temperature, which reshapes the probabilities first. Neither prevents hallucination; they only control randomness.

Advanced

Why is attention scaled by √dk? What happens if you remove the scaling?

If query and key components are independent with mean 0 and variance 1, the dot product q·k = Σi=1dk qiki is a sum of dk terms each with variance 1, so its variance is dk and its standard deviation √dk. With dk = 64 or 128, raw scores are around ±8 to ±11, which pushes softmax into saturation: one weight near 1, the rest near 0. The softmax Jacobian diag(p) − ppT is then close to zero, so gradients to Q and K vanish and training becomes slow and unstable. Dividing by √dk restores unit variance so softmax stays in its sensitive range. The factor is the exact standard deviation of the dot product, not an arbitrary constant; some models instead normalize Q and K (QK-norm) or fold the scale into learned parameters.

Why is softmax applied to QKT before multiplying by V, rather than softmax(QKTV)?

The two steps have different roles. QKT scores relevance between positions (where to look), and softmax turns each row into non-negative weights summing to 1. Multiplying by V then gathers content (what to retrieve) as a convex combination of value vectors, so the output stays on the same scale as the values regardless of sequence length. softmax(QKTV) would mix content before deciding relevance, normalize across feature dimensions instead of positions, and lose the interpretation of attention weights as a distribution over tokens. The shapes also reflect this: the T×T weight matrix is applied to the T×dv values.

Explain how RoPE encodes relative position mathematically.

RoPE splits each query and key into 2D pairs and rotates pair i by the angle mθi, where m is the position and θi = 10000−2i/d. For a rotation matrix R, (Rmq)T(Rnk) = qTRmTRnk = qTRn−mk, because rotations compose by adding angles and RT is the inverse rotation. So the attention score depends on the content of q and k and only on their relative offset n − m, not their absolute positions. Rotations preserve norms, so no magnitude distortion occurs. High-frequency pairs capture local order and low-frequency pairs long-range position. It is applied to Q and K in every layer, not to V. Long-context extensions (position interpolation, NTK-aware scaling, YaRN) rescale the angles.

Why do sinusoidal positional encodings use both sine and cosine at geometric frequencies?

Each (sin, cos) pair at frequency ω places a position on a circle. Shifting position by k is a fixed rotation of that point: [sin(ω(p + k)), cos(ω(p + k))] is a linear transform of [sin ωp, cos ωp] that depends only on k, so relative offsets are linearly accessible to attention. Using both functions also means no dimension pair is ever zero simultaneously, avoiding ambiguous positions. Geometrically spaced wavelengths (from about 6 positions to about 62,800) act like clock hands for seconds, minutes and hours, so every position has a unique multi-scale signature even though individual dimensions repeat. The encodings are defined for any position, allowing some extrapolation, unlike learned absolute embeddings.

What is the computational and memory complexity of self-attention, and how does multi-head attention affect it?

For sequence length T and model width d, computing Q, K, V costs O(Td2); computing QKT and multiplying by V costs O(T2d); storing the attention matrix costs O(T2) per head. So attention is quadratic in sequence length, which dominates for long contexts. Splitting into h heads with dk = d/h keeps total FLOPs roughly the same as a single full-width head, but multiplies the number of T×T score matrices by h. Fused kernels compute attention in tiles with an online softmax to avoid materializing the T×T matrix (linear memory), and during generation the KV cache makes each new token cost O(Td) instead of recomputing everything.

Show that minimizing cross-entropy is equivalent to minimizing KL divergence and to maximum likelihood.

KL(P||Q) = Σp log p − Σp log q = −H(P) + H(P, Q). The entropy H(P) of the data distribution does not depend on the model, so minimizing H(P, Q) over the model Q is the same as minimizing KL(P||Q). Replacing P with the empirical distribution of the training set, H(Pdata, Qθ) = −(1/n)Σi log qθ(yi | xi), which is the average negative log-likelihood. So cross-entropy training = forward-KL minimization = MLE. The forward-KL direction explains why MLE-trained models are mass-covering: they are heavily penalized for assigning near-zero probability to anything that occurs in the data.

Explain forward vs. reverse KL and where each is used.

Forward KL, D(P||Q) = EP[log P/Q], averages over the true distribution; it blows up wherever Q ≈ 0 but P > 0, so the optimal Q spreads to cover all modes of P (mean-seeking), possibly putting mass between modes. It is what MLE and cross-entropy minimize. Reverse KL, D(Q||P) = EQ[log Q/P], averages over the model; it blows up where Q > 0 but P ≈ 0, so Q concentrates on one mode and ignores others (mode-seeking). Variational inference and VAEs minimize reverse KL to an intractable posterior; the RLHF KL penalty Eπ[log π/πref] is also a reverse KL, keeping the policy within the support of the reference model.

Derive the normal equation for linear regression. When should you not use it?

Minimize L(w) = ||Xw − y||2 = wTXTXw − 2yTXw + yTy. The gradient is 2XTXw − 2XTy; setting it to zero gives XTXw = XTy, so w = (XTX)−1XTy when XTX is invertible. Geometrically, the residual y − Xw is orthogonal to every column of X. Avoid the explicit inverse when features are collinear (singular or ill-conditioned XTX; forming it squares the condition number), when d is large (O(d3) inversion, O(nd2) to form), or when n is huge or streaming. Use QR/SVD-based least squares, add ridge (XTX + λI), or use gradient descent.

Show that L2 regularization is MAP estimation with a Gaussian prior.

MAP maximizes log P(D | w) + log P(w). Take a prior w ~ N(0, τ2I): log P(w) = −||w||2/(2τ2) + const. With Gaussian noise of variance σ2, log P(D | w) = −||y − Xw||2/(2σ2) + const. Negating and multiplying by 2σ2, MAP minimizes ||y − Xw||2 + (σ2/τ2)||w||2: ridge regression with λ = σ2/τ2. A narrow prior (small τ) or noisy data (large σ) means strong regularization. A Laplace prior p(w) ∝ e−|w|/b similarly gives L1 (lasso), whose sharp peak at 0 produces sparsity.

Why does L1 regularization produce sparse weights while L2 does not?

Three views. Geometric: the L1 constraint region ||w||1 ≤ t is a diamond with corners on the axes; elliptical loss contours usually first touch it at a corner, where some coordinates are exactly zero. The L2 ball is round, so the touching point generically has all coordinates non-zero. Gradient: the L1 penalty's (sub)gradient is λ·sign(w), a constant push towards zero even for tiny weights, so weights whose data gradient is smaller than λ get pinned at 0; the L2 gradient 2λw vanishes as w shrinks, so weights approach but never reach zero. Probabilistic: L1 is a Laplace prior with a sharp peak at zero. Proximal methods implement L1 with soft-thresholding, which sets small weights exactly to 0.

What role do Hessian eigenvalues play in choosing a learning rate?

Near a minimum, the loss is approximately quadratic: L(w) ≈ L* + ½(w − w*)TH(w − w*). Along an eigenvector of H with eigenvalue λ, a gradient step multiplies the error by (1 − ηλ). Stability requires |1 − ηλ| < 1 for all directions, i.e. η < 2/λmax. Convergence along the flattest direction proceeds at rate (1 − ηλmin), so the number of steps scales with the condition number κ = λmax/λmin. This is why ill-conditioned problems zig-zag and why feature scaling, normalization layers, momentum (which improves the dependence to √κ) and adaptive or second-order methods help. Negative eigenvalues indicate saddle directions that noise and momentum can exploit to escape.

Why are saddle points more common than local minima in high-dimensional loss surfaces?

At a critical point (zero gradient), the Hessian has n eigenvalues. For a local minimum, all n must be positive. If signs were roughly random, the probability of all being positive falls exponentially with n, so most critical points have mixed signs: saddles. Empirical and theoretical work on random high-dimensional functions supports this, and further suggests that critical points with high loss tend to be saddles while true minima tend to have loss close to the global minimum. Plain gradient descent can slow down near saddles because gradients are small there, but momentum, gradient noise from mini-batches, and adaptive methods help escape along negative-curvature directions.

Derive the gradients of a dense layer in matrix form.

Let Z = XW + b with X (B×d), W (d×h), b (h) and upstream gradient G = ∂L/∂Z (B×h). Since Zbj = Σi XbiWij + bj:

  • ∂L/∂Wij = Σb GbjXbi, so ∂L/∂W = XTG (d×h).
  • ∂L/∂bj = Σb Gbj: sum G over the batch.
  • ∂L/∂X = GWT (B×d), passed to the previous layer.

Through an element-wise activation A = f(Z): ∂L/∂Z = ∂L/∂A ⊙ f'(Z). A quick sanity check is that each gradient has the same shape as its variable, which forces the transposes into place.

Why does reverse-mode automatic differentiation suit neural networks better than forward mode?

For a function from n inputs to m outputs, forward mode computes one Jacobian column (a directional derivative for one input direction) per pass, so a full gradient needs n passes. Reverse mode computes one Jacobian row (the gradient of one output with respect to all inputs) per pass. Training has millions or billions of inputs (parameters) and a single scalar output (the loss), so reverse mode gives the full gradient in one backward pass costing a small constant multiple of the forward pass. The price is memory: intermediate activations must be stored for the backward pass, which motivates activation checkpointing. Forward mode is preferred when outputs outnumber inputs, e.g. Jacobian-vector products for sensitivity analysis.

How do Xavier and He initialization keep signal variance stable?

For z = Σi=1n wixi with independent zero-mean terms, Var(z) = n·Var(w)·Var(x). To keep Var(z) = Var(x) layer after layer, we need Var(w) = 1/nin. Balancing the forward pass (fan-in) and backward pass (fan-out) gives Xavier/Glorot: Var(w) = 2/(nin + nout), suited to tanh or linear activations. ReLU zeroes half its inputs, halving the second moment, so He/Kaiming uses Var(w) = 2/nin. Without this scaling, activations and gradients grow or shrink geometrically with depth. Transformers often use small normal initialization (for example std 0.02) plus scaled residual branches.

Explain BatchNorm vs. LayerNorm vs. RMSNorm mathematically and when to use each.

All compute x̂ = (x − μ)/√(σ2 + ε) then y = γx̂ + β; they differ in which axis the statistics use. BatchNorm averages over the batch (and spatial dimensions) per channel; it needs reasonably large batches, uses running averages at inference, and adds regularizing noise; standard for CNNs. LayerNorm averages over the features of each individual example, so it works at any batch size and for variable-length sequences; standard for transformers. RMSNorm skips the mean subtraction and divides by √(mean(x2) + ε); cheaper and about equally effective, used in most modern LLMs. GroupNorm normalizes groups of channels per example, useful for small-batch vision.

What is the reparameterization trick?

In a VAE, the encoder outputs μ and σ and we need a sample z ~ N(μ, σ2). Sampling is not differentiable with respect to μ and σ. The trick rewrites the sample as z = μ + σ ⊙ ε with ε ~ N(0, I) drawn independently of the parameters. Now z is a deterministic, differentiable function of μ and σ, and the randomness is an external input, so gradients flow through the sampling step. The VAE loss is reconstruction error plus KL(N(μ, σ2) || N(0, I)) = ½Σ(μ2 + σ2 − log σ2 − 1), which has a closed form.

What is Jensen's inequality and where does it show up in ML?

For a convex function g, g(E[X]) ≤ E[g(X)]; for concave g (such as log) the inequality reverses: log E[X] ≥ E[log X]. Applications: the evidence lower bound in variational inference, log p(x) = log Eq[p(x, z)/q(z)] ≥ Eq[log p(x, z) − log q(z)]; proving KL divergence is non-negative; the EM algorithm's lower bound; understanding why the average of log-probabilities (what we optimize) differs from the log of an average probability; and why the geometric mean is at most the arithmetic mean (relevant to BLEU and to averaging perplexities).

How does the Beta-Binomial model work and how is it used for A/B testing or bandits?

A Beta(α, β) prior on a conversion rate p combined with k successes in n trials gives a Beta(α + k, β + n − k) posterior, because the Beta and binomial likelihood have the same functional form (conjugacy); α and β behave like prior pseudo-counts. The posterior mean is (α + k)/(α + β + n). In Bayesian A/B testing you compute P(pB > pA) by sampling from both posteriors, and report expected lift with credible intervals. In Thompson sampling for multi-armed bandits, each round you draw one sample from each arm's posterior and play the arm with the highest draw, which naturally balances exploration and exploitation.

What is mutual information and how does it differ from correlation?

I(X; Y) = Σp(x, y) log[p(x, y)/(p(x)p(y))] = H(Y) − H(Y | X) = KL(p(x, y) || p(x)p(y)). It measures how much knowing one variable reduces uncertainty about the other, in bits or nats. It is zero if and only if X and Y are independent, so it captures any dependence, linear or not, whereas Pearson correlation only captures linear association (X and X2 have zero correlation but high mutual information). It works for categorical variables too. Drawbacks: it is harder to estimate for continuous variables and has no sign. Uses: feature selection, decision-tree information gain, and contrastive learning objectives (InfoNCE is a lower bound on MI).

What is the curse of dimensionality, mathematically?

As dimension d grows, several things happen. Volume concentrates near the surface of a hypercube or ball, so data is sparse and neighborhoods of fixed radius are nearly empty; covering the space with a grid of spacing 0.1 needs 10d cells. For random points, the ratio (max distance − min distance)/min distance tends to 0, so nearest-neighbor distinctions vanish. The number of samples needed to estimate a density or fit a non-parametric model grows exponentially. Consequences: k-NN and kernel methods degrade, clustering with Euclidean distance becomes unreliable, and overfitting is easier. Remedies include dimensionality reduction, feature selection, regularization, and learning embeddings where data lies on a low-dimensional manifold.

What is the bias-variance decomposition of expected squared error?

For y = f(x) + ε with noise variance σ2 and a model f̂ trained on random datasets, E[(y − f̂(x))2] = (E[f̂(x)] − f(x))2 + Var(f̂(x)) + σ2 = bias2 + variance + irreducible noise. The derivation adds and subtracts E[f̂(x)] and uses independence of the noise, so cross terms vanish. Simple models have high bias and low variance (underfit); flexible models have low bias and high variance (overfit). Regularization, more data, bagging and ensembling reduce variance; richer features and larger models reduce bias. Modern over-parameterized networks can show "double descent", where test error drops again beyond the interpolation threshold.

How would you implement a numerically stable binary cross-entropy from logits?

Naively, loss = −[y log σ(z) + (1 − y) log(1 − σ(z))] overflows or produces log(0) for large |z|. Using log σ(z) = −log(1 + e−z) and log(1 − σ(z)) = −z − log(1 + e−z), the loss simplifies to log(1 + ez) − yz. Compute log(1 + ez) stably as max(z, 0) + log1p(e−|z|). So loss = max(z, 0) − zy + log1p(exp(−|z|)). This is what BCEWithLogitsLoss and TensorFlow's sigmoid_cross_entropy_with_logits implement; the gradient is simply σ(z) − y.

Why do LLMs train in BF16 rather than FP16, and what is loss scaling?

FP16 has 5 exponent bits: its maximum is 65,504 and its smallest normal value is about 6 × 10−5. Activations or logits can overflow, and many small gradients underflow to zero. Loss scaling multiplies the loss by a large factor S before backprop, shifting gradients into the representable range, then divides by S before the update; dynamic scalers reduce S when inf/NaN appears and skip that step. BF16 keeps FP32's 8 exponent bits (same range) with only 7 mantissa bits, so overflow and underflow are rare and loss scaling is usually unnecessary; the lower precision is tolerable because SGD is noisy anyway. Master weights and optimizer states are typically kept in FP32 for accurate accumulation.

How does LoRA use low-rank matrix factorization, and how many parameters does it save?

LoRA freezes a pretrained weight W (d×k) and learns an update ΔW = BA with B (d×r) and A (r×k), r « min(d, k), so the forward pass computes Wx + (α/r)BAx. The hypothesis is that fine-tuning updates have low intrinsic rank. For d = k = 4096 and r = 8, trainable parameters drop from 16.8 million to 2 × 4096 × 8 = 65,536 per matrix, about 256× fewer. B is initialized to zero so training starts from the original model. After training, BA can be merged into W, adding no inference cost. QLoRA additionally quantizes the frozen W to 4 bits to cut memory further.

What is the softmax Jacobian and why does saturation kill gradients?

For p = softmax(z), ∂pi/∂zj = pi(δij − pj), i.e. J = diag(p) − ppT. If one probability approaches 1 and the rest approach 0 (a saturated, near one-hot output), every entry of J approaches 0: pi(1 − pi) → 0 on the diagonal and pipj → 0 off it. Any gradient passing through that softmax is then multiplied by a near-zero matrix. This is why unscaled attention logits, very low temperatures during training, or huge logits cause vanishing gradients, and why cross-entropy is fused with softmax: the combined gradient p − y does not vanish when the prediction is confidently wrong.

How is the KV cache size computed, and how does grouped-query attention reduce it?

During generation, each layer stores a key and a value vector for every past token and every KV head: bytes = 2 × layers × KV heads × dhead × sequence length × batch × bytes per value. For 32 layers, 32 heads of 128 dimensions in FP16: 2 × 32 × 32 × 128 × 2 bytes ≈ 0.5 MB per token, about 2 GB for a 4,096-token context per sequence. Grouped-query attention shares each K/V head across a group of query heads (for example 8 KV heads for 32 query heads), cutting the cache 4×; multi-query attention uses a single KV head. Quantizing the cache to INT8 or INT4 and paging it in blocks reduce memory further.

Scenario & debugging

Your training loss suddenly becomes NaN after a few hundred steps. How do you debug it?
  1. Check the data: NaN/inf in inputs or labels, division by zero in feature engineering, labels out of range for the loss.
  2. Log the gradient norm and loss per step: a spike before the NaN points to exploding gradients. Add gradient clipping (norm 1.0) and lower the learning rate or add warmup.
  3. Look for unstable operations: hand-written log(softmax), log(sigmoid), log(0), sqrt of negative numbers, division by a near-zero variance. Use fused logit-based losses and add ε.
  4. With FP16 mixed precision, check for overflow; use dynamic loss scaling or switch to BF16.
  5. Use anomaly detection (torch.autograd.set_detect_anomaly(True)) to find the first operation producing NaN.
  6. Reproduce on a single batch with a fixed seed to isolate the culprit.
A fraud model has 99.5% accuracy but catches almost no fraud. What is going on, and what would you compute instead?

If fraud is 0.5% of transactions, predicting "not fraud" for everything gives 99.5% accuracy, so accuracy is meaningless here. Compute the confusion matrix, precision, recall, F1 and the precision-recall curve with its area (average precision), which is much more informative than ROC-AUC under heavy imbalance. Choose the decision threshold from the business cost of false negatives vs. false positives rather than using 0.5. Remedies: class-weighted or focal loss, resampling (with sampling only on training data), anomaly-detection features and more positive examples. Remember the Bayes lesson: even a good detector at a low base rate yields many false alarms, so expect modest precision.

Your A/B test shows a 3% lift with p = 0.04 after the team checked results every day and stopped when it turned significant. Do you ship?

Not on this evidence. Checking repeatedly and stopping at the first p < 0.05 ("peeking") inflates the false-positive rate well above 5%, often to 20-30% over many looks, because random fluctuations eventually cross the threshold. Also check whether other metrics or segments were tested (multiple comparisons), whether the test ran full weekly cycles, the sample ratio (was the split really 50/50?), and whether the lift's confidence interval is practically meaningful. Recommend re-running with a pre-computed sample size and fixed duration, or using a sequential testing method designed for continuous monitoring, and then deciding based on the effect size and its interval.

Model B beats model A by 0.4% accuracy on a 5,000-example test set. Is B better?

Probably not demonstrably. At about 90% accuracy, the standard error of one model's accuracy is √(0.9 × 0.1/5000) ≈ 0.42%, so a 0.4% gap is within noise for independent estimates. Because both models were evaluated on the same examples, use a paired test: McNemar's test on the disagreement counts (examples one model gets right and the other wrong) or a paired bootstrap of the accuracy difference. Also check variance across random seeds (retrain each model with 3-5 seeds) and whether the test set was used for model selection, which biases it. Report the difference with a confidence interval.

Your gradient-descent training loss oscillates wildly and never settles. What would you check?
  • Learning rate too high relative to the sharpest curvature (η > 2/λmax): reduce it by 3-10×, add warmup, or run an LR range test.
  • Unscaled features: one large-scale feature creates an ill-conditioned problem that zig-zags; standardize inputs.
  • Batch size too small: gradient noise dominates; increase batch size or use momentum.
  • Data order: unshuffled data sorted by class makes consecutive batches disagree; shuffle.
  • Exploding gradients in deep or recurrent nets: clip gradients, add normalization or residuals.
  • Bugs: labels misaligned with inputs, a loss computed on the wrong shape (broadcasting), or train-mode layers behaving unexpectedly.
Early layers of your deep network barely change during training while the last layers learn. What is happening and how do you fix it?

This is the vanishing gradient problem: backprop multiplies one local derivative per layer, and with saturating activations (sigmoid's derivative is at most 0.25) or poorly scaled weights, the product shrinks exponentially with depth; 0.2510 ≈ 10−6. Confirm by logging per-layer gradient norms. Fixes: replace sigmoid/tanh in hidden layers with ReLU/GELU; use He or Xavier initialization; add residual connections so gradients have an identity path; add BatchNorm or LayerNorm; for sequences, use LSTM/GRU or attention instead of vanilla RNNs. Also check for dead ReLUs.

A regression model trained with MSE is dominated by a few extreme targets. What would you change?

MSE squares errors, so a handful of large residuals dominates the gradient; it also implicitly assumes Gaussian noise, which heavy-tailed targets violate. Options: first check whether the extremes are data errors and fix them. Switch to a robust loss: MAE (predicts the median, gradient bounded), Huber (quadratic near zero, linear in the tails) or log-cosh. Transform the target, e.g. predict log(1 + y) for right-skewed positive targets like prices and revert with exp(·) − 1 (beware this predicts a median-like quantity, not the mean). If you need ranges rather than point estimates, use quantile loss. Evaluate with metrics matching the business need, such as MAE or MAPE.

You standardized features using the mean and standard deviation of the whole dataset before splitting. Why is that a problem?

It is data leakage: the scaler has seen the validation and test distribution, so information about those sets influences training, and evaluation scores become optimistically biased. The effect can be small for large i.i.d. data but severe for time series (future statistics leak into the past) or small datasets. The correct procedure is to split first, fit the scaler (and any imputer, PCA, target encoder or feature selector) on the training data only, then apply the fitted transformation to validation and test data. In cross-validation, put the preprocessing inside a pipeline so it is refit on each fold.

Your k-NN classifier performs poorly on a dataset with 500 features. What could be wrong?
  • Unscaled features: large-range features dominate the distance; standardize.
  • Curse of dimensionality: in 500 dimensions distances concentrate, so the "nearest" neighbors are barely nearer than random points. Reduce dimensionality (PCA, feature selection) or use learned embeddings.
  • Irrelevant or noisy features contribute to distance equally with informative ones; select features or learn a metric.
  • Wrong metric: for sparse or text-like data, cosine similarity often beats Euclidean.
  • k poorly tuned or class imbalance: tune k with cross-validation and consider distance weighting.
You notice two features have a correlation of 0.98 in a linear regression. What happens and what do you do?

Multicollinearity: XTX becomes nearly singular (a very small eigenvalue), so coefficient estimates have huge variance, can flip sign between samples, and are uninterpretable, even though predictions may remain fine. Diagnose with variance inflation factors (VIF > 5-10 is concerning) or the condition number of X. Remedies: drop one of the pair, combine them (average, or a domain ratio), use PCA, or use ridge regression, which adds λI to XTX to stabilize the inverse. Lasso tends to pick one of the correlated features arbitrarily; elastic net keeps groups together.

An LLM-based extraction service returns different JSON for the same input on each call. How do the sampling parameters explain this and what would you set?

With temperature > 0 (or top-p/top-k sampling), the next token is drawn randomly from the softmax distribution, so any token that is not overwhelmingly likely can vary between runs, and one different token changes everything after it. For deterministic extraction, set temperature to 0 (greedy decoding) or very low, and optionally a restrictive top-p; use structured-output or constrained decoding to guarantee valid JSON. Note that even at temperature 0, tiny numerical differences from batching or hardware can occasionally flip near-tied tokens, so also validate outputs against a schema and retry on failure. Keep higher temperatures for creative tasks where diversity is wanted.

An interviewer gives you logits [3.0, 1.0, 0.2] and asks for the softmax probabilities and the cross-entropy if the true class is the second one.

Subtract the max: [0, −2.0, −2.8]. Exponentiate: [1, 0.1353, 0.0608], sum 1.1961. Probabilities: [0.836, 0.113, 0.051]. The cross-entropy for true class 2 is −ln 0.113 ≈ 2.18. The gradient with respect to the logits is p − y = [0.836, 0.113 − 1, 0.051] = [0.836, −0.887, 0.051]: push the first logit down and the second up. With temperature 2, the logits become [1.5, 0.5, 0.1] and the probabilities flatten to roughly [0.62, 0.23, 0.15].

You are asked to decide whether a new recommendation model improved click-through rate from 4.0% to 4.2%. How would you design the experiment?
  1. Hypotheses: H0: CTRB = CTRA; H1: CTRB ≠ CTRA (two-sided, α = 0.05, power 0.8).
  2. Randomize by user (not by impression) to avoid correlated observations; use the same unit for analysis, or cluster-robust errors.
  3. Sample size for 4.0% → 4.2%: n ≈ 7.84 × (0.04 × 0.96 + 0.042 × 0.958)/0.0022 ≈ 154,000 users per arm.
  4. Run for full weeks; define guardrail metrics (latency, diversity, revenue, complaints).
  5. Analyze with a two-proportion z-test or chi-square, report the lift with a confidence interval, check sample-ratio mismatch and novelty effects, and avoid peeking.
After applying PCA before a classifier, accuracy dropped noticeably. Why might that happen?

PCA is unsupervised: it keeps directions of maximum variance, not directions that separate the classes. A low-variance direction can carry most of the discriminative signal (for example a subtle feature that differs between classes), and discarding it removes that signal. Other causes: features were not standardized, so a large-unit feature dominated the components; too few components were kept; the relationship is non-linear; or PCA was fit on data including the test set. Try more components, standardize first, compare against supervised methods (LDA, feature selection by importance), or skip PCA if the model handles the dimensionality fine.

Your model outputs "90% confident" but is right only 70% of the time on those predictions. What is this and how do you fix it?

The model is miscalibrated (overconfident): its predicted probabilities do not match observed frequencies. Measure with a reliability diagram and expected calibration error (bin predictions by confidence, compare mean confidence with accuracy per bin). Modern deep networks trained long with cross-entropy are often overconfident. Fixes: temperature scaling (learn a single T > 1 on a validation set and divide logits by it; it does not change accuracy because the argmax is unchanged), Platt scaling or isotonic regression, label smoothing during training, and ensembles. Calibration matters whenever probabilities drive decisions: thresholds, risk scores, abstention, or combining model outputs.

Two metrics are strongly correlated in your product dashboard. A stakeholder wants to push one to raise the other. What do you say?

Correlation does not imply causation. The relationship could be driven by a confounder (for example, engaged users both read more and buy more), by reverse causation, or by selection effects; forcing one metric up (such as adding autoplay to raise watch time) may not move the other, and can hurt it. Check for confounders, look at the relationship within segments (Simpson's paradox can reverse trends), and ideally run a randomized experiment that manipulates the proposed lever. If experiments are impossible, use causal-inference methods (difference-in-differences, instrumental variables, matching) with clearly stated assumptions.

Your embedding-based search returns long documents for almost every query. What might cause this, mathematically?

If you rank by raw dot product rather than cosine similarity, vectors with larger norms score higher regardless of direction, and embeddings (or TF-IDF sums) of long documents often have larger norms. Normalize vectors to unit length so dot product equals cosine similarity, or use a cosine index. Also check chunking: very long chunks average many topics into a generic vector that is moderately similar to everything; smaller, coherent chunks usually retrieve better. Mixing embeddings from different models or query/document encoders used inconsistently can cause similar symptoms. Evaluate with recall@k on labeled query-document pairs after each change.

Validation loss rises while training loss keeps falling. How do you interpret and respond?

The model is overfitting: it keeps reducing error on training data by fitting noise, while its performance on unseen data worsens (high variance). Responses: early stopping at the validation minimum; stronger regularization (weight decay, dropout, label smoothing); data augmentation or more data; a smaller model; lower learning rate late in training. Also rule out leakage or distribution shift between train and validation, and check whether validation accuracy is actually falling; sometimes the loss rises because predictions become overconfident while accuracy is stable, which calibration can address.

You must estimate average latency, but the distribution has a long tail with occasional 30-second timeouts. Which statistics would you report?

The mean is dominated by the rare timeouts and describes neither typical nor worst-case experience. Report the median (p50) for typical latency, plus high percentiles (p95, p99, p99.9) for tail behavior, and the timeout rate as a separate metric. Visualize with a histogram on a log scale or a CDF. For comparing two versions, use a test suited to skewed data (Mann-Whitney U, or bootstrap confidence intervals on the median or p99) rather than a t-test on raw means. Percentile metrics should be computed over raw requests, not averaged across servers, since averaging percentiles is mathematically invalid.

A colleague's attention implementation trains poorly; you see softmax weights that are almost perfectly one-hot from the first step. What would you check?
  • Missing 1/√dk scaling: scores have standard deviation √dk, saturating softmax and killing gradients.
  • Initialization too large for WQ/WK, or unnormalized inputs (missing LayerNorm before attention), inflating dot products.
  • Softmax over the wrong axis (should be over keys, the last axis of the T×T scores).
  • Masking bugs: adding a large negative value to the wrong positions, or masking everything except one token.
  • An accidental temperature or scaling factor, or FP16 overflow in the scores.

Log the entropy of attention rows and the score standard deviation per layer to confirm the fix.

Your team trained a binary classifier with softmax over two outputs and another with a single sigmoid. Are they different?

Mathematically they are equivalent. With two logits z1, z0, softmax gives p(1) = ez1/(ez1 + ez0) = σ(z1 − z0), so a two-way softmax is a sigmoid of the logit difference, and the two cross-entropy losses coincide. The two-output version has redundant parameters (only the difference matters) but trains the same. Differences arise in multi-label settings, where independent sigmoids are required, and in implementation details such as which loss function expects logits vs. probabilities.

You need to compare the average order value between two regions with small samples (n = 12 each) and visible skew. Which test?

With small samples and skewed data, the normal approximation behind a t-test is questionable, and outliers can dominate the means. Options: a non-parametric Mann-Whitney U test, which compares rank distributions (it tests whether one group tends to have larger values, not strictly the means); a permutation test on the difference in means, which makes no distributional assumption; or a bootstrap confidence interval for the difference. If you do use a t-test, use Welch's version (unequal variances) and consider a log transform first. Report the effect size and interval, and note the limited power with 12 per group.

Adding one more hidden layer made your MLP train much worse even though it has more capacity. Why could that be?

Deeper networks are harder to optimize, not just more expressive. Possible causes: vanishing or exploding gradients from poor initialization or saturating activations; the learning rate that suited the shallower model is now too high or too low; no normalization or residual connections, so signal variance drifts with depth; dead ReLUs; or overfitting if validation (not training) performance dropped. If training loss itself got worse, it is an optimization problem: use He initialization, add BatchNorm/LayerNorm or a skip connection, re-tune the learning rate and check per-layer gradient norms. A deeper network with residuals should be able to at least match the shallower one by learning near-identity mappings.

A monitoring dashboard shows a feature's mean unchanged but model performance dropping. How can you detect a distribution shift the mean misses?

The mean is only one summary; the variance, skew, tails, multimodality or the relationship with other features can change while the mean stays put. Compare full distributions between the training window and production: the Kolmogorov-Smirnov test or Wasserstein distance for continuous features, chi-square tests or the population stability index for binned or categorical features, KL or Jensen-Shannon divergence between histograms, and quantile tracking (p1, p50, p99). Check the missing-value rate and category frequencies. Also monitor the model's output distribution and, where labels arrive, the conditional relationship P(y | x) (concept drift), which can change even if P(x) does not.

You fine-tune with Adam and a large L2 penalty in the loss, but large weights barely shrink. Why?

With plain Adam, the L2 term's gradient λw is added to the data gradient and the sum is divided by √v̂, the running root-mean-square of gradients. Parameters that receive large or frequent gradients have large v̂, so their effective regularization λw/√v̂ becomes tiny, precisely for the weights you most wanted to shrink. Switch to AdamW, which applies decay directly as w ← w − ηλw independent of the adaptive scaling, and tune λ (typical values are 0.01-0.1 for transformers), usually excluding biases and normalization parameters from decay.