← Dimitris Gkoumas

AI Under the Hood

Study notes on statistics and ML foundations, why models fail to generalise, how they are optimised, how generative models and transformers work, how training scales across GPUs, how it all comes together in LLMs, how to deploy them, and how agents use tools.

Part I

Statistics foundations

Describing data, probability, sampling and drawing conclusions from samples: the toolkit the rest of the notes rely on.

01Data and measurement

Statistics is the science of collecting, organising, analysing and interpreting data. Descriptive statistics summarise the data you have; inferential statistics use a sample to draw conclusions about a larger population.

PopulationSample
WhatEvery member of the group you care aboutA subset you actually observe
SizeNn
Summaries are calledParameters: μ, σ², pStatistics (estimates): x̄, s², p̂
ML exampleAll future users of a modelYour training and test sets

Types of data

TypeSubtypeValuesExamples
Qualitative (categorical)NominalLabels, no orderGender, blood group, colour, city
OrdinalLabels with a rankCustomer rating 1–5, education level
Quantitative (numerical)DiscreteCountable whole numbersChildren in a family, number of sales
ContinuousAny value in a rangeHeight, house price, river length

Scales of measurement

The scale decides which statistics, tests and encodings are valid.

ScaleOrderDifferencesTrue zero (ratios)ExampleValid centreML encoding
Nominal✗✗✗Colour, cityModeOne-hot, embeddings
Ordinal✓✗✗Ranking, agree/disagreeMedian, modeInteger codes in order
Interval✓✓✗Temperature in °C, calendar yearMean, median, modeNumeric, scaled
Ratio✓✓✓Height, income, exam marksAll, plus ratiosNumeric, often log-scaled
  • Interval vs ratio: 20 °C isn't “twice as hot” as 10 °C, because 0 °C is arbitrary; 20 kg is twice 10 kg.
  • Likert scales (totally agree … totally disagree) are ordinal. They are often averaged as if interval, which assumes equal gaps between answers.

02Descriptive statistics

Central tendency

\begin{aligned}\mu &= \frac{1}{N}\sum_{i=1}^{N} x_i &&\text{population mean} \qquad \bar x = \frac{1}{n}\sum_{i=1}^{n} x_i \;\;\text{sample mean}\\ \text{median} &= \text{middle value of the sorted data (average of the two middle values if } n \text{ is even)}\\ \text{mode} &= \text{most frequent value (there can be several, or none)}\end{aligned}
The mean uses every value, so a single outlier moves it; the median and mode are robust. Use the median for skewed data such as income, and the mode for nominal data.

Dispersion

\begin{aligned}\sigma^2 &= \frac{1}{N}\sum_{i=1}^{N}(x_i-\mu)^2 && s^2 = \frac{1}{n-1}\sum_{i=1}^{n}(x_i-\bar x)^2\\ \sigma &= \sqrt{\sigma^2}, \quad s=\sqrt{s^2} && \text{IQR} = Q_3 - Q_1, \quad \text{range} = \max - \min\end{aligned}
Dividing by n − 1 (Bessel's correction) makes s² an unbiased estimator of σ²: the sample mean sits closer to the sample points than the true mean does, so dividing by n would underestimate the spread. The more spread out the data, the larger the variance.

z-scores and skewness

z = \frac{x-\bar x}{s} \qquad\qquad \text{skewness} = \frac{1}{n}\sum_{i=1}^{n}\Big(\frac{x_i-\bar x}{s}\Big)^3
A z-score says how many standard deviations a value lies from the mean; it is the same formula as standardisation in feature engineering. Skewness > 0: long right tail (mean > median); < 0: long left tail. Kurtosis (fourth power) measures how heavy the tails are.

Worked example

Heights of seven cricketers from one camp: 175, 180, 140, 140, 135, 160, 135 cm.

StatisticValueHow
Mean152.1 cm1065 / 7
Median140 cmSorted: 135, 135, 140, 140, 160, 175, 180
Mode135 and 140 cmEach appears twice: the data is bimodal
Sample variance s²373.8 cm²2242.9 / (7 − 1)
Standard deviation s19.3 cm√373.8
IQR40 cmQ₃ − Q₁ = 175 − 135 (medians of each half)
z-score of 140 cm−0.63(140 − 152.1) / 19.3
Figure 1. The worked example. The mean sits right of the median because the two tall values pull it up: the data is right-skewed. All values are computed from the data.

03Probability and distributions

Probability basics

The sample space Ω is the set of all outcomes (rolling a die: {1, …, 6}); an event is a subset of it. Probabilities lie in [0, 1] and sum to 1 over Ω.

\begin{aligned} &P(A\cup B) = P(A)+P(B)-P(A\cap B) && \text{addition rule}\\ &P(A\mid B) = \frac{P(A\cap B)}{P(B)} && \text{conditional probability}\\ &P(A\cap B) = P(A)\,P(B) && \text{if } A, B \text{ are independent}\\ &P(A\mid B) = \frac{P(B\mid A)\,P(A)}{P(B)} && \text{Bayes' rule}\end{aligned}
Set operations from the notes: with A = {1, …, 8} and B = {3, …, 7}, A ∩ B = {3, …, 7}, A ∪ B = {1, …, 8}, A − B = {1, 2, 8}, and B ⊂ A. Bayes' rule reappears in generative vs discriminative models.

Random variables and distributions

DiscreteContinuous
ValuesCountable outcomesAny value in a range
Described byPMF: P(X = x)PDF: f(x), a density; P(X = x) = 0 for any single x
Probability of an intervalSum the PMFIntegrate the PDF (area under the curve)
BothCDF: F(x) = P(X ≤ x), rising from 0 to 1
\mathbb E[X] = \sum_x x\,P(X=x) \;\;\text{or}\;\; \int x\,f(x)\,dx \qquad \mathrm{Var}(X) = \mathbb E\big[(X-\mathbb E[X])^2\big]

Common distributions

Figure 2. Common distributions. For skewed data the mean is pulled towards the long tail: positive (right) skew gives mean > median, negative (left) skew gives mean < median. Bottom row: Poisson counts, exponential waiting times (mean 1, median ln 2 ≈ 0.69), and a power law whose long tail decays slowly, so rare extreme values still occur.
DistributionTypeTypical data
UniformContinuous or discreteEvery value equally likely: random IDs, dice
BernoulliDiscrete, 0 or 1One yes/no outcome, a binary label
BinomialDiscrete countsSuccesses in n Bernoulli trials
NormalContinuous, symmetricMeasurement noise, heights
Log-normalContinuous, right-skewedIncome, prices, durations
PoissonDiscrete countsEvents per time window
ExponentialContinuousWaiting times
Power law / long tailHeavy-tailedWord frequencies, popularity
DistributionPMF / PDFMeanVariance
Bernoulli(p)P(1) = p, P(0) = 1 − ppp(1 − p)
Binomial(n, p)C(n, k) pᵏ (1 − p)ⁿ⁻ᵏnpnp(1 − p)
Poisson(λ)λᵏ e⁻λ / k!λλ
Uniform(a, b)1 / (b − a) on [a, b](a + b) / 2(b − a)² / 12
Normal(μ, σ²)exp(−(x − μ)² / 2σ²) / (σ√(2π))μσ²
Exponential(λ)λ e⁻λˣ, x ≥ 01/λ1/λ²

The normal distribution and the empirical rule

Symmetric, bell-shaped and unimodal, with mean = median = mode. Blood pressure, heights and measurement errors are roughly normal, and averages of many values tend towards it (the central limit theorem).

Figure 3. The empirical (68–95–99.7) rule, with percentages computed from the normal CDF.

Checking whether data is normal

  • Plots: a histogram, and a Q-Q plot of sorted data against normal quantiles: points on a straight line mean normal.
  • Tests: Shapiro–Wilk, D'Agostino–Pearson, Kolmogorov–Smirnov. With large n they flag tiny, harmless departures, so look at the plot too.
  • If skewed: try a log or Box-Cox transform, or use tests that don't assume normality.
Figure 4. Q-Q plots for 120 simulated values. Normal data follows the line; right-skewed (log-normal) data bends upwards because its large values are too large.

Right-skewed and log-normal features are good candidates for a log transform before training (see feature engineering).

04Sampling and correlation

Sampling techniques

TechniqueHowExample
Probability sampling: every member has a known chance of selection, so results generalise
Simple randomEveryone equally likelyDraw 100 customer IDs at random
StratifiedSplit into groups (strata), sample each in proportionKeep class balance in train/test splits
SystematicEvery k-th member of a listEvery 10th employee in an alphabetical list
ClusterRandomly pick whole groupsSurvey all students in 5 random schools
Non-probability sampling: cheaper, but prone to bias
ConvenienceWhoever is easiest to reachAsking students in your own lectures
PurposiveChosen for a specific traitInterviewing students with disabilities about support services
SnowballParticipants recruit othersHard-to-reach communities

Sampling bias is why a model trained on convenient data can fail on real users: the sample doesn't represent the population (see data curation).

Covariance and correlation

\mathrm{cov}(X,Y) = \frac{1}{n-1}\sum_{i=1}^{n}(x_i-\bar x)(y_i-\bar y) \qquad r = \frac{\mathrm{cov}(X,Y)}{s_X\,s_Y}\in[-1,1]
Covariance gives the direction of a relationship but depends on units. Pearson's r rescales it to [−1, 1]: +1 perfect positive, 0 no linear relationship, −1 perfect negative. Spearman's ρ applies the same formula to ranks, capturing any monotonic relationship and resisting outliers.
Figure 5. Simulated data, r computed from each sample. The last panel has a strong relationship but r ≈ 0, because Pearson's r only measures straight-line association.
Common mistake

Correlation isn't causation. Ice-cream sales and drownings both rise in summer: a third variable (temperature) drives both. Plot the data before trusting r (Anscombe's quartet has four very different datasets with the same r).

05Inferential statistics

Estimates and the central limit theorem

A point estimate is a single value for an unknown parameter (x̄ for μ); an interval estimate gives a range of plausible values. Intervals rely on the central limit theorem (CLT): whatever the population's shape, the mean of a large enough sample is approximately normal.

\bar X \;\approx\; \mathcal N\!\Big(\mu,\; \frac{\sigma^2}{n}\Big) \qquad \text{standard error: } \mathrm{SE} = \frac{\sigma}{\sqrt n}\;\;\big(\text{estimated by } s/\sqrt n\big)
Figure 6. The CLT in action: 3,000 simulated sample means from a skewed exponential population, with the normal curve the CLT predicts overlaid. Skew fades and the spread shrinks as σ/√n.

Confidence intervals

\bar x \pm z_{\alpha/2}\,\frac{\sigma}{\sqrt n} \;\;(\sigma\text{ known}) \qquad\qquad \bar x \pm t_{\alpha/2,\,n-1}\,\frac{s}{\sqrt n} \;\;(\sigma\text{ unknown})
For 95%, z = 1.96. A 95% CI means that if you repeated the sampling many times, 95% of the intervals would contain the true value; not that this interval has a 95% chance of containing it.
  • Model metrics need intervals too: report “accuracy 0.84 (95% CI 0.82–0.86)”. For metrics without a formula, use the bootstrap: resample the test set, recompute the metric, and take the 2.5th and 97.5th percentiles.

Hypothesis testing

  1. State the null hypothesis H₀ (no effect: “the new model is no better”) and the alternative H₁.
  2. Choose a significance level α, usually 0.05.
  3. Compute a test statistic from the sample.
  4. Find the p-value: the probability of a result at least this extreme if H₀ were true.
  5. If p < α, reject H₀; otherwise you fail to reject it (which is not proof that H₀ is true).
Figure 7. A two-tailed z-test at α = 0.05. The observed z = 2.3 falls in the rejection region; its p-value (both tails beyond ±2.3) is computed from the normal CDF.
H₀ trueH₀ false
Reject H₀Type I error (false positive), probability αCorrect: power = 1 − β
Fail to rejectCorrectType II error (false negative), probability β
What a p-value is not

It isn't the probability that H₀ is true, and it isn't the size or importance of an effect. A tiny, useless improvement becomes “significant” with enough data, so always report an effect size and a confidence interval.

Choosing a test

z = \frac{\bar x-\mu_0}{\sigma/\sqrt n} \qquad t = \frac{\bar x-\mu_0}{s/\sqrt n}\;\;(df=n-1) \qquad \chi^2 = \sum\frac{(O-E)^2}{E} \qquad F = \frac{\text{variance between groups}}{\text{variance within groups}}
TestQuestionUse when
z-testDoes a mean (or proportion) differ from a value, or between two groups?σ known, or n large (≳ 30)
t-testSame, for meansσ unknown or n small. One-sample, two-sample (independent groups) or paired (same subjects twice)
Chi-squareDo observed counts match expected ones? Are two categorical variables independent?Categorical data, counts in a table
ANOVADo means differ across 3+ groups?One-way (one factor, independent groups); repeated measures (same subjects); two-way (two factors). Uses the F statistic
Figure 8. Choosing a classic test. If data is clearly non-normal and samples are small, use non-parametric alternatives: Mann–Whitney U, Wilcoxon signed-rank, Kruskal–Wallis.

Statistics for ML experiments

  • Multiple comparisons: test 20 prompts at α = 0.05 and one will look “significant” by chance. Correct with Bonferroni (α / m) or control the false-discovery rate (Benjamini–Hochberg).
  • Practical vs statistical significance: decide in advance what improvement matters (the tolerance in a quality gate), then check the CI clears it.
  • A/B tests in production (testing in production) are hypothesis tests: fix the sample size from a power calculation before starting, and don't stop early when the p-value first dips below 0.05.
  • Comparing two models on the same test set is a paired comparison: use McNemar's test or a paired bootstrap, not two independent intervals.
Part II

ML foundations

Data, features, likelihood, and how to measure a model.

06Exploratory data analysis (EDA)

Figure 9. A typical EDA flow. Cleaning comes before transforming, so scalers aren't fitted on duplicates or bad values.

Outliers

  • Skew the mean (the median and mode are robust) and the standard deviation.
  • Affect normalisation, especially min-max scaling, where one extreme value squashes all the others.
  • A single outlier can dominate a squared loss such as MSE or RMSE, which hurts generalisation.
  • Detect: IQR rule (outside [Q1 − 1.5·IQR, Q3 + 1.5·IQR]) or |z-score| > 3.
  • Check before removing: an outlier may be real and important (fraud, failures). Alternatives are clipping, a log transform or a robust loss (Huber).

High cardinality

Categorical features with many values (user IDs, zip codes):

  • One-hot encoding explodes the number of dimensions, making training expensive.
  • Poor generalisation: the model can memorise individual IDs.
  • Fixes: group rare categories into “other”, target or hash encoding, learned embeddings.
Also check

Class imbalance (see section 8; it changes which metric to use) and target leakage: features that wouldn't be available at prediction time, such as a “refund issued” flag when predicting fraud.

07Data curation and quality

Better data often helps more than a better model. Curation decides what goes into the training set and how trustworthy its labels are.

The data pipeline

  • Collection: human annotation, automatic labelling, synthetic data.
  • Cleaning: remove noise, duplicates and broken examples.
  • Transformation and preprocessing: categorical encoding, bins, tokenisation, normalisation (see feature engineering).
  • Quality vs quantity: for fine-tuning LLMs, quality usually wins. The LIMA paper fine-tuned on about 1,000 carefully chosen examples with strong results.
  • Privacy, bias, licensing and consent.
  • Contamination: test or benchmark data leaking into training inflates evaluation scores. Deduplicate against your test sets.

Questions to ask your data

QuestionWhat to look for
Missing values? Duplicates? Outliers?See EDA and missing data
Is it up to date, representative, complete?Does the training data match what the model will see in use?
Is it biased?Under-represented groups, skewed sources
Is it sensitive?Personal data that needs anonymising
Can the labels be trusted?Inter-annotator agreement (e.g. Cohen's κ), label-error detection
Is there leakage?Features unavailable at prediction time; test data in training
May we use it?Licence and consent

Heuristic preprocessing

  • Pandas for analysis and fixes, from outlier removal to imputation.
  • Text filters: language ID, length limits, repetition, toxicity, and perplexity filters (text a reference model finds unusually surprising).
  • Deduplication: exact (hashing), near-duplicate (MinHash), semantic (embedding similarity).
  • Embeddings for label consistency: very similar examples with different labels are likely mislabelled.

Finding label errors with a human in the loop

Cleanlab is a data-centric AI package that flags mislabelled, outlying or ambiguous examples. It uses confident learning: out-of-sample predicted probabilities (from cross-validation) plus a confidence threshold per class estimate which given labels are probably wrong. The predictions must be out-of-sample: a model that trained on an example has memorised its label and can't flag it.

Figure 10. The data-improvement loop. The model finds suspect examples; people decide what to fix.

Argilla (now part of Hugging Face) is a collaborative annotation tool. You can send model or generative outputs to its interface for review, or pre-fill suggested corrections above a probability threshold. Apply the same quality rules to your test set, and never let training-time fixes peek at it.

Active learning

Labelling is expensive, so at each round the model tells you which examples to label next, usually the ones it is least sure about.

Figure 11. Uncertainty sampling: the unlabelled points nearest the current decision boundary are queried first.
StrategyPicks examples where…
Least confidencethe top predicted probability is lowest
Marginthe gap between the top two classes is smallest
Entropythe predicted distribution is most uncertain
Query-by-committeeseveral models disagree most
Diversity / core-setexamples cover the data well (avoids many near-duplicates)

ActiveLab (from Cleanlab) is useful when human labels are noisy. It weighs annotator agreement against model confidence to decide whether to re-label a suspect example or label a new one.

Synthetic data generation

A policy model generates several candidate outputs (proofs, code, text) per input; a reward model or verifier scores them on correctness or usefulness; the best are kept as training data, and the policy is fine-tuned on them. Repeat until performance plateaus. This is rejection sampling / best-of-n; variants include STaR, ReST and expert iteration.

Figure 12. Rejection-sampling loop for synthetic data.
  • ✗ Reward hacking: the policy learns to exploit flaws in the reward model; its scores rise while real quality doesn't.
  • ✗ Lower diversity and model collapse: repeatedly training on your own outputs narrows them (see data-centric fixes).
  • ✓ Prefer verifiable checks where possible (unit tests for code, proof checkers, exact answers): more reliable than a learned reward model.
  • Other methods: self-instruct (the model writes its own instructions and answers), distillation from a stronger model, paraphrasing and back-translation.

08Missing data, imbalance and resampling

Missing data

The right fix depends on why values are missing:

TypeMeaningImplication
MCAR (missing completely at random)Missingness is unrelated to anythingDropping rows is safe if there are few (or the dataset is big)
MAR (missing at random)Depends on other observed featuresModel-based imputation works well
MNAR (missing not at random)Depends on the missing value itself, e.g. high earners hiding incomeHard; the fact that it's missing is information
  • Simple imputation: mean or mode; the median for skewed data, since it is robust to outliers.
  • ML-based imputation: k-NN, iterative imputation (MICE), decision trees. Some models, such as XGBoost, handle missing values natively.
  • Add a “was missing” indicator feature: missingness itself can be predictive.
  • Fit the imputer on the training set only, the same rule as for scalers.

Imbalanced data

Figure 13. Left: resampling a 900 / 100 dataset. Right: SMOTE creates new minority points on the lines between real minority neighbours instead of copying them.
  • Oversample the minority class: random copies or SMOTE.
  • Undersample the majority class: fast, but throws data away.
  • Hybrid: both together.
  • Class weights or a weighted loss: give minority errors a larger penalty. Focal loss focuses training on hard examples.
  • Threshold tuning: move the decision threshold away from 0.5.
  • Evaluate with the right metric: F1, PR-AUC or recall, not accuracy.
Common mistakes

Resample after splitting, on training data only. Oversampling before the split puts copies of the same minority example in both train and test, which inflates scores.

Stratified sampling isn't an imbalance fix. It keeps class proportions the same across train, validation and test splits.

Resampling methods

  • Stratified splits: preserve class proportions in every split.
  • k-fold cross-validation: use the stratified version for imbalanced data.
  • Bootstrapping: draw n points with replacement from n. Used for confidence intervals on a metric and for bagging (random forests).
Figure 14. Three bootstrap samples of 10 points. Repeats are allowed; points never drawn are “out-of-bag” and can be used for validation. On average a sample contains 1 − 1/e ≈ 63.2% of the distinct points, leaving 36.8% out-of-bag.

09Feature engineering

Scaling numerical features

If feature X spans 154 to 24,917,482 and feature Y spans 5 to 22, X's gradients swamp Y's (see section 13). Normalisation helps models converge faster, make better predictions, avoid the “NaN trap” from overflowing values, and learn a sensible weight for each feature.

TechniqueFormulaWhen to use
Min-max (linear) scalingx′ = (x − x_min) / (x_max − x_min)Roughly uniform, bounded features; sensitive to outliers
Z-scorex′ = (x − μ) / σRoughly normal (bell-shaped) features
Log scalingx′ = log(x)Heavy right tail (power law, log-normal)
Clippingx′ = min(max(x, a), b)Extreme outliers
  • Fit the scaler on the training set only, then apply it to validation and test data. Fitting on all data leaks test information.
  • Tree-based models (random forests, XGBoost) don't need scaling: splits ignore scale.

Binning (bucketing)

Convert a numerical value into ranges. Useful when the relation between feature and label is non-linear or weak overall, or when values form clusters. Quantile binning puts the same number of points in each bin.

Categorical features

One-hot encoding for few categories, learned embeddings for many, and feature crosses (combinations such as city × hour) to capture interactions.

10Feature importance and dimensionality

  • Random-forest importance ranks features by how much they reduce impurity, but is biased towards continuous and high-cardinality features. Permutation importance (shuffle a feature, measure the drop in score) and SHAP values are more reliable.
  • Correlation analysis finds redundant features: if two are highly correlated, one may be enough.
  • PCA reduces dimensionality by building new features (principal components) from the eigenvectors of the covariance matrix. Especially useful with correlated features. It is not a feature-importance method, and components lose interpretability. Standardise first, or large-scale features dominate.
Figure 15. PCA on two correlated features, computed from the data's covariance matrix. Arrow lengths are proportional to the standard deviation along each component.

11From likelihood to loss to gradients

MLE defines the objective → the loss function encodes it → gradients tell us how to reach it.

Maximum likelihood estimation (MLE)

Given data points (x⁽ⁱ⁾, y⁽ⁱ⁾) drawn from a conditional distribution P(y | x; θ), choose the parameters θ (e.g. w, b) that make the observed data most probable. Products are inconvenient, so take the log:

\begin{aligned}\hat\theta_{\text{MLE}} &= \arg\max_\theta \prod_i P\big(y^{(i)} \mid x^{(i)};\theta\big)\\ \ell(\theta) &= \sum_i \log P\big(y^{(i)}\mid x^{(i)};\theta\big) && \text{log-likelihood}\end{aligned}

Loss: the negative log-likelihood

J(\theta) = -\frac{1}{m}\,\ell(\theta) = -\frac{1}{m}\sum_i \log P\big(y^{(i)}\mid x^{(i)};\theta\big)
Maximising likelihood = minimising NLL. For logistic regression, NLL is the cross-entropy loss. Averaging over m keeps the loss scale independent of dataset size.
  • MSE is the NLL under Gaussian noise: if y = f(x) + ε with ε ∼ N(0, σ²), maximising the likelihood is the same as minimising MSE.
  • MAP adds a prior and gives regularisation: a Gaussian prior on θ gives L2, a Laplace prior gives L1.

Gradients

The gradient is the vector of partial derivatives of the loss with respect to the parameters. Since J = −ℓ, ∇J = −∇ℓ: gradient descent on J is gradient ascent on the likelihood (see gradient descent).

Worked case: logistic regression

\begin{aligned}&\text{Model:} && \hat y = \sigma(w^\top x + b) = \frac{1}{1+e^{-(w^\top x+b)}}\\ &\text{Loss:} && J(w,b) = -\frac{1}{m}\sum_i\Big[y^{(i)}\log\hat y^{(i)} + (1-y^{(i)})\log(1-\hat y^{(i)})\Big]\\ &\text{Gradients:} && \frac{\partial J}{\partial w} = \frac{1}{m}\sum_i(\hat y^{(i)}-y^{(i)})\,x^{(i)},\quad \frac{\partial J}{\partial b} = \frac{1}{m}\sum_i(\hat y^{(i)}-y^{(i)})\\ &\text{Update:} && w \leftarrow w-\alpha\frac{\partial J}{\partial w},\quad b\leftarrow b-\alpha\frac{\partial J}{\partial b}\end{aligned}
The same gradient form, (prediction − target) × input, also holds for linear regression with ½·MSE.

12Evaluation metrics

Regression

Figure 16. How each loss treats an error. Squared error makes large errors (outliers) dominate; absolute error is robust but not differentiable at 0; Huber (δ = 1) combines both.
\begin{aligned}\text{MSE} &= \frac{1}{m}\sum_i (y_i-\hat y_i)^2, \qquad \text{RMSE}=\sqrt{\text{MSE}}\\ \text{MAE} &= \frac{1}{m}\sum_i |y_i-\hat y_i|\\ R^2 &= 1-\frac{\text{RSS}}{\text{TSS}} = 1-\frac{\sum_i (y_i-\hat y_i)^2}{\sum_i (y_i-\bar y)^2}\end{aligned}
RSS: variance left unexplained by the model. TSS: total variance of y around its mean. R² is the fraction of the variance in y explained by the model.
  • R² can be negative on test data, when the model is worse than always predicting the mean.
  • R² never decreases when you add features; use adjusted R² to compare models with different numbers of features.

Classification

Figure 17. A confusion matrix for 100 examples and the metrics computed from it.
MetricFormula / ideaUse when
Accuracycorrect / totalClasses are balanced
PrecisionTP / (TP + FP)False positives are costly
RecallTP / (TP + FN)False negatives are costly
F1Harmonic mean of precision and recallClasses are imbalanced
ROC-AUCRanking quality across all thresholdsComparing models independent of the threshold
Log lossCross-entropyProbability quality matters

Clustering

Clustering metrics need no labels. Inertia measures compactness; silhouette measures separation.

\begin{aligned}\text{Inertia} &= \sum_i \min_j \lVert x_i-\mu_j\rVert^2\\ \text{Silhouette} &= \frac{b-a}{\max(a,b)}\end{aligned}
a = mean distance to points in the same cluster; b = mean distance to points in the nearest other cluster. Range −1 to +1: +1 = well separated and compact, 0 = overlapping clusters, negative = points likely in the wrong cluster.
Figure 18. Choosing k for k-means. Inertia always falls as k grows, so look for the “elbow”; the silhouette score peaks at a good k. Illustrative values.
Common mistake

Inertia and silhouette score are clustering metrics, not classification metrics.

13How outliers and unscaled features affect training

Effect on gradients

Outliers can distort the updates. With MSE regression, the error (ŷ − y) becomes very large when the model is badly wrong, pulling the weights towards fitting the outlier. In logistic regression (ŷ − y) is bounded between −1 and 1, so large feature values cause the big gradients, and mislabelled points keep pulling with maximum force.

  • Mitigations: detect and handle outliers before training; robust losses (Huber); gradient clipping. Regularisation limits weight size but doesn't remove an outlier's pull, so it is a weaker fix.

Unscaled features cause unstable, slow training. The update for each weight is proportional to its feature's values, ∂J/∂wⱼ = (1/m) Σ (ŷ⁽ⁱ⁾ − y⁽ⁱ⁾) xⱼ⁽ⁱ⁾, so a feature in the thousands dominates one in [0, 1]. The loss surface becomes a long, narrow valley.

Figure 19. Simulated gradient descent, 20 steps each. Scaling turns the narrow valley into a round bowl, so one learning rate suits every direction.
  • Mitigation: feature scaling (z-score to mean 0, std 1; or min-max to [0, 1]).
Common mistake

Regularisation does not fix one feature dominating. L2 penalises all weights equally, so unscaled features are penalised unfairly: small-scale features need large weights and get punished more. Scale first, then regularise.

Effect on the decision boundary

Figure 20. One extreme point tilts the boundary towards itself. The data is still separated, but the boundary is worse for new points.
  • Outliers: dangerous even when data is separable. A single extreme point can tilt the boundary, worst for hard-margin SVMs. The classifier still separates the data, but generalisation suffers.
  • Separable data and logistic regression: without regularisation the weights grow without limit, because the loss keeps decreasing as the boundary gets sharper; the MLE doesn't exist. Regularisation or early stopping keeps the weights finite.
  • Normalising features: linear rescaling doesn't change whether data is separable. For an unregularised model trained to convergence the boundary is equivalent, just with different weights. With L2 regularisation, early stopping, SVM margins or distance-based models (k-NN, k-means), scaling changes the boundary itself. The result of normalising is faster, more stable training and, with regularisation, often a better boundary.

14The i.i.d. assumption and dependent data

Averaging the loss over a batch treats every sample equally. That assumes samples are independent and identically distributed (i.i.d.) draws from the true data distribution.

With dependent data (time series, sequences, graphs) the problems are:

  • Correlated mini-batches: consecutive samples carry nearly the same information, so the gradient estimate has high variance and can be biased towards the current stretch of the sequence.
  • Leakage when splitting: a random train/test split lets the model see the “future”. Split by time instead (forward chaining, see cross-validation).

How to handle it:

  • Weight samples or the loss.
  • Model the dependencies explicitly: RNNs, transformers, conditional random fields.
  • Change the sampling: draw windows from different parts of the sequence, with gaps between them, in each mini-batch.
Part III

Generalisation

Why models underfit or overfit, and what to do about it.

15Bias and variance

Bias is error from wrong or overly simple assumptions. A high-bias model underfits: it misses real patterns and does badly on training and test data alike.

Variance is error from being too sensitive to the particular training sample. A high-variance model overfits: it learns the noise, does well on training data and badly on new data, and would change a lot if trained on a different sample.

Figure 21. The same noisy data fitted three ways. The dashed line is the true function. A straight line misses the curve (high bias); a curve through every point chases the noise (high variance).

For squared error, the expected test error splits into three parts:

\mathbb{E}\big[(y-\hat f(x))^2\big] = \text{Bias}\big[\hat f(x)\big]^2 + \text{Var}\big[\hat f(x)\big] + \sigma^2
σ² is irreducible noise: no model can remove it. More complexity usually lowers bias and raises variance.
Figure 22. The classical trade-off. Total error is lowest where the falling bias² and rising variance balance.

How to diagnose it

StateTraining errorValidation errorGap
Underfitting (high bias)highhighsmall
Good fitlowlowsmall
Overfitting (high variance)very lowhighlarge

16Overfitting

The model learns the training data too well, including its noise and outliers (memorisation). Training error is very low, validation error is high.

Causes

  1. Model too complex for the amount of data.
  2. Too little training data.
  3. Training for too many epochs.
  4. Noisy labels, which give the model noise to memorise.

Remedies fall into two groups: change the data, or change the model and training.

17Data-centric fixes

  1. Collect more data. More examples make memorising noise harder and shrink the train–validation gap. Helps against overfitting, not underfitting.
  2. Data augmentation or synthetic data. Augmentations must keep the label valid: flipping a cat photo is fine, flipping a “6” into a “9” is not. Low-quality synthetic data can add bias, and training LLMs heavily on model-generated text can cause model collapse (not the same as GAN mode collapse).
  3. Self-supervised or transfer learning. The model learns general features from large unlabelled or related data, so it needs fewer labelled examples. Transfer learning is partly model-centric too.
  4. Clean labels, remove noise and outliers. Less noise to memorise (tools: section 7).
  5. Deduplicate. Especially important for LLMs: reduces memorisation and prevents train/test leakage.
  6. Feature selection. Fewer irrelevant features, fewer spurious patterns.
Common mistake

Shuffling does not make data normally distributed; reordering never changes a distribution. Shuffle before splitting and batching so that train/val/test come from the same distribution and mini-batches are unbiased. For time series, split by time instead.

Standardisation, (x − μ)/σ, gives mean 0 and variance 1, but that is not the same as making data Gaussian.

18Model-centric fixes

A. L2 and L1 regularisation

Add a penalty on weight size to the loss: total loss = standard loss (prediction error) + regularisation term.

L_{\text{total}} = L_{\text{standard}} + \frac{\lambda}{2}\lVert W\rVert^2 = L_{\text{standard}} + \frac{\lambda}{2}\sum_j w_j^2
Sum of squared weights. The ½ makes the gradient simply λW. Shrinks all weights towards zero. Some texts write λ/n instead; same idea, different scaling.
L_{\text{total}} = L_{\text{standard}} + \lambda\sum_j |w_j|
Promotes sparsity: drives some weights to exactly zero, acting as feature selection.
  • λ sets the trade-off. Too high: weights are forced near zero and the model underfits (training still converges, just to a too-simple solution). Too low: little effect.
  • Bias terms are usually not penalised.
  • With plain SGD, L2 and weight decay are the same thing. With Adam they are not; see AdamW.

B. Dropout

During training, each activation is set to zero with probability p, so neurons can't rely on specific partners. At inference all neurons are used (activations are scaled to compensate).

Figure 23. Each training step samples a different thinned network. The effect is similar to averaging many smaller networks.

C. Early stopping

Figure 24. Training loss keeps falling; validation loss turns up once the model starts memorising.
  • Monitor validation loss.
  • Use a patience window (stop after N epochs without improvement) so random noise doesn't trigger a stop.
  • Restore the best checkpoint, not the last one.

D. Fewer trainable parameters

  • Pruning: train the full model, remove weights (unstructured, usually by smallest magnitude) or whole neurons, heads or channels (structured), retrain, and repeat.
  • Knowledge distillation: a small student learns to match a large teacher's softened output distribution (full treatment in section 51).
  • LoRA for fine-tuning: train a small low-rank update instead of all weights. See section 52.
L = \alpha\,\text{CE}(y, p_s) + (1-\alpha)\,T^2\,\mathrm{KL}\big(p_t^{(T)} \,\Vert\, p_s^{(T)}\big)
p^(T) = softmax(z / T). Soft targets carry extra information (which wrong classes are similar) and act as a regulariser. The student often generalises better than the same small model trained from scratch, but usually not better than the teacher.
Key point

Pruning and distillation are mainly efficiency tools. Better generalisation is a side benefit, not their main purpose.

E. Ensembles

Combine several models. More common in classical ML than with large neural networks, because of cost.

MethodHow it worksMainly reduces
Bagging (e.g. Random Forest)Train models on bootstrap samples, average their outputsVariance
Boosting (e.g. XGBoost)Train models one after another, each fixing the previous errorsBias (can overfit with too many rounds)
Voting / averagingCombine predictions directly (majority vote or mean)Variance
StackingTrain a meta-model (meta-learner) on the base models' outputsBoth, depending on the base models

F. Normalisation layers

These mainly stabilise and speed up training. Any regularising effect is indirect and weaker than dropout or weight decay.

\text{LayerNorm}(x) = \gamma\,\frac{x-\mu}{\sqrt{\sigma^2+\epsilon}} + \beta
μ and σ² are computed per token across its features. ε sits inside the square root to avoid division by zero. γ and β are learned scale and shift.
LayerStatistics overRegularising effectUsed in
BatchNormThe mini-batch, per featureSome (batch statistics add noise)CNNs
LayerNormEach example's featuresVery littleTransformers
RMSNormLike LayerNorm, no mean subtractionVery littleMany modern LLMs

Where the norm sits also matters: the original Transformer normalised after each residual add (post-LN); modern LLMs normalise before each sub-layer (pre-LN), which trains more stably. See section 37.

19Cross-validation

k-fold cross-validation is an evaluation and model-selection method, not an ensemble and not a remedy by itself. It detects overfitting and helps tune hyperparameters such as λ, dropout rate or number of epochs.

Figure 25. 5-fold CV. Each round holds out a different 1/k of the data; the final score is the average over the k rounds.
  • k-fold: each fold holds out 1/k of the data, not k samples.
  • Leave-one-out (LOOCV): the special case k = n.
  • Leave-p-out: holds out p samples in each round.
  • Stratified k-fold keeps class proportions in each fold; for time series use forward-chaining splits.
  • Bootstrapping (sampling with replacement) is the other common resampling method: see section 8.

20Beyond the classic picture

Double descent

Test error first follows the classical U-curve, then peaks at the interpolation threshold: the point where the model has just enough capacity to fit the training data exactly (roughly, parameters ≈ data points). Past that point, error falls again as the model grows and can end below the best classical model.

Figure 26. Model-wise double descent. Very small models still underfit; the good region on the left is the sweet spot of the U.
  • The peak is worse with noisy labels; regularisation and early stopping reduce it.
  • It also appears over training time (epoch-wise) and with dataset size (sample-wise).
  • It helps explain why huge LLMs generalise despite having billions of parameters.

Grokking

The model first memorises the training set (≈100% training accuracy, chance-level validation accuracy). After many more steps, validation accuracy suddenly jumps to near-perfect. The smaller the training set, the more optimisation steps this takes.

Figure 27. Grokking, first reported by Power et al. (2022) on small algorithmic tasks such as modular arithmetic.
  • Weight decay is a key ingredient.
  • Practical lesson: early stopping can end training before the model groks.

21Underfitting

The model is too simple, or trained too little, to capture the underlying patterns (high bias). Training and validation error are both high and close to each other.

Causes

  • Model too simple for the task.
  • Too few training epochs.
  • Too much regularisation or dropout.
  • Poor or missing features.
  • Bad optimisation, e.g. a learning rate that is too low or too high.

Fixes

  • Increase model complexity: more layers or units, or a more expressive model class.
  • Train longer.
  • Feature engineering: more relevant features, interaction terms.
  • Reduce regularisation: lower λ, lower dropout rate p.
  • Boosting, which reduces bias. Bagging reduces variance and does little here.
  • Tune optimisation: learning rate, a better optimiser such as Adam, normalisation layers (Part II).
  • Clean the data: noisy labels limit how well any model can do (a weaker, indirect fix).
Common mistake

More data usually does not fix underfitting. If the model can't fit the data it already has, more of the same won't help much.

Part IV

Optimisation

How training actually finds good weights.

22Loss landscapes: convex and non-convex

A function is convex if the straight line (chord) between any two points on its graph never goes below the graph:

f\big(\theta x+(1-\theta)y\big) \le \theta f(x) + (1-\theta) f(y), \qquad \theta\in[0,1]
For twice-differentiable functions this is the same as f''(x) ≥ 0, or in many dimensions, a positive semi-definite Hessian.
Figure 28. Left: every chord stays above a convex curve. Right: the hump rises above the chord, so the function is not convex.
  • Key property: in a convex function every local minimum is a global minimum. That is what makes convex optimisation easy.
  • A convex function can have many global minima (a flat-bottomed valley) or none (eˣ, a straight line). Strictly convex functions (f'' > 0) have at most one.
  • Non-convex simply means not convex. It may have several local minima, but not necessarily.

Saddle points

A saddle point has zero gradient but curves up in one direction and down in another, like f(x, y) = x² − y². It only really exists in two or more dimensions; a flat inflection point is the closest 1D analogue.

Figure 29. Contours of f(x, y) = x² − y². Along x the centre is a minimum; along y it is a maximum. Gradient descent slows to a crawl near such points.

What this means for deep learning

  • Convex losses: MSE for linear regression, cross-entropy for logistic regression, hinge loss for SVMs.
  • Neural-network losses are non-convex because stacked non-linear layers make them so, even with MSE or cross-entropy. Convexity depends on the model plus the loss, not the loss formula alone.
  • In high dimensions, saddle points and plateaus are far more common than bad local minima, and most local minima have similar loss. The real difficulty is getting through saddles and flat regions; SGD noise, momentum and Adam all help.

Weight initialisation

Good initialisation doesn't guarantee the best minimum. It matters for two other reasons:

  • Breaking symmetry. If all weights start at zero, every neuron in a layer gets the same gradient and learns the same thing.
  • Keeping signals at a healthy scale through the layers, so gradients don't vanish or explode. Xavier/Glorot initialisation suits tanh and sigmoid; He initialisation suits ReLU.

23Gradient descent

Goal: find the parameters that minimise the loss, w* = argmin_w L(w). Start from initial values and repeatedly step against the gradient.

w_1 = w_0 - \alpha\,\nabla L(w_0)
∇L points uphill (steepest ascent), so −∇L is the descent direction. α is the learning rate: too small is slow, too large overshoots or diverges.
Figure 30. One step. The slope at w₀ is positive, so the step s = −α∇L(w₀) moves w to the left, to lower loss.

Batch, stochastic and mini-batch

VariantGradient fromProsCons
Batch GDThe whole dataset✓ Smooth, stable path
✓ Reaches the global minimum on convex problems
✗ Slow and memory-hungry on large data
✗ Deterministic: can stall at saddles or local minima
SGDOne example✓ Cheap updates, low memory
✓ Noise helps escape saddles and sharp minima (flatter minima tend to generalise better)
✗ Noisy path; needs learning-rate decay to settle
✗ Poor use of GPU parallelism
Mini-batch GDA batch of B examples (32 to a few thousand)✓ Balances noise and cost
✓ Efficient on GPUs
✗ Batch size is another hyperparameter

Mini-batch is the standard choice. In deep learning, “SGD” almost always means mini-batch SGD.

Figure 31. Simulated paths on the same loss. Batch GD is smooth; SGD jitters around the minimum; mini-batch sits in between.

24Momentum

Add a velocity that accumulates past gradients, like a ball rolling downhill. Steps build up along directions where the gradient is consistent and cancel where it zig-zags.

\begin{aligned} v &\leftarrow \beta v + \nabla L(w)\\ w &\leftarrow w - \alpha v && (\beta\approx 0.9)\end{aligned}
Figure 32. A ravine (high curvature across, low along). Plain GD bounces between the walls; momentum damps the bouncing and keeps moving along the valley.
  • ✓ Faster convergence.
  • ✓ Handles ravines (high-curvature valleys) well.
  • ✗ May overshoot the optimum.
  • Nesterov momentum computes the gradient at the point momentum is about to reach, which reduces overshooting.

25Adaptive optimisers: Adam and AdamW

OptimiserIdea
AdaGradEach parameter gets its own learning rate, which shrinks as its squared gradients add up. The rate can decay too far.
RMSPropLike AdaGrad, but uses a moving average of squared gradients so the rate doesn't vanish.
AdamMomentum (1st moment) + RMSProp (2nd moment), with bias correction.
AdamWAdam with weight decay applied separately from the gradient. The default for transformers and LLMs.

Adam (Adaptive Moment Estimation)

\begin{aligned} m &\leftarrow \beta_1 m + (1-\beta_1)\,g && \text{1st moment (momentum)}\\ v &\leftarrow \beta_2 v + (1-\beta_2)\,g^2 && \text{2nd moment}\\ \hat m &= \frac{m}{1-\beta_1^t},\quad \hat v = \frac{v}{1-\beta_2^t} && \text{bias correction}\\ w &\leftarrow w - \alpha\,\frac{\hat m}{\sqrt{\hat v}+\epsilon}\end{aligned}
g is the gradient at step t. Defaults: β₁ = 0.9, β₂ = 0.999, ε = 10⁻⁸, α ≈ 10⁻³. m and v start at 0, so without bias correction they would be too small in early steps.
  • ✓ Works well across many problems.
  • ✓ Little tuning of β₁, β₂, ε. The learning rate still needs tuning.
  • ✗ Needs 2 extra values per parameter (m and v): optimiser memory ≈ 2× model size.
  • ✗ On some tasks (e.g. image classification) well-tuned SGD + momentum generalises slightly better; can be unstable early in training (one reason for warmup).

Why Adam + L2 goes wrong, and AdamW fixes it

\begin{aligned} &\text{Adam + L2:} && g=\nabla L+\lambda w \;\Rightarrow\; w\leftarrow w-\alpha\frac{\hat m}{\sqrt{\hat v}+\epsilon}\\ &\text{AdamW:} && g=\nabla L \;\Rightarrow\; w\leftarrow w-\alpha\Big(\frac{\hat m}{\sqrt{\hat v}+\epsilon}+\lambda w\Big)\end{aligned}
With L2, the decay term λw is divided by √v̂ like the rest of the gradient, so parameters with large past gradients are decayed less. AdamW keeps the decay outside the adaptive scaling, so every weight shrinks at the same relative rate (Loshchilov & Hutter, 2019).
Key point

With plain SGD, L2 regularisation and weight decay are mathematically equivalent. With adaptive optimisers like Adam they are not. That is why AdamW exists.

26Learning-rate schedules

Figure 33. Linear warmup followed by cosine decay, the standard schedule for transformers.

Warmup

Start with a small learning rate (small updates, not small weights) and raise it over the first few hundred to few thousand steps.

  • Early on, weights are random, so gradients are large and unreliable. A full learning rate would cause destabilising jumps.
  • Adam's estimates m and v are poor in the first steps; warmup gives them time to settle.

Cosine decay

\text{lr}(t) = \text{lr}_{\min} + \tfrac{1}{2}\,(\text{lr}_{\max}-\text{lr}_{\min})\Big(1+\cos\frac{\pi t}{T}\Big)
Large steps early explore the landscape; small steps late let the model settle into a minimum instead of bouncing around it.

27Gradient clipping

Prevents single huge steps caused by exploding gradients, which lead to instability and divergence. Common in RNNs and transformers.

\text{if } \lVert g\rVert_2 > \text{max\_norm}: \quad g \leftarrow g\cdot\frac{\text{max\_norm}}{\lVert g\rVert_2}
‖g‖₂ is the Euclidean norm (length) of the gradient, usually computed over all parameters together (the global norm). Example: max_norm = 1.0, ‖g‖ = 5 → scale factor 1/5.
Figure 34. Clipping by norm keeps the gradient's direction and only shortens it. Clipping each value separately (“clip by value”) can change the direction.
TechniqueWhat it targets
Warmup, cosine decayStep size over the course of training
Gradient clippingSingle steps that are too large (exploding gradients)
Weight decayOverfitting (a regulariser)
TemperatureRandomness of outputs at inference, not training (section 47)
Part V

Generative models

Models that learn a data distribution and can sample new data from it.

28Generative vs discriminative

GenerativeDiscriminative
Modelsp(x), or the joint p(x, y)p(y | x), labels given inputs
Can doSample new data; also classify via Bayes' ruleLearn a decision boundary; cannot generate data
ExamplesVAEs, GANs, diffusion models, GPT-style LLMs, Naive BayesLogistic regression, SVMs, BERT classifiers
p(y\mid x) = \frac{p(x\mid y)\,p(y)}{p(x)}
Bayes' rule: how a generative model of p(x | y) and p(y) can still be used to classify.

The families below differ in how they represent p(x): through a latent variable (VAE), a two-player game (GAN), an invertible mapping (flow), a chain of conditionals (autoregressive), or iterative denoising (diffusion).

29Variational autoencoders (VAEs)

A normal autoencoder maps each input to a single point in a lower-dimensional latent space. A VAE maps each input to a probability distribution over the latent space, usually a Gaussian with a mean μ and standard deviation σ per latent dimension. The decoder takes a sample z from that distribution and reconstructs the input.

Figure 35. Training path (top) and generation path (bottom). At generation time the encoder isn't used: z comes from the prior N(0, I).

Loss: the negative ELBO

L(\theta,\phi) = \underbrace{-\,\mathbb{E}_{z\sim q_\phi(z\mid x)}\big[\log p_\theta(x\mid z)\big]}_{\text{reconstruction loss}} + \underbrace{\mathrm{KL}\big(q_\phi(z\mid x)\,\Vert\,p(z)\big)}_{\text{KL divergence}}
Reconstruction loss: negative log-likelihood of rebuilding x from z; in practice BCE or MSE. KL divergence: the regulariser, which keeps the encoder's distribution close to the prior p(z) = N(0, I) so the latent space is smooth and can be sampled. ELBO = evidence lower bound on log p(x).

Reparameterisation trick

z = \mu + \sigma\odot\epsilon, \qquad \epsilon\sim\mathcal N(0,I)
Sampling is not differentiable. Moving the randomness into ε lets gradients flow through μ and σ. Encoders usually output log σ² for numerical stability.
  • Training: z is sampled from the encoder's q_φ(z|x).
  • Generation: z is sampled from the prior N(0, I) and decoded.
  • ✓ Stable training, good coverage of the data, a useful latent space. Stable Diffusion uses a VAE to compress images before diffusion.
  • ✗ Samples tend to be blurrier than GAN or diffusion samples.

30Generative adversarial networks (GANs)

Two networks compete. The generator turns noise into fake samples; the discriminator tries to tell real from fake. As the generator improves, the discriminator must get sharper, and vice versa, until the discriminator can no longer tell them apart.

Figure 36. The adversarial loop. Both networks are trained from the discriminator's output.
\min_G\max_D\; \mathbb{E}_x\big[\log D(x)\big] + \mathbb{E}_z\big[\log\big(1-D(G(z))\big)\big]
A two-player minimax game. At the ideal equilibrium the discriminator outputs ½ for every input.
  • ✓ Sharp, high-quality samples.
  • ✓ Fast generation: one forward pass.
  • ✗ Unstable training and sensitive hyperparameters; resource-hungry.
  • ✗ Mode collapse: the generator produces only a few kinds of outputs and ignores the rest of the data distribution (low diversity).
  • ✗ No explicit likelihood: you cannot compute p(x).
Common mistake

Mode collapse (GANs) is low output diversity during training. Model collapse is the degradation that comes from training models on model-generated data. Different problems, similar names.

31Flow-based models

A chain of invertible transformations turns a simple distribution (Gaussian noise) into the complex data distribution. Because every step can be inverted, the model gives an exact log-likelihood.

\begin{aligned} &x=f(z),\quad z=f^{-1}(x),\quad z\sim\mathcal N(0,I)\\ &\log p(x) = \log p(z) + \log\left|\det\frac{\partial z}{\partial x}\right|\end{aligned}
Change of variables: the Jacobian determinant accounts for how f stretches or squeezes space.
Figure 37. f maps noise to data (generation); f⁻¹ maps data back to noise (exact likelihood).
  • ✗ Design constraints: every layer must be invertible, keep the same dimensionality, and have a cheap Jacobian determinant. Sample quality has historically lagged GANs.
  • Examples: RealNVP, Glow. A related modern idea, flow matching, is used in recent image models such as Stable Diffusion 3.

32Autoregressive models

Factorise the distribution into a chain of conditionals and generate one element at a time, each conditioned on everything generated so far.

p(x) = \prod_t p(x_t\mid x_{<t})
  • ✓ Easy to train: exact likelihood, and with transformers every position trains in parallel (teacher forcing).
  • ✗ Slow generation: one token at a time, sequentially.
  • ✗ Errors compound: early mistakes feed into later steps (exposure bias).
  • ✗ Long context is costly: transformer attention is O(n²) in sequence length (see SSMs).
  • Examples: GPT-style LLMs, PixelCNN (images), WaveNet (audio). How LLMs decode is covered in section 47.

33Diffusion and consistency models

Diffusion models

A forward process adds Gaussian noise over T steps until only noise is left. It is fixed; nothing is learned. A network learns the reverse process: removing noise step by step, which turns fresh noise into new data.

Figure 38. A 2D spiral dataset under the forward process. Generation runs the learned reverse process from right to left.
\begin{aligned} x_t &= \sqrt{\bar\alpha_t}\,x_0 + \sqrt{1-\bar\alpha_t}\,\epsilon, \qquad \epsilon\sim\mathcal N(0,I)\\ \text{Loss} &= \big\lVert \epsilon-\epsilon_\theta(x_t,t)\big\rVert^2\end{aligned}
The network (a U-Net or transformer) usually predicts the noise that was added. ᾱ_t shrinks from 1 to 0 as t goes from 0 to T.
  • ✓ Very high quality and diversity; stable training with no mode collapse.
  • ✗ Slow sampling: tens to hundreds of network passes. Fixes: DDIM samplers, distillation, and latent diffusion, which runs diffusion in a VAE's compressed latent space (Stable Diffusion).

Consistency models

Introduced by Song et al. (2023). A consistency model learns a function that maps any point on a noise-to-data trajectory to the same clean sample, so it can jump from noise to data in one step.

Figure 39. Diffusion walks the trajectory in many small steps. A consistency model learns f_θ(x_t, t) = x₀ for every point on it.
  • Consistency distillation: trained from an existing diffusion model. Consistency training: trained from scratch.
  • Generate in one or a few steps. Quality is slightly below many-step diffusion; adding steps trades speed for quality.

34Comparing generative models

ModelSample qualityDiversityGeneration speedExact likelihoodTraining
VAEBlurryGoodFastNo (lower bound)Stable
GANSharpMode-collapse riskFastNoUnstable
FlowMediumGoodFastYesStable, constrained architecture
AutoregressiveHighGoodSlow (sequential)YesStable
DiffusionVery highVery goodSlow (many steps)ApproximateStable
ConsistencyHighGoodVery fast (1–few steps)NoOften distilled from diffusion

These ratings are rules of thumb; they shift with scale and recent research.

Part VI

Transformers & attention

From token embeddings to attention, the Transformer, and the variants that scale it: mixture of experts, efficient attention and state space models.

35Embeddings and positions

Distributional hypothesis: words that occur in the same contexts tend to have similar meanings (“you shall know a word by the company it keeps”, Firth). Embeddings put this into practice: each token becomes a vector, and tokens used in similar contexts end up close together.

Figure 40. An illustrative 2D projection. Related words cluster, and some relations become directions: king − man + woman ≈ queen (word2vec).
  • Similarity is usually measured with cosine similarity: cos(a, b) = a·b / (‖a‖ ‖b‖).
  • word2vec and GloVe give one static vector per word. Transformers produce contextual embeddings: “bank” gets different vectors in “river bank” and “bank account”.

Adding position information

Attention on its own treats the input as a set, so word order would be lost. Position information is added in one of three ways:

MethodHowUsed in
SinusoidalFixed sine/cosine patterns added to the embeddingsOriginal Transformer
Learned absoluteA trained vector per position, added to the embeddingsBERT, GPT-2
RoPE (rotary)Rotates each query and key by an angle proportional to its position, so the score q·k depends on the relative distance between tokensLlama, DeepSeek, most modern LLMs

36Attention

Self-attention

Each token builds a contextual representation by weighing every other token in the same sequence, all positions in parallel. In self-attention, queries, keys and values all come from the same sequence X:

\begin{aligned} &Q=XW_Q,\quad K=XW_K,\quad V=XW_V\\ &\text{Attention}(Q,K,V) = \text{softmax}\!\Big(\frac{QK^\top}{\sqrt{d_k}}\Big)V\end{aligned}
Each query is compared with every key; the softmax turns the scores into weights that sum to 1 per row; the output mixes the values with those weights. Dividing by √d_k stops large dot products from saturating the softmax.
TermMeaning
Scaled dot-product attentionThe scoring formula above. Used by every variant below.
Self-attentionQ, K and V from the same sequence.
Cross-attentionQ from one sequence (decoder), K and V from another (encoder output).
Causal attentionSelf-attention where each position sees only itself and earlier positions.

Causal (masked) attention

The prediction at each position may depend only on the current and previous positions, never on future ones. Scores for future positions are set to −∞ before the softmax, so their weight becomes 0 and each row still sums to 1.

Figure 41. Attention weights for a toy sentence (rows = queries, columns = keys). Right: future positions are masked and each row is renormalised, so “The” attends only to itself with weight 1.00.

Multi-head attention

Run several attentions in parallel, each with its own learned projections, then concatenate the results and mix them with an output projection. Each head can focus on a different kind of relation (syntax, coreference, nearby words) in a different representation subspace.

\begin{aligned} \text{head}_i &= \text{Attention}(XW_Q^{i},\, XW_K^{i},\, XW_V^{i})\\ \text{MultiHead}(X) &= \text{Concat}(\text{head}_1,\dots,\text{head}_h)\,W_O\end{aligned}
Each head works in d_head = d_model / h dimensions, so h heads cost about the same as one full-size head.
Figure 42. Multi-head attention: parallel heads, concatenation, output projection.

37The Transformer architecture

The original Transformer (Vaswani et al., 2017) is an encoder–decoder, 6 layers each. The encoder reads the input and outputs one contextual vector per token. The decoder generates the output one token at a time, using its own previous tokens and the encoder's output.

Figure 43. Encoder–decoder Transformer. Each sub-layer also has a residual connection, omitted here for clarity.
  • Encoder layer: multi-head self-attention, then a feed-forward network.
  • Decoder layer: causal self-attention; cross-attention (queries from the decoder, keys and values from the encoder); a feed-forward network.
  • Output: a linear layer and a softmax over the vocabulary give next-token probabilities.
  • Positions are added at the input (see section 35).
  • Post-LN vs pre-LN: the original normalises after each residual add (post-LN). Modern LLMs normalise before each sub-layer (pre-LN), usually with RMSNorm, which trains more stably.

38Model families

FamilyAttentionExamplesPretrainingGood for
Encoder-onlyBidirectionalBERT, RoBERTaMasked language modellingClassification, NER, embeddings
Decoder-onlyCausalGPT, Llama, Claude, DeepSeekNext-token predictionText generation, chat
Encoder–decoderBoth + crossT5, BART, original TransformerSequence-to-sequenceTranslation, summarisation

Encoder-only models see the whole input at once, so they don't generate text autoregressively. They produce task outputs such as labels or per-token predictions.

39Mixture of experts (MoE)

MoE replaces the single feed-forward network (FFN) in a transformer block with many expert FFNs plus a router. Each token is sent to only a few experts, so the model gets far more parameters (more capacity to store knowledge) without a matching increase in compute per token. This is called sparse or conditional computation.

Figure 44. Top-2 routing over 8 experts. Only the two highest-scoring experts run; their outputs are mixed using the router's renormalised scores.

How a token is routed

  1. Router input: the token's hidden state x. The router is usually a linear layer followed by a softmax, trained together with the rest of the network. It decides before seeing any expert output.
  2. Expert computation: the selected experts each process the same x with their own weights.
  3. Combination: their outputs are summed, weighted by the router's scores, and passed on to the next layer.
\begin{aligned} g &= \text{softmax}(W_r x) && \text{one score per expert}\\ y &= \sum_{i\in \text{TopK}(g)} g_i\,E_i(x) && \text{weighted sum of chosen experts}\end{aligned}
The top-k scores are often renormalised to sum to 1. Variants: noisy top-k gating (Shazeer et al., 2017) adds noise to encourage exploration; Switch Transformer routes each token to a single expert (top-1); DeepSeek-V3 uses sigmoid gates.
  • MoE layers may replace every FFN or only some. DeepSeek-V3, for example, keeps its first 3 layers dense.
  • Experts tend to specialise in token types and syntax patterns rather than clear topics such as “maths” or “biology”.

Total vs active parameters

ModelExpertsUsed per tokenTotal paramsActive params
Mixtral 8×7B8top-2~47B~13B
DeepSeek-V3256 routed + 1 sharedtop-8 + shared671B37B
Key point

Compute per token scales with the active parameters. Memory scales with the total parameters, because every expert must be loaded.

Expert designs

Figure 45. Three designs, following the DeepSeekMoE paper (Dai et al., 2024). Highlighted experts are active for this token.
  • (a) Conventional top-2: a few large experts, 2 active per token.
  • (b) Fine-grained experts: split each expert into smaller ones and activate more of them. Compute stays the same, but the number of possible expert combinations explodes: choosing 2 of 16 gives 120 combinations, choosing 8 of 64 gives about 4.4 billion. This allows more specialised experts.
  • (c) Shared expert: one or more experts are always active and learn common knowledge, so the routed experts don't each have to relearn it. This reduces redundancy.

Load balancing

Left alone, the router sends most tokens to a few popular experts. Those experts train faster, so they get picked even more: a self-reinforcing loop that wastes the other experts (expert collapse). Two separate mechanisms counter this:

Figure 46. Share of tokens per expert (8 experts, ideal 12.5% each). Left: tokens above an expert's capacity are dropped. Right: after load balancing.
\begin{aligned} L_{\text{aux}} &= \alpha\, N \sum_i f_i\,P_i\\ \text{capacity} &= \text{capacity factor}\times\frac{\text{tokens per batch}}{N}\end{aligned}
f_i = fraction of tokens sent to expert i; P_i = average router probability for expert i. The loss is smallest when both are uniform. The auxiliary loss encourages balance; capacity is a hard limit, and overflow tokens skip the expert and pass through the residual connection (Switch Transformer).
  • Router z-loss (ST-MoE) penalises large router logits to keep training stable.
  • Auxiliary-loss-free balancing (DeepSeek-V3) adds a per-expert bias to the routing scores, raised for under-used experts and lowered for over-used ones, avoiding the quality cost of an extra loss term.

Overfitting and fine-tuning

Sparse models have huge capacity relative to small fine-tuning datasets, so they are prone to overfitting (high variance), and historically generalised poorly after fine-tuning.

  • Use a higher dropout rate inside the experts than in the dense layers.
  • Fine-tune fewer parameters, e.g. LoRA or only the non-expert layers.
  • Instruction tuning: MoE models were found to benefit from it more than dense models (Shen et al., 2023).

Dense or MoE?

SituationBetter choiceWhy
Fixed pretraining compute budgetMoEReaches the same quality with fewer FLOPs
High-throughput serving on many GPUsMoEExperts are spread across devices (expert parallelism)
Little VRAM, low throughputDenseMoE must hold all experts in memory but uses only a few
ChallengeFix
Load imbalance, expert collapseAuxiliary loss, capacity limits, bias-based balancing
Training instabilityRouter z-loss, careful initialisation
Overfitting when fine-tuningHigher expert dropout, parameter-efficient fine-tuning, instruction tuning
Memory for all expertsExpert parallelism, offloading, quantisation
Communication between GPUsExpert placement; limiting each token to experts on a few devices

40Efficient attention and the KV cache

The KV cache

During generation, the keys and values of earlier tokens don't change, so they are stored instead of recomputed. The cache grows with every token and quickly becomes the main memory cost of long contexts:

\text{KV cache} = 2 \times n_{\text{layers}} \times n_{\text{kv\_heads}} \times d_{\text{head}} \times \text{seq\_len} \times \text{bytes per value}
The 2 is for keys and values. The variants below shrink n_kv_heads (GQA, MQA) or replace K and V with a compressed latent (MLA).

MHA, GQA and MQA

Grouped-query attention lets groups of query heads share one key–value head. Query heads stay separate; only K and V are shared.

Figure 47. With 4 query heads: MHA keeps 4 KV heads, GQA shares 2, MQA shares 1.
VariantKV headsKV cacheQuality
MHAh (one per query head)LargestBest
GQAg groups (1 < g < h)h/g times smallerClose to MHA
MQA1, shared by all headsSmallestSome loss
  • The gain is mainly at inference: a smaller cache and less memory traffic, which matters for long contexts and large batches. It saves little training compute.
  • GQA is used in Llama 2 70B, Llama 3 and Mistral.

Multi-head latent attention (MLA)

Introduced in DeepSeek-V2 and used in V3/R1. Instead of sharing K and V, MLA compresses them into a small latent vector and caches only that.

Figure 48. What gets cached per token in standard attention versus MLA.
  1. Down-project each token to a latent vector: c_KV = W_DKV · x, with d_c ≪ n_heads × d_head.
  2. Cache only c_KV.
  3. Up-project when needed: K = W_UK · c_KV, V = W_UV · c_KV.
  • The up-projection can be skipped at inference: W_UK can be merged into the query projection and W_UV into the output projection, so full K and V are never built.
  • RoPE complication: rotary position embeddings don't survive the compression, so MLA keeps a small separate key part that carries position information, and caches it too.
  • GQA vs MLA: GQA shares KV heads at a small quality cost; MLA compresses them, and DeepSeek reports quality on par with or better than MHA with a much smaller cache.
Figure 49. KV cache for one 32,768-token sequence, computed with the formula above for an example model: 32 layers, 32 query heads, d_head = 128, 16-bit values. GQA uses 8 KV heads; MLA uses d_c = 512 plus 64 RoPE dimensions (DeepSeek's sizes). Illustrative, not a specific product.

Other efficiency techniques

  • FlashAttention: computes exact attention faster by reducing reads and writes to GPU memory. An implementation speed-up, not an approximation.
  • Sliding-window attention: each token attends only to the last w tokens, making cost linear in sequence length. Used in Mistral.

41State space models

SSMs are a sequence architecture, an alternative to attention, not a separate type of generative model. They can be the backbone of an autoregressive generative model. They model an internal hidden state that evolves over time and is usually not observed directly.

\begin{aligned} h_t &= A\,h_{t-1} + B\,x_t\\ y_t &= C\,h_t\end{aligned}
Figure 50. How cost grows with sequence length n. Illustrative shapes, not measured values.
  • Classical SSMs: Kalman filters, hidden Markov models.
  • Modern SSMs: S4 and Mamba (a selective SSM whose parameters depend on the input).
  • ✓ Linear time in sequence length and constant memory per generated token, versus attention's O(n²) and growing KV cache.
  • ✗ A fixed-size state must compress the whole past, so exact recall over long contexts is harder than with attention. Hybrid SSM–attention models combine both.
Part VII

Training at scale

Where GPU memory goes, how to save it on one GPU, and how to split training across many.

42The memory budget

Each training step has three phases: forward pass, backward pass, optimizer step. GPU memory has to hold four things:

  • Parameters: the learnable weights.
  • Gradients: one per parameter, used to update it.
  • Optimizer states: for Adam, the momentum m and variance v of every parameter.
  • Activations: layer outputs created in the forward pass and kept for the backward pass.
Component (mixed precision + Adam)Bytes per parameter
BF16 weights2
BF16 gradients2
FP32 master weights4
Adam m (FP32)4
Adam v (FP32)4
Total16, plus activations
Figure 51. A 7B-parameter model × 16 bytes = 112 GB before any activations: more than one 80 GB GPU holds.

What drives memory and compute

  • Batch size: activation memory grows linearly with it. Larger batches give more accurate gradients, better hardware use and fewer optimizer steps per epoch. Very large batches can hurt generalisation unless the learning rate is scaled.
  • Sequence length: activations grow quadratically with naive attention (the n×n score matrix) and linearly with FlashAttention.
  • Precision: 32-bit vs 16-, 8- or 4-bit values. Lower precision saves memory but can cost accuracy.
  • Model size: number of layers and their width.
Key point

Every technique in this part is divide and conquer, and each adds communication or recomputation. Adding GPUs gives diminishing returns: past some point, communication eats the gains.

43Saving memory on one GPU

Gradient checkpointing (activation recomputation)

Instead of storing every activation for the backward pass, keep only a few checkpoints. When the backward pass needs a missing activation, recompute it from the nearest checkpoint.

Figure 52. Trading compute for memory. Full recomputation costs roughly one extra forward pass (~30% more compute).
  • Selective recomputation recomputes only the parts that are cheap to compute but expensive to store.
  • FlashAttention recomputes only the attention scores in the backward pass instead of storing the n×n matrix. That is a narrow form of recomputation, not general checkpointing.

Gradient accumulation

Run several small micro-batches forward and backward, add up their gradients, then take one optimizer step. This simulates a large batch without holding it in memory.

\text{global batch} = \text{micro-batch}\times\text{accumulation steps}\times\text{data-parallel GPUs}
Divide the loss by the number of accumulation steps so the gradient is an average, not a sum. It saves memory but takes more time per optimizer step.

Mixed-precision training

Do most computation in 16-bit (BF16 or FP16) and keep FP32 master weights and optimizer states for accuracy. Gradients are usually BF16.

Figure 53. Exponent bits set the range; mantissa bits set the precision. BF16 keeps FP32's range with less precision.
  • FP16 needs loss scaling: its small range would round tiny gradients to zero. BF16 has FP32's range, so it doesn't.
  • FP8 training is the newest step; DeepSeek-V3 used it.
  • In PyTorch and Hugging Face this is autocast / AMP (the bf16=True or fp16=True Trainer flags).
Common mistake

bitsandbytes does not provide mixed-precision training. It provides 8-bit optimizers and 4/8-bit quantization (used in QLoRA).

Quantization

Store weights (and sometimes activations) in fewer bits, e.g. 32-bit floats to 8-bit integers, using rounding and sometimes outlier clipping. Mainly used for inference and QLoRA fine-tuning; mixed precision is the training technique.

  • Post-training quantization (PTQ) quantizes a finished model: GPTQ and AWQ (weight-only), bitsandbytes LLM.int8 and 4-bit NF4.
  • Quantization-aware training (QAT) simulates quantization during training so the model learns to tolerate it.
7B model weightsMemory
BF16~14 GB
8-bit~7 GB
4-bit~3.5 GB

Attention slicing

Computes attention in chunks one after another on a single GPU, lowering peak memory at the cost of speed. It comes from the diffusers library and is an inference trick, not a multi-GPU technique.

44Parallelism across GPUs

Figure 54. What each strategy splits: the batch (DP), the layers (PP), each layer's matrices (TP), or the sequence (CP).

Data parallelism (DP)

Each GPU holds a full copy of the model and processes a different mini-batch. After the backward pass, gradients are averaged with an all-reduce so every copy stays in sync.

  • ✓ Nearly linear speed-up when communication is fast (NVLink, NCCL). The all-reduce is overlapped with the backward pass, with gradients grouped into buckets.
  • ✗ Per-GPU memory is not reduced: each GPU stores the whole model and optimizer state. Gradient sync becomes a bottleneck on slow networks or very large models. ZeRO fixes the memory problem.

Pipeline parallelism (PP)

Naive model parallelism splits the layers into chunks on different GPUs and passes activations from one to the next. It lets a model larger than one GPU train, but only one GPU works at a time. Pipeline parallelism fixes this by splitting each batch into micro-batches that flow through the stages, so GPUs work on different micro-batches at once.

Figure 55. F = forward, B = backward, numbers are micro-batches. Shaded empty slots are the pipeline bubble: GPUs waiting while the pipeline fills and drains.
\text{bubble fraction} \approx \frac{p-1}{m} \qquad (p=\text{pipeline stages},\ m=\text{micro-batches})
More micro-batches shrink the bubble, but each micro-batch's activations must be stored until its backward pass.
  • GPipe: all forward passes, then all backward passes (as in the figure).
  • 1F1B: alternates one forward and one backward, so fewer activations are held at once.
  • Interleaved: each GPU holds several smaller stages; a smaller bubble at the cost of more communication.

Tensor parallelism (TP)

Splits the matrices inside each layer across GPUs, so every GPU works on the same tokens with a slice of the weights. Suited to wide layers; deep models are pipeline parallelism's job.

Figure 56. Megatron-style MLP: split the first matrix by columns and the second by rows, so only one all-reduce is needed per block in the forward pass. Attention is split by heads.
  • TP communicates activations on every layer, so keep it inside one node on fast NVLink, typically TP ≤ 8.
  • TP shards activations only inside the split layers. LayerNorm and dropout still hold full activations, so sequence parallelism is added alongside TP to shard those along the sequence.

Context and expert parallelism

  • Context parallelism (CP): splits a long sequence across GPUs (e.g. ring attention), for very long contexts.
  • Expert parallelism (EP): places MoE experts on different GPUs and sends tokens to them.

DP, TP, PP, CP and EP together are often called 5D parallelism.

Communication operations

OperationWhat it doesUsed in
All-reduceEvery GPU ends with the sum of all inputsDP gradient sync, TP
All-gatherEvery GPU ends with all the piecesZeRO-3 parameters, TP
Reduce-scatterSum, then each GPU keeps one pieceZeRO-2/3 gradients

45ZeRO: sharding the model state

Plain data parallelism stores the same parameters, gradients and optimizer states on every GPU. ZeRO (DeepSpeed) removes this redundancy by partitioning them across the data-parallel GPUs, so each stores only a slice.

StagePartitionsMemory per GPUCommunication vs DP
DP (baseline)nothing16Ψ1×
ZeRO-1optimizer states4Ψ + 12Ψ/Nsame
ZeRO-2+ gradients2Ψ + 14Ψ/Nsame
ZeRO-3+ parameters16Ψ/N~1.5× (parameters gathered layer by layer)

Ψ = number of parameters, N = data-parallel GPUs, mixed precision with Adam.

Figure 57. Memory per GPU for a 7B model on 8 data-parallel GPUs, from the formulas above (activations not included).
  • PyTorch FSDP (Fully Sharded Data Parallel) is essentially ZeRO-3.
  • Limits: ZeRO doesn't shard activations, which grow with batch size and sequence length. ZeRO-3 also needs each layer's full parameters gathered on one GPU while that layer runs. Tensor, sequence and context parallelism address these.

46Combining strategies

  • Data + pipeline: each data-parallel replica is a pipeline spread over several GPUs.
  • Data + tensor: TP inside each node (fast NVLink), DP across nodes. Each data-parallel replica is a TP group.
  • 3D parallelism (DP + PP + TP): typically TP inside a node, PP across nodes, DP outermost. DeepSpeed and Megatron combine these.
  • ZeRO-1, not ZeRO-3, with pipelines: ZeRO-2/3 would have to communicate gradients or parameters for every micro-batch, which clashes with pipelining.

What each technique reduces

TechniqueParamsGradsOptimizerActivationsCost
Gradient checkpointing✓Extra compute
Gradient accumulation✓ (per step)More time
Mixed precision✓✓✓Precision care
ZeRO-1 / 2 / 332, 31, 2, 3Communication
Tensor parallelism✓✓✓Partly (+ sequence parallelism)Communication every layer
Pipeline parallelism✓✓✓✓Bubbles
Context parallelism✓Communication

Further reading: Hugging Face, The Ultra-Scale Playbook (2025).

Part VIII

LLMs in practice

Generating text, test-time compute, serving and latency, distillation, fine-tuning, retrieval-augmented generation, and how the earlier ideas apply at scale.

47Decoding strategies

Autoregressive decoding generates one token at a time: the model outputs a probability for every vocabulary token, one is chosen, appended to the input, and the loop repeats until an end token or a length limit. Each step reuses the KV cache (section 40). Strategies are either deterministic (search) or stochastic (sampling).

Deterministic: greedy and beam search

Figure 58. Greedy takes the best token at each step and ends at 0.5 × 0.4 = 0.20. Beam search (width 2) keeps both “nice” and “dog” after step 1 and finds 0.4 × 0.9 = 0.36. Example tree after Hugging Face's How to generate text.
  • Greedy search: always take the most likely token. Simple and fast, but it misses better sequences hidden behind a lower-probability first token, and can be repetitive.
  • Beam search: at each step, extend every beam with every possible next token, score each sequence by its total probability, and keep the top B (the beam width). It is a heuristic: it doesn't guarantee the most probable sequence overall.
\text{score}(y) = \sum_t \log P(y_t\mid y_{<t},x), \qquad \text{normalised: } \frac{\text{score}(y)}{|y|^{\alpha}},\ \ \alpha\approx 0.6\text{–}1.0
Multiplying many probabilities below 1 underflows to 0 in floating point; summing logs avoids that, and the ranking is unchanged because log is monotonic. Every token adds a negative term, so without length normalisation beam search favours short outputs.
  • Good for translation and summarisation; poor for open-ended chat, where it produces generic, repetitive text. An n-gram repetition penalty helps.
  • Contrastive search is a deterministic alternative that penalises tokens too similar to earlier context.

Stochastic: top-k, top-p and min-p

  • Top-k: keep the k most probable tokens, renormalise them to sum to 1, and sample. Lower k is more predictable, higher k more diverse.
  • Top-p (nucleus): sort tokens by probability and keep the smallest set whose cumulative probability reaches or exceeds p, then renormalise and sample. Typical p = 0.9–0.95.
  • Min-p: keep tokens whose probability is at least a fraction of the top token's. Adapts like top-p and holds up well at high temperature.
Figure 59. A fixed k fits badly: on the peaked step it lets in unlikely tokens, on the flat step it cuts off good ones. Top-p adapts the number of kept tokens to the distribution. Kept-token counts are computed from the bars shown.
  • Order of operations in most libraries: temperature first, then top-k, then top-p, then sample. Settings like temperature=0.7, top_p=0.9 combine.
  • Repetition / frequency penalties down-weight tokens that have already appeared.
  • Sampling (temperature > 0) is what makes self-consistency and best-of-N possible.
StrategyDeterministic?Good forWatch out for
GreedyYesShort factual answers; speedMisses better sequences; repetition
Beam searchYesTranslation, summarisationGeneric, short outputs without length normalisation
Top-kNoCreative textFixed k fits peaked and flat steps badly
Top-pNoChat, open-ended textVery high p with high temperature becomes incoherent

Temperature

Temperature rescales the logits before the softmax. It is an inference setting for sampling; it doesn't affect training optimisation. It also appears in knowledge distillation.

p = \text{softmax}(z/T)
Figure 60. The same five logits at three temperatures.
TEffect
T → 0Always picks the top token (greedy)
T < 1Sharper, more confident
T = 1Unchanged
T > 1Flatter, closer to uniform, more random

DoLa: decoding for factuality

DoLa (Decoding by Contrasting Layers, Chuang et al., 2023) contrasts the final layer's next-token distribution with an earlier layer's. Tokens whose probability grows in later layers, where factual knowledge tends to emerge, are boosted. It aims at better factuality and less hallucination, at a small extra cost, not at speed. Hugging Face doesn't recommend it for small models such as GPT-2.

48Test-time compute

Instead of only growing pretraining budgets, test-time methods let a trained model “think longer” on harder problems by spending more compute at inference.

FamilyIdeaExamples
ParallelSample many answers, then pick or voteBest-of-N, self-consistency
SequentialImprove one answer step by stepSelf-refine, long chain-of-thought
SearchExplore partial solutions guided by a verifierBeam search, DVTS, tree search
  • Reasoning models (OpenAI o1, DeepSeek-R1) are trained with reinforcement learning to produce one long chain of thought: sequential scaling built into the model.
  • Compute-optimal scaling (Snell et al., 2024): the best strategy depends on problem difficulty, and a small model with more test-time compute can match a much larger one on some problems. Hugging Face reports Llama 3.2 3B with search outperforming Llama 3.1 70B on MATH-500.

Self-refinement

Self-Refine (Madaan et al., 2023) uses the same model to generate, critique and rewrite, with no extra training: only a feedback prompt, a refine prompt and a stopping rule.

Figure 61. The Self-Refine loop. Every box is the same model with a different prompt.
  • Stopping rule: a fixed number of rounds, or the model saying no more changes are needed.
  • ✗ Works with strong models, but LLMs often can't fix their own reasoning errors without external feedback (Huang et al., 2023) and may change correct answers to wrong ones.
  • ✓ Better: get feedback from a separate LLM judge, or even better from a tool or test (a compiler, unit tests, a calculator).

Self-consistency (majority voting)

Sample N answers with temperature > 0 and take the most common final answer. No verifier is needed, but answers must be comparable (numbers, multiple choice). A strong, cheap baseline to beat before adding a verifier.

Search against a verifier

Generate several candidates and let a verifier choose. A verifier can be anything from a hard-coded check to a learned reward model:

VerifierScoresExample
Heuristic / exactFinal answerUnit tests, an exact-answer checker
ORM (outcome reward model)The final answer onlyA learned model judging the whole solution
PRM (process reward model)Every stepMath-Shepherd-style step scores
LLM as judgeEitherA prompted strong model
Figure 62. Search strategies with N = 4 and beam width M = 2. Green = kept by the verifier, red = pruned, ringed = selected answer.
  • Best-of-N: generate N full solutions and keep the highest-scored one. Weighted best-of-N sums the scores of solutions reaching the same answer and usually wins.
  • Beam search: keep N beams; at each step the PRM keeps the top N/M partial solutions and each is expanded into M continuations.
  • DVTS (diverse verifier tree search): split the N beams into N/M independent subtrees, each searched greedily with the PRM, which keeps solutions diverse.
  • When each wins (Hugging Face results): beam search at small budgets and hard problems; DVTS at large N on easy and medium problems, where beam search collapses onto similar solutions.
  • ✗ Cost grows linearly with N, and at large N search finds solutions the verifier likes but that are wrong (reward hacking).

Reducing step scores to one score

A PRM gives one score per step, so a solution needs a reduction to a single number:

Figure 63. Three reductions of the same step scores, computed from the values shown. Highlighted cells are the ones each reduction uses.
  • min is pessimistic: one weak step sinks the whole solution.
  • prod penalises long solutions: more steps means more factors below 1.
  • last worked best in Hugging Face's experiments with their PRM.

Further reading: Hugging Face, Scaling test-time compute with open models (2024).

49Serving LLMs with vLLM

Test-time methods multiply the number of generated tokens, so serving speed matters. vLLM is a fast, easy-to-use library for LLM inference and serving (not to be confused with a VLM).

PagedAttention

Stores the KV cache in fixed-size blocks, like pages of virtual memory in an operating system, instead of one contiguous slab per request.

Figure 64. Top: reserving the maximum length per request wastes memory. Bottom: blocks are allocated on demand, and two samples from the same prompt share its blocks. Block numbers are illustrative.
  • Almost no memory is lost to fragmentation, so more requests fit at once.
  • Samples from the same prompt share its KV blocks: ideal for best-of-N and self-consistency.
  • Prefix caching reuses blocks for shared system prompts across requests.

Continuous batching

Figure 65. Four GPU slots over time. With continuous batching, requests join and leave at every generation step, so slots rarely sit idle and all six requests finish sooner.

Speculative decoding

A small draft model proposes k tokens; the large target model checks all of them in one forward pass. Accepted tokens are kept and the first rejected one is replaced, so generation is faster while the output distribution is unchanged.

Figure 66. One verification step: four tokens produced for one pass of the large model instead of four. Tokens are illustrative.

Speculative decoding in depth

Notation

Here p = draft model and q = target model. The original papers (Leviathan et al., 2023; Chen et al., 2023) use the opposite letters. Pick one convention and state it.

Goal: produce tokens exactly as if sampled from the target q, while most of the work is done by the cheap draft p. For each draft token x:

\begin{aligned} &\text{Case 1: } q(x)\ge p(x) && \Rightarrow \text{accept}\\ &\text{Case 2: } q(x)<p(x) && \Rightarrow \text{accept with probability } \tfrac{q(x)}{p(x)} \;\;(r\sim U(0,1),\ \text{accept if } r<\tfrac{q}{p})\\ &\text{Rejected:} && \Rightarrow \text{resample from } q'(x)=\frac{\max(0,\,q(x)-p(x))}{\sum_x \max(0,\,q(x)-p(x))}\text{, then stop}\end{aligned}
Every draft token after a rejection is discarded, because it was conditioned on a token that was thrown away.
Figure 67. Why the output follows the target exactly. Accepted tokens contribute the overlap min(p, q); rejections are refilled from the residual (q − p)₊. Together: min(p, q) + (q − p)₊ = q. Distributions are illustrative.
P(x) = p(x)\min\!\Big(1,\frac{q(x)}{p(x)}\Big) + P(\text{reject})\,q'(x) = \min\big(p(x),q(x)\big) + \max\big(0,\,q(x)-p(x)\big) = q(x)

Worked example

TokenDraft pTarget qAccept probabilityResult
dogs0.80.91 (case 1)✓
love0.70.81 (case 1)✓
chasing0.90.80.8/0.9 ≈ 0.89✓ (this draw passed)
after0.80.30.3/0.8 = 0.375✗ (this draw failed): resample from q′
cars–––discarded

The ✓ and ✗ are one random outcome: with other draws “chasing” could be rejected or “after” accepted. This round yields 4 tokens (3 accepted + 1 resampled) from one target pass.

The algorithm

while len(seq) < max_len:
    # draft: propose k tokens, keeping each FULL distribution p_1..p_k
    # target: ONE pass on seq + drafts → q_1..q_{k+1}
    #         (logits at position t predict token t+1: shift by one)
    for i in 1..k:
        if rand() < min(1, q_i(x_i) / p_i(x_i)):
            accept x_i
        else:
            append sample(normalise(max(0, q_i − p_i)))
            break
    else:
        append sample(q_{k+1})        # bonus token: all k accepted
  • The loop advances by accepted tokens + 1, so each round yields between 1 and k+1 tokens.
  • The draft's full distributions are needed to compute the residual, not only the chosen tokens' probabilities.
  • Greedy decoding simplifies the rule: accept a draft token if it equals the target's top token.

Expected speed-up

\mathbb{E}[\text{tokens per target pass}] = \frac{1-\alpha^{k+1}}{1-\alpha}
α = probability a draft token is accepted. Example: α = 0.8, k = 4 → (1 − 0.8⁵)/0.2 ≈ 3.4 tokens per pass.
Figure 68. Computed from the formula above. A large k only pays off when the draft is usually accepted; at low α every k gives little more than one token per pass. Wall-clock gain is lower, since the draft's own cost is not included.
  • A good draft is small, fast, similar to the target, and shares its tokenizer. Typical k = 3–8.
  • It helps most when decoding is memory-bound (small batches); see section 50.

Other features

  • CUDA/HIP graphs: record a sequence of GPU operations once and replay it, cutting per-step launch overhead.
  • Quantization: GPTQ, AWQ, INT4, INT8, FP8 (see section 43).
  • Optimised kernels: FlashAttention and FlashInfer.
  • Tensor parallelism across GPUs and an OpenAI-compatible API.
UseOptions
High-throughput servingvLLM, SGLang, TensorRT-LLM, TGI
Local / laptopllama.cpp, Ollama

50Latency optimisation

Many speed-ups cost no quality at all. Know which phase is slow, then pick the technique that targets it.

Prefill and decode

Figure 69. Generation has two phases with different bottlenecks. Step widths are illustrative.
PhaseWhat happensBottleneckMetric
PrefillProcesses the whole prompt at onceComputeTTFT: time to first token
DecodeOne token per stepMemory bandwidth: all weights and the KV cache are read every stepTPOT: time per output token
  • Latency is how long one request takes; throughput is tokens per second across all users.
  • Decoding at small batch sizes is memory-bound, so anything that moves fewer bytes per step (quantization) or produces more tokens per pass (speculative decoding) speeds it up.

Lossless vs lossy

Lossless (same outputs, just faster)Lossy (may cost quality)
KV cache; static cache + torch.compileQuantization
FlashAttention, PyTorch SDPA, kernel fusionPruning, distillation to a smaller model
Speculative, self-speculative and prompt-lookup decodingSliding-window and other approximate attention
Tensor parallelism, batching, prefix caching

Model-side techniques

  • KV cache: stores past keys and values so they aren't recomputed each step (section 40). PagedAttention is a way to manage that cache's memory, not the cache itself.
  • Static cache + torch.compile: torch.compile fuses PyTorch code into optimised kernels but needs fixed tensor shapes; a cache that grows each step would trigger recompilation. Pre-allocating the cache to the maximum length keeps shapes fixed, so compiled kernels and CUDA graphs are reused.
  • Speculative decoding (section 49): a small assistant model drafts tokens that the large model verifies.
    • Self-speculative decoding (e.g. LayerSkip): the same model exiting at an early layer drafts; the full model checks. The draft is lower quality, the final output isn't, and no second model is needed.
    • Multi-token prediction: extra heads trained to predict several future tokens (Medusa heads, DeepSeek-V3's MTP module) can serve as the draft.
  • Quantization: store weights in lower precision. Weight-only methods (GPTQ, AWQ) speed up decoding mainly because fewer bytes are read per token. Mixed-precision quantization keeps sensitive parts higher-precision (LLM.int8 keeps outlier features in FP16) for better accuracy.
  • Smaller models: pruning and distillation. Lossy, so check quality on your task.

Prompt lookup decoding

Speculative decoding where the draft comes from n-grams already in the prompt instead of a draft model: free, and lossless because the model still checks every token. Works best when the output copies from the input: summarisation, RAG answers, code edits.

Figure 70. The last two generated tokens match a bigram in the prompt, so the tokens that followed it are proposed as the draft. Example text is illustrative.

GPU-side techniques

FlashAttention splits attention into tiles that fit in fast on-chip memory (SRAM) and never writes the n × n score matrix to slower GPU memory (HBM). It is IO-aware and exact.

Figure 71. The saving is memory traffic, not arithmetic: the same maths, far fewer slow reads and writes.
  • FlashAttention-2 divides the work better and also parallelises over sequence length; FlashAttention-3 targets H100 (Hopper) GPUs.
  • PyTorch SDPA (scaled_dot_product_attention) automatically picks a backend (FlashAttention, memory-efficient attention, or the plain maths version) depending on GPU, data type and mask.
  • Tensor parallelism splits each layer across GPUs, so one request runs faster: it lowers latency for large models but needs fast interconnects (NVLink).
  • Batching runs many requests together: it raises throughput but can make each request slightly slower. Continuous batching reduces that cost.
  • Vectorisation and kernel fusion: operate on whole tensors instead of loops, and fuse several operations into one GPU kernel to avoid writing intermediates to memory and cut launch overhead. torch.compile and FlashAttention both do this.

Serving-level techniques

  • Prefix caching: reuse the KV cache for shared system prompts.
  • Chunked prefill: split long prompts so they don't stall other users' decoding.
  • Streaming: doesn't make generation faster, but users see text after TTFT instead of waiting for the whole response.

Which technique helps which metric

TechniqueTTFTTPOTThroughputLossless?
KV cache✓✓✓
Static cache + torch.compile✓✓✓✓
FlashAttention / SDPA✓ (long prompts)✓✓✓
Speculative / prompt lookup✓✓
Quantization✓✓✓✗
Tensor parallelism✓✓✓
Continuous batching✓✓
Prefix caching✓✓✓

Further reading: Hugging Face Transformers documentation, LLM inference optimization.

51Knowledge distillation

A small student learns from a large teacher, giving most of the teacher's quality at a fraction of the cost. Three things can be transferred: outputs, intermediate features, or relations.

Figure 72. Where each type of knowledge is taken from. Feature matching needs a projection when widths differ; relation matrices have the same shape whatever the width.

Response-based: soft targets

Train the student to match the teacher's output distribution (Hinton et al., 2015):

L = \alpha\,T^2\,\mathrm{KL}\Big(\text{softmax}\big(\tfrac{z_t}{T}\big)\,\Big\Vert\,\text{softmax}\big(\tfrac{z_s}{T}\big)\Big) + (1-\alpha)\,\text{CE}\big(y,\text{softmax}(z_s)\big)
z_t, z_s = teacher and student logits. Temperature T softens both distributions; the hard-label term uses T = 1. Softening shrinks gradients by about 1/T², so the T² factor keeps the two terms balanced. Typical T = 2–5, α = 0.5–0.9.
Figure 73. The same teacher logits at T = 1 and T = 4, computed with softmax. The hard label only says “2”; the softened distribution also shows that “7” is the most similar wrong class. This “dark knowledge” is what the student learns from, and it acts as a regulariser.

Feature-based

Match intermediate representations (FitNets, Romero et al., 2015), usually with MSE or cosine loss on chosen “hint” layers.

  • Student layers are usually narrower: add a small learned projection to map them to the teacher's width.
  • Matching very deep layers over-constrains a small student; middle layers are a common choice.
  • In practice the losses are combined: L = α·CE + β·KD + γ·L_feature.
  • MSE, MAE and RMSE are training losses here. To evaluate a student's embeddings, use cosine similarity to the teacher's, downstream retrieval or classification accuracy, or benchmarks such as MTEB.

Relation-based

Transfer how samples or layers relate to each other, rather than the values themselves.

  • RKD (Park et al., 2019) matches distances and angles between samples' embeddings; similarity-preserving KD matches the batch's n × n similarity matrix; FSP matrices capture correlations between two layers' feature maps.
  • ✓ Relation matrices have the same shape whatever the model width, so no projection is needed, even across architectures.
  • ✗ Choosing which relations to transfer is task-specific, and batch relations cost O(n²) in batch size. Students can approach the teacher; beating it is uncommon.
TypeTransfersLossNeeds same width?
Response-basedOutput distributionsKL with temperature + CENo
Feature-basedIntermediate featuresMSE / cosine (+ projection)Yes, or add a projection
Relation-basedRelations between samples or layersDistance / angle / similarity matchingNo

Training approaches

  • Offline: the teacher is trained first and frozen; its soft labels can be precomputed and cached. The standard setup.
  • Online: teacher and student train together. In deep mutual learning, peer models learn from each other with no pre-trained teacher.
  • Self-distillation: one network is both teacher and student. Deeper layers can teach shallower ones (enabling early exit), or a model can learn from its own earlier predictions. Born-Again Networks train a same-size student that often beats its teacher.

Distilling LLMs

TypeHowNeedsExamples
Black-box (sequence-level)Fine-tune the student on text the teacher generatesOnly teacher outputsAlpaca; DeepSeek-R1-Distill models trained on R1's reasoning traces
White-box (logit-level)Match the teacher's full next-token distributionsTeacher logits and the same tokenizerDistilBERT, MiniLLM
  • DistilBERT is 40% smaller and 60% faster than BERT while keeping 97% of its language-understanding performance.
  • On-policy distillation (GKD): the teacher scores text the student generates, fixing the train/inference mismatch (exposure bias).
  • Licences: some model terms forbid using their outputs to train competing models.

Forward vs reverse KL

Figure 74. Fitting a single-peaked student to a two-peaked teacher. Both fits are computed: forward KL by matching mean and variance, reverse KL by grid search.
  • Forward KL(teacher ‖ student) is mean-seeking: the student spreads probability over everything the teacher might say, including the low-probability gap between modes.
  • Reverse KL(student ‖ teacher) is mode-seeking: the student commits to the teacher's main answers. Often better for generation (MiniLLM).

52LoRA (Low-Rank Adaptation)

Instead of fine-tuning a full weight matrix W ∈ ℝ^(d×k), freeze it and train a small low-rank update.

\begin{aligned} &\Delta W = BA,\quad B\in\mathbb R^{d\times r},\ A\in\mathbb R^{r\times k},\ r\ll\min(d,k)\\ &h = Wx + \frac{\alpha}{r}\,BAx\end{aligned}
W stays frozen; only A and B are trained.
Figure 75. B is tall and thin, A is short and wide; their product has the same shape as W but rank at most r.
  • r (rank): higher r gives more expressive updates but more parameters and memory. Typical values: 4 to 64.
  • α (lora_alpha): scales the update. Larger α gives stronger updates. Dividing by r lets you change the rank without retuning the learning rate; common choices are α = r or α = 2r.
  • Initialisation: A is random (Gaussian), B is zero, so ΔW = 0 at the start and training begins exactly from the pretrained model.
  • Parameter savings: r·(d + k) instead of d·k. With d = k = 4096 and r = 8: 65,536 versus 16.8M, about 0.4%. Memory is saved mainly on gradients and optimiser states (Adam's m and v).
  • No extra inference cost: after training, merge W′ = W + (α/r)·BA, or keep adapters separate and swap them per task.
  • Where: the original paper (Hu et al., 2021) adapted the attention projections W_q and W_v; today often all linear layers.
  • QLoRA keeps the frozen base model in 4-bit precision, making fine-tuning of very large models possible on one GPU.
  • Fewer trainable parameters means less capacity to memorise, but LoRA can still overfit on small datasets.

53Retrieval-augmented generation (RAG)

RAG gives an LLM access to knowledge it wasn't trained on. A retriever finds relevant passages for the question, and a reader (the LLM) answers using them. This keeps answers current, grounded in sources you control, and citable.

Figure 76. The two halves of RAG. Indexing runs offline (pre-production); retrieval and reading run for every query (production). Frameworks such as LlamaIndex, LangChain and Haystack wire these steps together.

Design questions first

  • Simplicity: what is the simplest model and pipeline that is accurate enough?
  • Base vs instruction model: an instruction-tuned model expects its own chat template (role tags, special tokens); quality drops without it. A base model has no template.
  • Do we also need recommendations, or only answers?
  • Constraints: safety, privacy, storage, latency, cost, and how the system will be evaluated.
RAGFine-tuning (e.g. LoRA)
Best forFacts, changing or private knowledgeStyle, format, task behaviour
Updating knowledgeRe-index documentsRetrain
CitationsNatural: answer points to sourcesHard
CostRetrieval at every query, longer promptsTraining up front

The two combine well: fine-tune for behaviour, retrieve for knowledge.

Chunking

Figure 77. The same document, with three paragraphs per colour-coded topic, split three ways. Thin lines mark paragraph boundaries.
MethodHow it splits
Fixed-size characterEvery N characters, with overlap
Recursive characterTries paragraphs, then sentences, then words, until chunks fit
Document-specificFollows structure: Markdown headers, code functions, HTML tags
SemanticSplits where embedding similarity between consecutive sentences drops
AgenticAn LLM decides boundaries or rewrites text into self-contained statements
  • Size trade-off: small chunks are precise to retrieve but lose context; large chunks keep context but give noisier embeddings. A common start is 256–1,024 tokens with 10–20% overlap.
  • Metadata (source, date, section) enables filtering and citations.
  • Small-to-big / parent-document retrieval: retrieve small chunks, then pass their larger parent to the LLM.

Choosing an embedding model

  • Compare on the MTEB leaderboard, then test on your own domain and languages.
  • Maximum input length and vector dimension drive storage and speed.
  • Use the same model for queries and documents. Some need prefixes, such as E5's “query: ” and “passage: ”.

54Retrieval: search, reranking and context

Vector stores and nearest-neighbour search

  • FAISS is a library, not a database: a fast in-memory index without persistence, metadata filtering or access control.
  • Vector databases: MongoDB Atlas Vector Search (convenient if your data already lives in MongoDB), pgvector, Qdrant, Weaviate, Milvus, Chroma.
  • Approximate nearest-neighbour (ANN) indexes: HNSW (graph-based), IVF (clusters), PQ (compression). They trade a little recall for a lot of speed; see section 55.
  • Distance metric: for unit-length vectors, cosine and dot product give the same ranking, and Euclidean too (‖a − b‖² = 2 − 2·cos). But use the metric the embedding model was trained with: for a model trained on raw dot product, normalising changes the results.

Hybrid search

Dense (vector) search captures meaning but misses exact matches: IDs, names, codes, rare terms. Keyword search (BM25) catches those. Standard practice runs both and merges the ranked lists with reciprocal rank fusion:

\text{RRF}(d) = \sum_{\text{lists}} \frac{1}{k+\text{rank}(d)}, \qquad k\approx 60
Only ranks are used, so scores on different scales (BM25 vs cosine) don't need calibrating.
Figure 78. RRF with k = 60. Documents ranked well by both lists (D1, D3) rise to the top; scores are computed from the formula above.

Query reformulation

  • Query rewriting: clean up or expand the question.
  • Multi-query: generate several phrasings and merge the results.
  • Decomposition: split a complex question into sub-questions.
  • HyDE: have the LLM write a hypothetical answer, then embed that instead of the question.

Reranking

“Learning to rank” is the broad family. In RAG the reranker is usually a cross-encoder (e.g. bge-reranker, Cohere Rerank).

Figure 79. A bi-encoder can precompute every document vector; a cross-encoder must run once per query–document pair but sees both texts together.
Bi-encoder (retriever)Cross-encoder (reranker)
InputQuery and document embedded separatelyQuery and document read together
SpeedFast; document vectors precomputedSlow; one pass per pair
AccuracyGoodBetter
UseRetrieve top 50–100 from millionsRerank to top 3–10

Building the prompt and verifying

  • Lost in the middle: LLMs use information at the start and end of the context better than the middle. Put the best chunks first or last.
  • Context compression: drop irrelevant sentences to save tokens and reduce distraction.
  • Verification: groundedness (faithfulness) checks, citations back to source chunks, an LLM as judge, and answering “I don't know” when nothing relevant was retrieved.

Evaluating RAG

StageMetrics
RetrievalRecall@k, MRR (mean reciprocal rank), nDCG
GenerationFaithfulness (grounded in the context?), answer relevance
End to endRAGAS (faithfulness, answer relevancy, context precision and recall), human review

55Vector search indexes

Retrieval needs the nearest vectors to a query among millions. There are two ways to make that faster than comparing against everything:

LeverHowIndexes
Smaller vectorsFewer dimensions or fewer bits per valuePQ, scalar / binary quantisation, PCA
Smaller search scopeCompare against only a subset of vectorsIVF, HNSW, LSH

Flat (exact) search

Compute the distance from the query to every stored vector, with L2 or inner product (FAISS IndexFlatL2 / IndexFlatIP).

L_2(x_q,y) = \sqrt{\sum_{i=1}^{d}\big(y_i-x_{q,i}\big)^2}
Cost per query is O(N·d): query time grows linearly with the number of vectors. Recall is exactly 1.0, so flat search is the baseline other indexes are measured against. 1M vectors × 128 dims × 4 bytes = 512 MB.

Locality-sensitive hashing (LSH)

Unlike cryptographic hashes, LSH wants collisions: similar vectors should land in the same bucket. FAISS IndexLSH projects each vector onto nbits random hyperplanes and keeps the sign of each projection as one bit; vectors are compared by Hamming distance between their codes.

Figure 80. Random-hyperplane LSH with nbits = 3. Each line contributes one bit (which side the point is on); points in the same region share a code. The query is compared only with its own bucket, or nearby codes.
  • Curse of dimensionality: as d grows, nbits must grow to keep recall, and search slows down.
  • Rarely the best choice for dense embeddings today; IVF and HNSW usually beat it.

Inverted file index (IVF)

k-means splits the space into nlist cells (Voronoi cells). A query searches only the nprobe cells whose centroids are nearest.

Figure 81. IVF with nlist = 12 and nprobe = 3. Only highlighted points are compared. A query near a cell edge would miss its true neighbour with nprobe = 1: the edge problem.
  • Raising nprobe fixes the edge problem and doesn't increase memory, but it does increase search time: it trades speed for recall.
  • IVF needs training (k-means on representative data). Rule of thumb: nlist ≈ 4√N to 16√N.

Product quantization (PQ)

IVF reduces how many vectors are compared; PQ makes each comparison cheap by compressing the vectors.

  1. Split each d-dimensional vector into m equal subvectors.
  2. Run a separate k-means on each of the m subspaces (typically 256 centroids each): the codebooks.
  3. Replace each subvector with the ID of its nearest centroid.
Figure 82. Top: encoding a 128-dim float32 vector (512 bytes) into 8 one-byte IDs, 64× smaller. Bottom: asymmetric distance computation. Codes and table values are illustrative.
  • Asymmetric distance computation (ADC): for each query, precompute the distance from each query subvector to every centroid (an m × 256 table). A database vector's distance is then the sum of m table lookups.
  • Plain PQ is still exhaustive, just cheap per vector. IVFPQ combines both levers: IVF cuts the scope, PQ compresses.
  • PQ is lossy, so recall drops; rerank the top candidates with the original vectors to recover it. OPQ adds a learned rotation before PQ for better accuracy.

Hierarchical navigable small world graphs (HNSW)

In a navigable small world graph, each vector links to its near neighbours, plus some long links, so any node is reachable in a few hops. HNSW stacks several such graphs like express lanes.

Figure 83. Greedy search, computed on a toy graph: on each layer, move to whichever neighbour is closest to the query until none is closer, then drop to the layer below and continue.
  • Each node gets a maximum layer drawn with exponentially decreasing probability, so higher layers hold far fewer nodes. Layer 0 holds every node.
  • M: links per node (higher = better recall, more memory). efConstruction: search width while building. efSearch: search width at query time (higher = better recall, slower).
  • ✓ Excellent speed and recall, no training; the default in most vector databases.
  • ✗ High memory (full vectors plus every node's links); deletions are awkward.

When to use which

IndexMemory (MB)Query time (ms)RecallNotes
Flat (L2 or IP)~500~181.0Small datasets, or when query time doesn't matter
LSH20–6001.7–300.4–0.85Low-dimensional data or small datasets
HNSW600–1,6000.6–2.10.5–0.95Very good quality and speed; large memory
IVF~5201–90.7–0.95Scalable, good balance of quality, speed and memory
IVFPQVery lowVery fastLowerVery large datasets; rerank to recover recall

Figures from Pinecone's FAISS benchmark (1M vectors, 128 dimensions); they change with dataset and parameters. Every index trades off speed, memory and recall: you can't max out all three.

Optimising the embeddings themselves

  • Dimensionality reduction: PCA or random projection. Matryoshka embeddings are trained so you can simply keep the first k dimensions.
  • Quantisation: int8 scalar quantisation (4× smaller); binary (32× smaller), usually followed by rescoring the top results with full-precision vectors.
Common mistake

t-SNE (and largely UMAP) is for visualisation, not for shrinking search vectors. It distorts distances and can't consistently map new queries into the same space.

Infrastructure and parallelism

  • GPU FAISS and batched queries.
  • Sharding an index across machines; replicas for throughput.
  • Metadata pre-filtering to shrink the search space; caching frequent queries.
  • Disk-based indexes (DiskANN) or memory-mapped files for billion-scale data.
  • Composite indexes: IVF with an HNSW coarse quantiser, IVF-PQ, HNSW-PQ.

Hybrid search (dense + BM25) is covered in section 54. For dense retrieval use sentence-embedding models (SBERT, E5, BGE): raw BERT embeddings are poor for similarity. Learned sparse retrieval (SPLADE) sits between keyword and dense search.

Further reading: Pinecone, Faiss: The Missing Manual.

56Graph RAG and multimodal RAG

Knowledge-graph RAG

A knowledge graph stores entities as nodes and relationships as edges, which helps with questions that chain facts together (“where is Alice's employer based?”).

Figure 84. Building the graph (left) and answering with it (right). The example graph and query are illustrative.
  1. Extract entities and relations from text with an LLM or NER tools (e.g. NuExtract, Haystack, or LangChain's LLMGraphTransformer; LlamaIndex's equivalent is PropertyGraphIndex).
  2. Write them to the graph with Cypher, Neo4j's query language (MERGE, CREATE), which is also used for reading.
  3. Query at answer time: text-to-Cypher (Lang2Cypher) has an LLM write a Cypher query from the question; the results are turned back into text (Cypher2Language) and passed to the LLM.
  • Safety: generated queries can be invalid or harmful. Put the graph schema in the prompt, use a read-only connection, and validate queries before running them.
  • NetworkX vs Neo4j: NetworkX builds graphs in memory (analysis, prototypes); Neo4j is a persistent graph database.
  • Microsoft GraphRAG summarises clusters of related entities (“communities”), so it can answer broad questions such as “what are the main themes?” that chunk retrieval handles poorly.

Multimodal RAG with ColPali

Instead of OCR and layout parsing, ColPali retrieves page images directly from a text query. Byaldi (Answer.AI) wraps ColPali-style models in a simple API.

  • Each page image is embedded by a vision-language model (PaliGemma) into one vector per image patch, about 1,000 vectors of dimension 128 per page.
  • The text query gets one vector per token.
  • Late interaction (MaxSim, from ColBERT): each query token finds its best-matching patch, and the matches are summed.
\text{score}(q,d) = \sum_{i\,\in\,\text{query tokens}}\ \max_{j\,\in\,\text{page patches}}\ q_i\cdot d_j
Figure 85. MaxSim on a toy page with illustrative similarities. Each query token picks its best patch (outlined); the page score is the sum.
  • Strengths: tables, charts, scans and layout work without parsing. ColQwen2 is the same idea built on Qwen2-VL.
  • Cost: ~1,000 vectors per page makes a large index. Mitigations: token pooling, binary or low-bit quantisation. The database must support multi-vector search (Vespa, Qdrant multivectors, or Byaldi's in-memory index).
  • Reranker: MonoQwen2-VL-v0.1 (LightOn) reads the query and a page image together and scores relevance from the probability of a “True” token. Images are sent base64-encoded; keep the top n < k pages.
  • Reader: a vision-language model (VLM) such as Qwen2-VL-7B-Instruct answers from the query and the retrieved page images. Not “VLLM”: vLLM is a separate inference server.
  • min_pixels / max_pixels: Qwen2-VL handles any resolution at roughly one visual token per 28×28-pixel patch. More pixels mean more tokens, memory and latency; these settings cap it.
  • Alternative: OCR the documents and caption their images, then use normal text RAG. Cheaper and easier to debug, but loses layout, charts and visual detail.
Text RAGMultimodal (ColPali) RAG
IndexingParse → chunk → embed textScreenshot each page → embed patches
Vectors1 per chunk~1,000 per page
StrengthsCheap, mature toolingTables, charts, scans, layout
ReaderLLMVLM

Further reading: Faysse et al., ColPali: Efficient Document Retrieval with Vision Language Models (2024).

57Putting it together for LLMs

  • Scale changes the picture. LLMs are hugely over-parameterised yet generalise well (double descent). Huge deduplicated datasets, about one epoch of pretraining, and the implicit regularisation of SGD keep variance in check.
  • Typical architecture: decoder-only Transformer, pre-LN with RMSNorm, RoPE positions, GQA or MLA attention, and often mixture-of-experts feed-forward layers (Mixtral, DeepSeek-V3).
  • Standard training recipe: AdamW with weight decay, linear warmup then cosine decay, gradient clipping (often max_norm = 1.0), mixed precision, and 3D/5D parallelism with ZeRO or FSDP.
  • Overfitting controls: weight decay, data deduplication, dropout (often turned off in large-scale pretraining), and for fine-tuning: LoRA, low learning rates, early stopping.
  • Where variance shows up: fine-tuning on small datasets (overfitting, catastrophic forgetting), verbatim memorisation of training text, and output variability from sampling temperature and prompt wording.
  • Underfitting: a model too small or under-trained for the task. Fix with a larger model, more pretraining (scaling laws), or fine-tuning on the target task.
Two meanings of “bias”

Statistical bias is the bias–variance concept on this page.

Social bias means stereotypes or skewed associations learned from training data. It is a data and alignment problem, not part of the bias–variance trade-off.

Part IX

Deployment & operations

Running ML and LLM systems in production: the MLOps lifecycle, serving, Kubernetes, CI/CD, monitoring, drift and governance.

58The MLOps lifecycle

MLOps is a set of practices that streamline the whole machine-learning lifecycle, from data and development to deployment, monitoring and maintenance. It is a loop, not a line: what monitoring finds feeds back into data and retraining.

Figure 86. The MLOps loop, with typical tools per stage and the section that covers each.
StageDoesTools
Data managementCollect, store, preprocess and version datasetsDVC, lakeFS (data versioning)
Model developmentTrack experiments, ensure reproducibilityMLflow, Weights & Biases
CI/CDAutomate testing, training pipelines and model registriesGitHub Actions, MLflow registry
Model servingAPIs, batch jobs, streaming; containersFastAPI, vLLM, Kubernetes
Monitoring & observabilityAccuracy, latency, drift, system metricsPrometheus, Grafana, Evidently, Langfuse
Governance / responsible AICompliance, fairness, explainabilityWhyLabs, Fiddler, model cards
  • Reproducibility runs through every stage: version data, code, dependencies and environments; use containers and automated pipelines; document every step and configuration.

59Deploying LLMs in production

Production work runs along three axes: making each request fast, building infrastructure that scales, and operating the system safely. The first axis is covered in earlier sections; this one links to them and adds the rest.

Figure 87. The three axes of LLM deployment and what belongs on each.

Axis 1: inference latency

  • Smaller models: quantization (INT8/INT4/FP8), pruning, distillation. All are lossy: “minimal accuracy loss”, not “preserved accuracy”, so measure quality on your task. For inference, run in FP16/BF16 rather than FP32; “mixed precision” is a training term.
  • Fast generation: speculative decoding and multi-token prediction, both lossless when the target verifies the draft.
  • GPU optimisation: MQA/GQA shrink the KV cache (more requests fit, less memory traffic per step); FlashAttention and PagedAttention (section 50).

Batching: dynamic vs continuous

Dynamic batchingContinuous batching
GroupsRequests arriving within a short time windowRequests at every generation step
A slot frees whenThe whole batch finishesAny single request finishes
Typical inTriton, classic model serversvLLM, TGI, SGLang
Best forFixed-size outputs (classification, embeddings)LLM generation

Both raise throughput, not per-token speed; per-request latency can rise slightly. See the batching figure.

Axis 2: infrastructure

Strategy at inferenceWhat it doesEffect
Tensor parallelismSplits each layer across GPUs in one nodeLower latency for big models
Pipeline parallelismSplits layers across GPUs or nodesFits huge models; adds per-request latency
Replicas (“data parallel”)Full copies behind a load balancerMore throughput; no latency change
Expert parallelismSpreads MoE expertsNeeded for large MoE models

Replicas are not model parallelism, and ZeRO/FSDP are training techniques that don't apply here.

Figure 88. A typical serving stack. Each replica is a tensor-parallel group; the autoscaler adds replicas based on queue depth or KV-cache usage.
  • GPU choice: memory ≈ bytes per weight × parameters, plus 20–30% headroom for the KV cache. A 7B model in BF16 needs about 14 GB for weights alone.
  • Cloud, on-premise or serverless: cloud for fast scaling and managed services; on-premise for data control at a higher up-front cost; serverless GPUs and managed APIs for no idle cost, with less control and cold starts.
  • Autoscale on the right signal: queue depth or KV-cache usage, not CPU. Watch cold starts: loading tens of GB of weights takes minutes. Fast NVMe storage, safetensors and cached weights shorten it.
  • Containers and orchestration: Docker for consistent images, Kubernetes to schedule and scale them, with serving layers such as KServe, Ray Serve, or NVIDIA Triton / NIM.
  • Distributed architecture: several machines and regions remove single points of failure.

Axis 3: deployment, testing and monitoring

AreaMetrics
LatencyTTFT, TPOT, p50 / p95 / p99 end-to-end latency
ThroughputTokens/s, requests/s, queue length
ResourcesGPU utilisation, KV-cache usage, memory, cost per 1M tokens
ReliabilityError rate, timeouts, rate-limit hits
QualityUser feedback, LLM-as-judge scores, hallucination and refusal rates, input drift
  • Tools: Prometheus and Grafana for system metrics; LLM observability (Langfuse, LangSmith, Arize Phoenix) to trace prompts, responses and RAG steps.
  • Benchmarking: load-test against SLOs (e.g. “p95 TTFT < 500 ms at 50 concurrent users”) with vLLM's benchmark scripts, NVIDIA GenAI-Perf or Locust, using realistic prompt and output lengths.
  • Infrastructure as code and CI/CD: Terraform provisions infrastructure; Kubernetes manifests or Helm charts describe deployments; a model registry (MLflow, Hugging Face Hub) versions models.
Figure 89. Releasing a new model. A shadow phase first sends real traffic to the new model without showing its answers; the canary then grows its share in steps, each gated on latency, error and quality metrics. The dashed line shows an automatic rollback. Percentages are illustrative.

Security, caching and cost

  • Security and safety: authentication, rate limiting, input/output guardrails, PII filtering, prompt-injection defences.
  • Caching: exact and semantic response caches, plus prefix caching.
  • Cost: the smallest model that meets quality; a router that sends easy queries to a cheaper model; batch processing for offline jobs.

60Batch and real-time serving

Model serving turns a trained model into a network service that other applications can call, typically over a REST API.

ModeLatencyExampleCost
BatchHoursNightly reports, bulk taggingCheapest; LLM batch APIs are often about 50% off
Streaming / near-real-timeSecondsEvent pipelines (Kafka)Medium
Real-time (online)Milliseconds to secondsChat, fraud detectionHighest: always-on capacity

Building a real-time LLM endpoint

  1. Reduce latency first: model size, fast generation, GPU optimisation (section 50), e.g. serve with vLLM.
  2. Serving layer: an API framework such as FastAPI.
  3. Async handlers so one worker serves many users.
  4. Stream tokens so users see text as it is generated.
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
from openai import AsyncOpenAI          # async client: doesn't block the event loop

app, client = FastAPI(), AsyncOpenAI()

@app.post("/chat")
async def chat(msg: str):
    async def tokens():
        stream = await client.chat.completions.create(
            model="my-llm", messages=[{"role": "user", "content": msg}], stream=True)
        async for chunk in stream:
            yield f"data: {chunk.choices[0].delta.content or ''}\n\n"
    return StreamingResponse(tokens(), media_type="text/event-stream")
  • Async isn't batching: while one request waits on I/O (the LLM call), the same worker serves others. Batching requests onto the GPU is the model server's job (continuous batching).
  • await needs the async client; calling a sync client inside async def blocks every user. A plain def endpoint runs in FastAPI's thread pool instead.
  • Streaming: one-way token streams usually use Server-Sent Events (text/event-stream), as the OpenAI API does: simple and plain HTTP. Use WebSockets for genuinely two-way connections such as voice or collaborative apps.
  • Chat history: append the user's message, stream the answer, then save the full reply to the history.
Figure 90. Three requests on one worker, each mostly waiting on the LLM. Blocking code serves them in turn; async code overlaps the waiting. Durations are illustrative.

Scaling up and out

Figure 91. Vertical scaling makes one machine bigger; horizontal scaling adds machines.
  • Vertical: a bigger GPU or more memory. Needed when the model doesn't fit at all.
  • Horizontal: more replicas behind a load balancer. Adds throughput and removes single points of failure.
  • LLMs usually need both: a big enough GPU per replica, then enough replicas.
  • Microservices: split the system (UI, retrieval, model, guardrails) into services that scale independently (section 62). Data and model parallelism for training are covered in section 44.

61Model serving options

Model serving bridges development and production: it packages a trained model into a network-accessible service so other applications can request predictions, classifications or generated content.

ApproachTypeWhat it doesHostingArtifact storageWhy it's goodOpen source?
AWS SageMakerManaged cloud platformFully managed ML/LLM deployment: hosting, scaling, monitoringAWS-managed endpoints on GPU/CPUAmazon S3Enterprise-ready autoscaling and monitoring; integrates with the AWS ecosystemNo
Google Vertex AIManaged cloud platformDeploys ML/LLM models with real-time or batch endpoints; integrated pipelines and monitoringGCP-managed endpoints (containers on GPU/TPU/CPU)Google Cloud StorageEasy scaling; strong MLOps pipelines; good for Google Cloud usersNo
Microsoft Azure MLManaged cloud platformReal-time and batch endpoints; full ML lifecycle supportAzure endpoints (AKS-Kubernetes or managed)Azure Blob StorageEnterprise-ready autoscaling and monitoring; integrates with Microsoft toolingNo
vLLMSelf-managed, LLM-optimised serverHigh-throughput LLM inference: PagedAttention, continuous batching, token streamingYour GPU servers or Kubernetes podsHugging Face Hub, model registry or object storageFree; lowest cost per token at scale; you pay only for GPUs and run the infrastructureYes

More broadly:

TypeOptionsTrade-off
Managed platformsAWS SageMaker, Google Vertex AI, Azure ML; hosted APIs (Bedrock, Together)Little operations work; less control, higher cost per token
Self-hosted LLM enginesvLLM, TGI, SGLangFull control, lowest cost per token at scale; you run the infrastructure
General serving frameworksTriton, Ray Serve, BentoML, KServeMulti-model, multi-framework serving on your own cluster

For self-hosting on your own cluster, see section 62; for how vLLM works inside, see section 49.

62Serving on Kubernetes

A common path from notebook to production: wrap the model in a Python app, give it a Gradio interface, package it in a Docker container, and run it on Kubernetes (K8s), which handles deployment, scaling and recovery.

Figure 92. From inference code to a monitored service.

Gradio

A Python library that turns any function into an interactive web demo:

import gradio as gr
demo = gr.Interface(fn=greet, inputs=["text", "slider"], outputs=["text"])
demo.launch()
  • Ideal for demos and internal tools; Streamlit is an alternative, and Hugging Face Spaces hosts them for free.
  • For a public, high-traffic product, put the model behind an API server (vLLM's OpenAI-compatible server, or FastAPI) and use Gradio or a web app as a thin client.
  • Gradio's queue and sessions are stateful: with several replicas, enable sticky sessions at the load balancer.

Separate the UI from the model

If the model runs inside the Gradio process, every UI pod loads its own copy onto a GPU, wasting expensive GPUs on an idle interface.

Figure 93. UI pods on cheap CPU nodes, model pods on GPU nodes, each scaled on its own signal. Weights come from a volume instead of being baked into the image.
PodsRunsHardwareScales on
UIGradioCPU, cheapActive users
Model servervLLM / TGIGPUQueue length, KV-cache usage

Kubernetes building blocks

  • Pod: one or more containers scheduled together.
  • Deployment: keeps N identical pods (replicas) running and replaces failed ones; rolling updates and rollbacks.
  • Service: a stable address that load-balances across the pods.
  • Ingress / Gateway: exposes the app outside the cluster, with TLS and routing.
  • Containers provide most of the consistency across environments; Kubernetes adds declarative config (YAML) that keeps environments alike.
apiVersion: apps/v1
kind: Deployment
metadata: { name: llm-server }
spec:
  replicas: 2
  template:
    spec:
      containers:
      - name: vllm
        image: vllm/vllm-openai:<version>
        args: ["--model", "/models/my-llm"]
        resources:
          limits: { nvidia.com/gpu: 1 }       # needs the NVIDIA device plugin
        readinessProbe:
          httpGet: { path: /health, port: 8000 }
        volumeMounts: [{ name: weights, mountPath: /models }]

Abridged example. A Service then points at these pods, and an Ingress exposes the UI.

  • GPUs: install the NVIDIA device plugin (or GPU Operator), request nvidia.com/gpu, and use node selectors or taints so GPU nodes only run GPU work.
  • Model weights: mount them from a persistent volume or object storage, or download and cache at startup. Baking tens of GB into the image makes every deploy slow.
  • Health checks: a startup/readiness probe keeps traffic away until the model has loaded; a liveness probe restarts a hung pod.

Autoscaling

Figure 94. Simulated traffic spike. GPU inference keeps CPU low, so a CPU-based autoscaler never reacts; a queue-based one adds replicas as requests wait. Values are illustrative.
  • The default Horizontal Pod Autoscaler (HPA) scales on CPU or memory, which barely move for GPU inference.
  • Scale on custom metrics instead: requests waiting, requests in flight or KV-cache usage (vLLM exposes them at /metrics), fed in through KEDA or the Prometheus Adapter.
  • The Cluster Autoscaler (or Karpenter) adds GPU nodes when pods can't be scheduled. Expect minutes of cold start: node boot, image pull, model load.

Monitoring and logging

  • Metrics Server only provides basic CPU/memory for kubectl top and the HPA; it isn't a monitoring system.
  • Prometheus + Grafana for metrics; the DCGM exporter for GPU utilisation, memory and temperature; vLLM's own TTFT, tokens/s and KV-cache metrics.
  • Loki or ELK for logs; Langfuse, LangSmith or Phoenix to trace prompts and responses (see the metrics table).

Testing in production

StrategyAffects users?Use caseRollbackWatch
ShadowNoRun a new model on live traffic, answers hiddenTrivialAccuracy, latency, drift
CanaryYes, small shareGradual rolloutEasyErrors, latency, quality
Blue-greenYes, all at onceTwo full environments; switch traffic instantlyInstant (switch back)Everything; needs 2× capacity
A/B testYesCompare two models head to headEasyBusiness KPIs; needs statistical significance
Feature flagsYes, chosen usersTurn features on per user or groupInstantPer-flag metrics

A typical order: shadow → canary → full rollout (see the canary figure), with A/B tests for product decisions.

63CI/CD for ML

Continuous integration (CI) tests every change automatically; continuous deployment (CD) ships changes that pass. For ML, “every change” includes code, data and models, so the pipeline also trains, evaluates and versions models.

Figure 95. CI runs on every pull request and blocks the merge if any check fails; CD runs only after CI passes on main.

Triggers

WorkflowTriggerPurpose
CIpull_request (and push to main)Test and evaluate before a change is merged
CDworkflow_run after CI succeeds on main, or a release tagDeploy only code and models that passed

Triggering CI only on push to main means a bad change is already merged before anyone sees the results.

Building the CI pipeline

  • Makefile: one set of commands (make install, make train, make eval) for both laptops and CI, so “works on my machine” problems surface early. Useful, not required.
  • Environment: pick a runner (ubuntu-latest), set up Python, pin dependency versions and cache installs. Hosted runners have no GPU: use a self-hosted GPU runner or have CI launch a cloud or Kubernetes job (CML can provision cloud runners).
  • CML (Continuous Machine Learning, by Iterative) posts metrics, plots and confusion matrices as a comment on the pull request (cml comment create report.md). Any email comes from GitHub notifications.
name: ci
on:
  pull_request:
  push: { branches: [main] }
jobs:
  train-eval:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: "3.11", cache: pip }
      - uses: iterative/setup-cml@v2
      - run: make install lint test
      - run: make train eval          # writes metrics.json + report.md
      - run: python check_gate.py     # exit 1 if worse than baseline
      - env: { REPO_TOKEN: "${{ secrets.GITHUB_TOKEN }}" }
        run: cml comment create report.md

Abridged example; action versions are illustrative.

ML-specific checks

CheckExample
Code qualityFormatting and linting (black, ruff), unit tests
Data validationSchema, missing values, distribution shift (Great Expectations, pandera)
ReproducibilityFixed seeds, pinned versions, data version recorded
Quality gateFail the build if the new model is worse than the current one: accuracy below baseline, latency above the SLO
LLM evaluationA fixed eval set scored automatically or by an LLM judge; regression tests on known prompts
Figure 96. A quality gate on five pull requests: each new model must match the production model's score within a tolerance and stay under the latency limit. Scores are illustrative.

Versioning models and data

  • Don't commit model files to git: they bloat the repository, and GitHub rejects files over 100 MB.
  • Don't let CI push straight to main: it skips review and can retrigger the workflow in a loop. If CI must change files, open a pull request from a bot branch.
  • Version data and models with DVC, Git LFS, the MLflow model registry or the Hugging Face Hub. Tag the code commit (v1.3.0) and record the matching model version.

Building the CD pipeline

  1. Fetch the trained model (CI artifact or registry).
  2. Upload it to the model registry or Hugging Face Hub.
  3. Build and push a Docker image.
  4. Deploy to Hugging Face Spaces (Gradio) or Kubernetes, releasing via shadow → canary → full rollout with automatic rollback (section 59).
  • Authentication: store tokens such as HF_TOKEN as GitHub Secrets, never in code; for cloud providers prefer OIDC to long-lived keys.

MLOps maturity levels

LevelWhat's automated
0Nothing: manual notebooks, manual deploys
1Continuous training (CT): retraining triggered by new data or drift
2Full CI/CD/CT: code, data and model pipelines all tested and deployed automatically

ML needs continuous training because a model can degrade when the data changes, even if the code doesn't (Google Cloud, MLOps: continuous delivery and automation pipelines in machine learning). Further reading: DataCamp, CI/CD for Machine Learning.

64Drift and model monitoring

A deployed model can get worse without any code change, because the world it sees changes. Labelled “golden” data is rarely available in production, so monitoring relies on proxy signals.

DriftWhat changesSignal without labels
Data (covariate) driftInputs: new topics, languages, prompt lengthsEmbedding-distribution shift; KS test on numeric features
Concept driftThe right answer for the same inputNeeds labels or a judge: user feedback, LLM-as-judge
Prediction driftOutput distributionOutput length, refusal rate, sentiment
Figure 97. Cosine similarity of each input's embedding to the baseline centroid, simulated for two periods. The shift is measured with a two-sample Kolmogorov–Smirnov statistic (largest gap between the cumulative distributions), computed from the samples.
  • Embedding-based detection: compare embeddings of current inputs and outputs with a baseline; a falling similarity suggests a shift in meaning. For full embeddings, use multivariate tests (MMD) or a classifier trained to tell old inputs from new.
  • Statistical tests: the KS test compares one numeric feature at a time (e.g. prompt length) against a baseline.
  • Perplexity: rising perplexity on new inputs means they are unlike the training data (data drift). It doesn't directly measure answer quality.
  • LLM-as-judge scores thousands of outputs quickly; calibrate it against a sample of human labels first, since judges have biases such as favouring longer answers.
  • User feedback: explicit ratings (thumbs up/down) and implicit signals (edits, retries, abandoned sessions).
  • Human in the loop: experts periodically review a sample of outputs.

Monitoring tools

NeedTools
System metrics (latency, throughput, CPU/GPU, errors)Prometheus
Dashboards over metrics, databases and other sourcesGrafana
Model monitoring (drift, quality)Evidently, WhyLabs, Arize, Fiddler
LLM tracing (prompts, responses, RAG steps)Langfuse, LangSmith, Arize Phoenix
Experiment tracking and model registryMLflow (not a live monitoring tool)

65Versioning, rollbacks and governance

Model versioning

Track, reproduce and roll back models safely as they evolve. Version every artifact of the pipeline:

  • Model weights, training data version, preprocessing and training code, hyperparameters and configuration, metrics, and the deployment environment.
  • Prompts and RAG indexes too: a prompt change can break behaviour as badly as a model change.
  • A model registry (e.g. MLflow) stores versions; aliases such as “champion” and “challenger” point at them, so every deployment uses a specific registered version.
  • Containers and CI/CD make each version reproducible and tested.

Rollbacks

  • Revert to the previous stable version when a new one causes errors or degradation; with aliases, rolling back means moving the alias back.
  • Keep the previous version warm (blue-green) for instant switching; trigger rollback automatically on metric breaches (canary figure).
  • Check the new version is compatible with the current data schema, so rolling back doesn't break consumers.

Sensitive data

  • Encrypt data at rest and in transit; strict access control; anonymise or pseudonymise personal identifiers.
  • Redact PII before sending prompts to third-party APIs, and check the provider's data-retention terms.
  • Logs are sensitive: stored prompts and responses contain user data and need retention limits and access control.
  • Right to erasure (GDPR): removing a person's data from a trained model is hard; keep personal data out of training, or be ready to retrain.
  • Regulations: GDPR, HIPAA, and the EU AI Act for high-risk uses.

Interpretability vs explainability

InterpretabilityExplainability
WhatThe model is understandable by designAfter-the-fact explanations of a black-box model
ExamplesLinear models, small decision treesSHAP, LIME, feature attributions, saliency maps
ScopeUsually the whole model's logicUsually individual predictions (why this output for this input)

The terms are often used loosely, so define them when you use them.

Part X

Agents & tool use

How LLMs reach tools and data, how agents remember, and how agents are built on top.

66Model Context Protocol (MCP)

MCP is an open protocol that standardises how AI applications connect to tools and data. Instead of a custom connector for every pair of app and system, each app implements an MCP client and each system an MCP server.

Figure 98. Without a standard, M apps and N systems need M × N connectors (here 3 × 4 = 12); with MCP they need M + N (here 3 + 4 = 7).

Host, client and server

  • Host: the AI application (an IDE or chat app). It runs the LLM and decides what to do with tool results.
  • Client: a component inside the host, with one client per server (a 1:1 connection). A host connected to three servers runs three clients.
  • Server: a program that exposes capabilities and executes them (an API call, a database query).
  • Protocol: messages are JSON-RPC 2.0. A session starts with an initialize handshake where both sides agree on capabilities; the client then calls tools/list to discover tools and tools/call to run one.
Figure 99. One host, three servers, three clients. Local servers use stdio; the remote server uses Streamable HTTP.

Transports

TransportServer runsTypical use
stdioOn the same machine, as a subprocess of the hostLocal tools: files, git, local databases
Streamable HTTPAnywhere, over the networkRemote or shared services, multi-user
Common mistake

The transport has nothing to do with one server versus many: a host can connect to many servers over either transport. The original HTTP + SSE transport was replaced by Streamable HTTP in the 2025 specification, which can still stream using SSE inside it.

A tool call, step by step

Figure 100. The example from the notes as a sequence. The returned value is illustrative.
Key point

The LLM never talks to the server directly. It only proposes a tool call; the host and client execute it. That is also where the host can ask the user for approval.

Server primitives

PrimitiveControlled byWhat it isExample
ToolsThe modelFunctions the LLM can callget_earnings(ticker)
ResourcesThe applicationRead-only data the host can attach as contextFiles, database rows
PromptsThe userReusable prompt templates“/summarise-report”

Servers can also ask things of the client: sampling (borrow the host's LLM) and elicitation (ask the user for input).

MCP vs function calling

  • Function calling is a model-API feature: the model outputs a structured call to a function you described.
  • MCP standardises how tools are discovered, described and served across apps. MCP tools usually reach the model through function calling.

One server or many

AspectMultiple MCP serversSingle MCP server
ComplexityDistributed; each server easier to reason aboutCentralised; harder to manage as it grows
SecurityIsolated boundaries, smaller “blast radius”Single point of vulnerability for all tools
ScalabilityIndependent scaling per domainAll-or-nothing scaling, possible bottlenecks
MaintenanceModular updates, easier debuggingSystem-wide updates, harder debugging
OperationsMore processes and connections; extra latency per hop; possible tool-name clashesOne thing to deploy and monitor

Too many tools hurts the model, whatever the number of servers: every tool description takes context, and with dozens of tools the LLM picks the wrong one more often. Expose only the tools a task needs, write clear and distinct descriptions, or select tools dynamically.

Security

  • Prompt injection through tool results: a web page or email returned by a tool can contain instructions aimed at the LLM.
  • Tool poisoning: a malicious server hides instructions in its tool descriptions.
  • Mitigations: install only trusted servers; give each least privilege (read-only where possible); require user approval for sensitive actions; use OAuth for remote HTTP servers; log every tool call (section 65).

Further reading: modelcontextprotocol.io, the specification and documentation.

67Agent memory

An LLM forgets everything between calls. Agents add memory around it: short-term memory holds the immediate context of one interaction; long-term memory persists knowledge across sessions, tasks and time. The taxonomy follows cognitive science and the CoALA framework (Sumers et al., 2023).

Figure 101. For every LLM call, the orchestrator builds the context window from the three long-term memories, and writes new episodes back afterwards.

Short-term (working) memory

The context window itself: system prompt, available tools, retrieved context, and the reasoning-and-action history (scratchpad), assembled by the orchestrator for each call.

  • Limit: context length and cost. As a conversation grows, trim old turns or keep a sliding window, summarise earlier turns, or move details to long-term memory and retrieve them when needed.

Long-term memory

TypeStoresExampleTypical storage
EpisodicWhat happened: past interactions, actions, outcomes“Last week the user asked for a refund; it was approved”Logs, vector DB, graph DB
SemanticFacts about the world and the user“The user lives in London and prefers short answers”; company docsVector DB (RAG), knowledge graph
ProceduralHow to do thingsSystem prompt, tool definitions, workflows, guardrailsGit, prompt and tool registries; also the model weights
  • Episodic: after each action, the application stores what happened. Retrieving similar past episodes and showing them as examples of what worked is a common few-shot technique.
  • Semantic: a private knowledge base plus grounding context is exactly RAG. Live web search is a tool, not memory.
  • Procedural: the agent's “how-to”: update it by editing prompts and tools, or by fine-tuning, which changes what the model itself knows how to do.

Writing and managing memory

Figure 102. The memory lifecycle. Consolidation turns many episodes into a few durable facts.
  • Hot path: the agent calls a save_memory tool during the conversation. Memory is immediate, but each turn is slower.
  • Background: a separate job extracts memories after the conversation. Chat stays fast; memory lags.
  • Consolidation: an LLM “reflection” step turns episodes into semantic facts, e.g. three conversations about Python errors become “the user codes in Python”.
  • Updating and forgetting: new facts can conflict with old ones (“moved to Paris”), so memories need update and delete, not just append; unused memories should decay or be pruned.

Retrieving the right memories

Relevance alone isn't enough. Generative Agents (Park et al., 2023) combines three signals:

\text{score}(m) = \alpha\cdot\text{recency}(m) + \beta\cdot\text{importance}(m) + \gamma\cdot\text{relevance}(m,q), \qquad \text{recency}(m) = 0.995^{\,\text{hours since last access}}
Each term is scaled to [0, 1]. Importance is rated by the LLM when the memory is written; relevance is the cosine similarity between the memory and the query q.
Figure 103. Scoring four memories for the query “book a restaurant tonight” with α = β = γ = 1. Scores are computed from the formula; the inputs are illustrative.

Risks

  • Stale or wrong memories keep misleading the agent until corrected.
  • Memory poisoning: a prompt injection that gets saved affects every future session. Validate what gets written (section 66).
  • Privacy: memories are personal data. Let users view and delete them; the right to erasure applies (section 65).
  • Cost: every retrieval adds latency and context tokens.

Tools

  • LangGraph: checkpoints for short-term memory, a store for long-term memory.
  • Mem0; Zep (a temporal knowledge graph that tracks when facts were true).
  • Letta (formerly MemGPT): manages memory like an operating system, paging information between the context window and external storage.

Further reading: Sumers et al., Cognitive Architectures for Language Agents (2023); Park et al., Generative Agents (2023).

68Check yourself

Try to answer before opening each one.

Statistics foundations
Parameter vs statistic?

A parameter describes the population (μ, σ); a statistic is computed from a sample (x̄, s) and estimates it.

Why can't you say 20 °C is twice as hot as 10 °C?

Celsius is an interval scale: its zero is arbitrary, so ratios are meaningless. Ratio scales (kg, cm) have a true zero.

Why does sample variance divide by n − 1?

Bessel's correction: deviations from the sample mean are slightly too small, so dividing by n underestimates σ²; n − 1 makes the estimate unbiased.

A value has z = −2. What does that mean?

It lies two standard deviations below the mean; for normal data only about 2.3% of values are lower.

PMF vs PDF?

A PMF gives probabilities of discrete values; a PDF is a density for continuous values, and probabilities are areas under it.

What does the central limit theorem say?

The mean of a large enough sample is approximately normal around μ with standard error σ/√n, whatever the population's shape.

p = 0.03: is there a 3% chance the null hypothesis is true?

No. It is the probability of data this extreme if H₀ were true. It says nothing about effect size either.

Comparing average scores across four prompt variants: which test?

One-way ANOVA (or repeated-measures ANOVA if the same inputs are scored under every prompt), followed by corrected pairwise tests.

Pearson r ≈ 0: does that mean no relationship?

Only no linear relationship. A U-shaped relationship can have r ≈ 0; plot the data.

ML foundations
Positive (right) skew: is the mean above or below the median?

Above. The long right tail pulls the mean up; the median and mode are more robust.

Why fit the scaler on the training set only?

Fitting on all the data leaks information about the validation and test sets into training.

Why is PCA not a feature-importance method?

It builds new features (components) from combinations of the old ones, ordered by variance, not by usefulness for predicting the label.

Under what noise assumption is minimising MSE the same as MLE?

Gaussian noise: y = f(x) + ε, ε ∼ N(0, σ²).

Which prior gives L1 regularisation in MAP estimation?

A Laplace prior. A Gaussian prior gives L2.

Logistic regression gradient for w?

∂J/∂w = (1/m) Σ (ŷ⁽ⁱ⁾ − y⁽ⁱ⁾) x⁽ⁱ⁾.

When can R² be negative?

On test data, when the model is worse than always predicting the mean.

TP = 40, FP = 5, FN = 10: precision and recall?

Precision = 40/45 ≈ 0.89; recall = 40/50 = 0.80.

Are inertia and silhouette classification metrics?

No, they are clustering metrics and need no labels. Inertia measures compactness; silhouette measures separation.

Does L2 regularisation fix unscaled features?

No. It penalises all weights equally, so it is unfair to small-scale features. Scale first, then regularise.

What happens to unregularised logistic regression on linearly separable data?

The weights grow without limit: the loss keeps decreasing as the boundary sharpens, so the MLE doesn't exist.

What is data contamination?

Test or benchmark data leaking into the training set, which inflates evaluation scores.

Why does Cleanlab need out-of-sample predictions?

A model that trained on an example has memorised its label, so it can't flag that label as wrong. Cross-validation gives out-of-sample predictions.

Which examples does uncertainty sampling pick?

Those the model is least sure about, typically the ones closest to the decision boundary.

Main risk of filtering synthetic data with a learned reward model?

Reward hacking: the policy exploits the reward model's flaws. Verifiable checks (unit tests, exact answers) are more reliable.

Give an example of MNAR data.

High earners leaving income blank: whether it's missing depends on the missing value itself.

Why resample only after splitting?

Otherwise copies of the same minority example end up in both train and test, inflating scores.

About what fraction of distinct points does a bootstrap sample contain?

1 − 1/e ≈ 63.2%. The other 36.8% are out-of-bag.

Generalisation
Training error 2%, validation error 25%. What's wrong, and what are two fixes?

Overfitting (high variance). Fixes: more data, augmentation, L2/weight decay, dropout, early stopping, a smaller model.

Training error 30%, validation error 32%. What's wrong?

Underfitting (high bias). Use a bigger model, train longer, add features, reduce regularisation. More data won't help much.

What happens when λ in L2 regularisation is very large?

Weights are pushed close to zero and the model underfits. Training still converges, to a too-simple solution.

L1 vs L2: which produces sparse weights?

L1. It drives some weights to exactly zero. L2 shrinks all weights but rarely makes them exactly zero.

Is k-fold cross-validation an ensemble method?

No. It is for evaluation and model selection. Each fold holds out 1/k of the data.

Bagging or boosting for a high-variance model?

Bagging, which averages models trained on bootstrap samples and reduces variance. Boosting mainly reduces bias.

Where does the peak in double descent occur?

At the interpolation threshold, where the model can just fit the training data exactly (roughly, parameters ≈ data points).

Why can early stopping be a problem for grokking?

Validation accuracy stays flat for a long time before jumping. Stopping on a plateau ends training before generalisation appears.

Does LayerNorm mainly prevent overfitting?

No. It mainly stabilises training. BatchNorm has a mild regularising effect from batch noise; LayerNorm has very little.

Does shuffling make data normally distributed?

No. It ensures splits and mini-batches are representative. Reordering never changes the distribution.

Optimisation
What is the key property of a convex loss?

Every local minimum is a global minimum.

Why are saddle points a bigger problem than local minima in deep networks?

In high dimensions they are far more common, and the gradient near them is tiny, so training slows to a crawl. Most local minima have similar, good loss values.

Why not initialise all weights to zero?

Every neuron in a layer would receive the same gradient and learn the same thing (no symmetry breaking).

What does "SGD" usually mean in deep learning?

Mini-batch SGD: gradients from a batch of examples, not a single one.

Why does momentum help in a ravine?

Gradient components that flip sign across the valley cancel out in the velocity, while the consistent component along the valley builds up.

Why is AdamW preferred over Adam with L2?

In Adam, the L2 term is divided by √v̂, so weights with large past gradients are decayed less. AdamW applies the decay separately, uniformly for every weight.

What does learning-rate warmup make small: the weights or the updates?

The updates. It starts with a small learning rate while gradients and Adam's moment estimates are unreliable.

max_norm = 1.0 and the gradient norm is 4. What happens?

The gradient is multiplied by 1/4. Its direction stays the same; its length becomes 1.

Generative models
Generative vs discriminative: which models p(y | x)?

Discriminative. Generative models learn p(x) or p(x, y) and can sample new data.

What do the two terms of the VAE loss do?

The reconstruction term makes the decoder rebuild x from z. The KL term keeps q_φ(z|x) close to the prior N(0, I), so the latent space is smooth and can be sampled.

Why does a VAE need the reparameterisation trick?

Sampling isn't differentiable. Writing z = μ + σ·ε with ε ∼ N(0, I) lets gradients flow through μ and σ.

When generating new data with a VAE, where does z come from?

From the prior N(0, I). The encoder is only used during training.

Mode collapse vs model collapse?

Mode collapse: a GAN generator produces only a few kinds of outputs. Model collapse: degradation from training on model-generated data.

Why must flow layers be invertible?

So the change-of-variables formula applies and the model can compute an exact log-likelihood.

What does a diffusion network usually predict?

The noise ε that was added to x₀ to make x_t, trained with ‖ε − ε_θ(x_t, t)‖².

Why are consistency models faster than diffusion models?

They learn to map any point on the noise-to-data trajectory straight to the clean sample, so they need one or a few steps instead of many.

Transformers & attention
Is “self-attention” the same as “scaled dot-product attention”?

No. Scaled dot-product attention is the scoring formula. Self-attention means Q, K and V come from the same sequence; cross-attention uses the same formula with Q from one sequence and K, V from another.

Why divide by √d_k in attention?

Large dot products push the softmax into saturation, where gradients are tiny. Scaling keeps them in a healthy range.

In causal attention, how are future positions removed, and do rows still sum to 1?

Their scores are set to −∞ before the softmax, so their weights are 0. The softmax then spreads the weight over the remaining positions, so each row still sums to 1.

How are the outputs of the heads in multi-head attention combined?

They are concatenated and multiplied by an output projection W_O.

In cross-attention, where do Q, K and V come from?

Queries from the decoder; keys and values from the encoder's output.

What does RoPE make the attention score depend on?

The relative distance between the two tokens, because queries and keys are rotated by angles proportional to their positions.

Which family is BERT, and what is it good for?

Encoder-only, pretrained with masked language modelling. Good for classification, NER and embeddings, not generation.

32 query heads and 8 KV heads: how much smaller is the KV cache than MHA?

4× smaller (h/g = 32/8). Query heads are unchanged.

What does MLA cache instead of full keys and values?

A small compressed latent vector c_KV per token (plus a small RoPE key part). K and V are up-projected from it, or the up-projections are merged into W_Q and W_O.

Is FlashAttention an approximation?

No. It computes exact attention, just with fewer reads and writes to GPU memory.

What is the main advantage of SSMs like Mamba over attention?

Cost grows linearly with sequence length and memory per generated token is constant, versus O(n²) attention and a growing KV cache.

MoE: what scales with active parameters, and what with total parameters?

Compute per token scales with active parameters; memory scales with total parameters, because all experts must be loaded.

How are the outputs of the selected experts combined?

As a weighted sum, using the router's (usually renormalised) scores for the top-k experts.

Why use many small (fine-grained) experts instead of a few large ones?

Same compute, but vastly more possible expert combinations (8 of 64 ≈ 4.4 billion vs 2 of 16 = 120), allowing more specialised experts.

What does a shared expert do?

It is always active and learns common knowledge, so routed experts don't each have to relearn it.

Auxiliary loss vs expert capacity?

The auxiliary loss encourages the router to spread tokens evenly. Capacity is a hard per-expert limit; overflow tokens are dropped and pass through the residual connection.

Little VRAM and low throughput: dense or MoE?

Dense. An MoE must hold every expert in memory but only uses a few per token.

Training at scale
About how many bytes per parameter does mixed-precision training with Adam need?

About 16: BF16 weights (2) + BF16 gradients (2) + FP32 master weights (4) + Adam m (4) + Adam v (4), plus activations.

What does gradient checkpointing trade?

Compute for memory: fewer activations are stored, and the missing ones are recomputed in the backward pass (~30% extra compute for full recomputation).

Micro-batch 4, 8 accumulation steps, 16 data-parallel GPUs: what is the global batch?

4 × 8 × 16 = 512.

Why does FP16 training need loss scaling but BF16 doesn't?

FP16 has a small range (max 65,504, 5 exponent bits), so tiny gradients underflow to zero. BF16 has FP32's 8 exponent bits and range.

Does bitsandbytes provide mixed-precision training?

No. Mixed precision comes from autocast/AMP. bitsandbytes provides 8-bit optimizers and 4/8-bit quantization.

Does data parallelism reduce memory per GPU?

No. Every GPU holds the full model, gradients and optimizer states. ZeRO/FSDP is what shards them.

How do you shrink the pipeline bubble?

Use more micro-batches: bubble ≈ (p − 1)/m. Interleaved schedules help too.

Why keep tensor parallelism inside one node?

It communicates activations on every layer, so it needs the fast NVLink links inside a node.

Memory per GPU under ZeRO-3?

16Ψ/N: parameters, gradients and optimizer states are all split across the N data-parallel GPUs. PyTorch FSDP is essentially ZeRO-3.

Why is ZeRO-1 rather than ZeRO-3 combined with pipeline parallelism?

ZeRO-2/3 would have to communicate gradients or parameters for every micro-batch, which clashes with pipelining.

Which parallelism splits a long sequence across GPUs?

Context parallelism (e.g. ring attention). Sequence parallelism complements tensor parallelism for LayerNorm and dropout activations.

LLMs in practice
What does the KV cache save?

Recomputing keys and values of earlier tokens at every decoding step.

In the example tree, why does greedy search miss “The dog has”?

Greedy takes “nice” (0.5) over “dog” (0.4) at step 1, ending at 0.5 × 0.4 = 0.20; “dog has” scores 0.4 × 0.9 = 0.36.

Why does beam search sum log-probabilities?

Products of many small probabilities underflow; summing logs is numerically stable and preserves the ranking.

Why is length normalisation needed in beam search?

Every token adds a negative log-probability, so unnormalised scores favour short outputs.

What is top-k's main weakness, and how does top-p fix it?

A fixed k admits junk on peaked steps and cuts good options on flat ones; top-p keeps however many tokens are needed to reach probability p.

Temperature 2 vs 0.5: which gives more varied outputs?

T = 2. Temperatures above 1 flatten the distribution; below 1 sharpen it.

RAG or fine-tuning for adding frequently changing company knowledge?

RAG: re-index the documents instead of retraining, and the answers can cite sources. Fine-tuning suits style and behaviour.

What is the trade-off in chunk size?

Small chunks retrieve precisely but lose context; large chunks keep context but give noisier embeddings.

Is FAISS a vector database?

No, it is an in-memory similarity-search library without persistence, metadata filtering or access control.

Why add BM25 to vector search?

Vector search misses exact matches such as IDs, names and rare terms. Hybrid search merges both rankings, e.g. with reciprocal rank fusion.

What are the two levers for faster vector search?

Smaller vectors (quantisation, PCA) and a smaller search scope (IVF, HNSW, LSH).

Does raising nprobe in IVF cost memory or time?

Time, not memory: more cells are searched, so recall goes up and speed goes down.

A 128-dim float32 vector compressed with PQ (m = 8, 256 centroids): how many bytes?

8 bytes (one byte per subvector ID), down from 512: 64× smaller.

How does PQ compute distances quickly?

Asymmetric distance computation: a per-query table of distances from each query subvector to every centroid; each vector's distance is the sum of m lookups.

Why does HNSW use memory heavily?

It stores the full vectors plus every node's neighbour links on each layer.

Should t-SNE be used to shrink embeddings for search?

No. It is for visualisation, distorts distances and can't consistently map new queries. Use PCA, random projection or Matryoshka embeddings.

Bi-encoder vs cross-encoder: which reranks, and why?

The cross-encoder: it reads query and document together, so it is more accurate, but it needs one pass per pair, so it only runs on the top candidates.

What does “lost in the middle” mean for prompt building?

LLMs use the start and end of the context best, so put the most relevant chunks there.

How should text-to-Cypher queries be made safe?

Give the schema in the prompt, use a read-only connection, and validate generated queries before running them.

How does ColPali score a page?

Late interaction: for each query-token vector, take its maximum similarity over the page's patch vectors, then sum over tokens.

VLM or vLLM for answering from page images?

A VLM (vision-language model) such as Qwen2-VL. vLLM is an inference server.

What are the three families of test-time compute methods?

Parallel (best-of-N, self-consistency), sequential (self-refine, long chain-of-thought) and search against a verifier (beam search, DVTS).

What is the main weakness of self-refinement?

Without external feedback, models often can't fix their own reasoning errors and may turn correct answers into wrong ones.

Self-consistency: what does it need instead of a verifier?

Comparable final answers, so the most common one can be chosen by majority vote.

ORM vs PRM?

An outcome reward model scores only the final answer; a process reward model scores every step.

When does DVTS beat beam search?

At large N on easier problems, where beam search collapses onto similar solutions; DVTS keeps independent subtrees diverse.

Step scores 0.75, 0.91, 0.83, 0.99: min, prod and last?

0.75, ≈0.56 and 0.99.

Why does PagedAttention help best-of-N sampling?

Samples from the same prompt share the prompt's KV blocks, and blocks are allocated on demand, so little memory is wasted.

Speculative decoding: when is a draft token accepted for sure?

When the target gives it at least as much probability as the draft, q(x) ≥ p(x) (with p = draft, q = target). Otherwise it is accepted with probability q(x)/p(x).

After a rejection, what is sampled and what happens to later draft tokens?

A token from the normalised residual max(0, q − p); all later draft tokens are discarded.

Acceptance rate 0.8 and k = 4: expected tokens per target pass?

(1 − 0.8⁵)/(1 − 0.8) ≈ 3.4.

Does speculative decoding change the model's outputs?

No. The target model verifies every token, so the output distribution is unchanged; it is only faster.

Which generation phase is memory-bound, and which metric measures it?

Decoding: every step reads all weights and the KV cache to produce one token. Measured by TPOT (time per output token).

Does speeding up inference always cost quality?

No. KV caching, FlashAttention, torch.compile, speculative and prompt-lookup decoding, and batching are lossless. Quantization, pruning and distillation can cost quality.

Why does a static KV cache help torch.compile?

Compiled kernels need fixed tensor shapes; a growing cache would force recompilation.

Does self-speculative decoding lower output quality?

No. Early layers draft, but the full model verifies every token.

Batching vs tensor parallelism: which lowers per-request latency?

Tensor parallelism. Batching raises throughput but can make each request slightly slower.

What does FlashAttention avoid?

Writing the n × n attention matrix to slow GPU memory; it computes tiles in fast SRAM and gives exact results.

Is DoLa a latency technique?

No. It contrasts final and earlier layers to improve factuality, at a small extra cost.

Why is the distillation KL term multiplied by T²?

Softening with temperature T shrinks its gradients by about 1/T²; the factor keeps the soft- and hard-label terms balanced.

What is “dark knowledge”?

The relative probabilities a teacher gives wrong classes (a “2” looks more like a “7” than a cat), revealed by softening with temperature.

Feature-based distillation with a narrower student: what is needed?

A small learned projection mapping student features to the teacher's width before the MSE/cosine loss.

Why doesn't relation-based distillation need matching widths?

Relations such as an n × n similarity matrix have the same shape whatever the model width.

Black-box vs white-box LLM distillation?

Black-box fine-tunes on teacher-generated text (only outputs needed). White-box matches full next-token distributions and needs logits and the same tokenizer.

Forward or reverse KL: which is mode-seeking?

Reverse KL(student ‖ teacher): the student focuses on the teacher's main modes. Forward KL is mean-seeking.

Why is LoRA's B matrix initialised to zero?

So ΔW = BA = 0 at the start, and fine-tuning begins exactly from the pretrained model.

How many trainable parameters does LoRA add for a 4096 × 4096 matrix with r = 16?

r·(d + k) = 16 × 8192 = 131,072, about 0.8% of 16.8M.

Deployment & operations
Does batching make each token faster?

No. It raises throughput; per-request latency can rise slightly. For LLMs, continuous batching beats dynamic (time-window) batching.

At inference, which parallelism lowers latency, and which only adds throughput?

Tensor parallelism lowers latency for big models; replicas (“data parallel”) only add throughput.

What signal should LLM autoscaling use?

Queue depth or KV-cache usage, not CPU; and plan for cold starts while weights load.

Shadow vs canary deployment?

Shadow sends real traffic to the new model without showing its answers; canary shows it to a growing share of users, gated on metrics, with rollback.

Why run the Gradio UI and the model in separate pods?

Otherwise every UI replica loads its own model copy on a GPU. Separate pods let cheap CPU UI pods and GPU model pods scale independently.

Deployment vs Service in Kubernetes?

A Deployment keeps N replica pods running and handles rolling updates; a Service gives them a stable address and load-balances between them.

Why does an LLM pod need a readiness probe?

Loading the model takes minutes; the probe keeps traffic away until the pod can answer.

Blue-green vs canary?

Blue-green switches all traffic between two full environments at once (instant rollback, 2× capacity); canary shifts a small share first and grows it gradually.

Why trigger CI on pull requests rather than only on push to main?

So problems are caught before the change is merged; on push to main, a bad change is already in.

Where does CML put its evaluation report?

As a comment on the pull request or commit; emails come from GitHub notifications.

What is a quality gate in ML CI?

A check that fails the build if the new model is worse than production (e.g. score below baseline or latency above the SLO).

Why not commit trained models to git?

They bloat the repository and large files are rejected; use DVC, Git LFS, a model registry or the Hugging Face Hub.

What does continuous training (CT) add to CI/CD?

Automatic retraining when new data arrives or drift is detected, because models degrade even when code doesn't change.

What stage closes the MLOps loop?

Monitoring: what it finds (drift, quality drops) feeds back into data and retraining.

SSE or WebSockets for streaming LLM tokens?

Usually Server-Sent Events: one-way, plain HTTP, used by the OpenAI API. WebSockets suit two-way connections such as voice.

Does async code batch requests?

No. It lets one worker serve other requests while waiting on I/O; GPU batching is the model server's job.

Vertical vs horizontal scaling for LLMs?

Vertical (bigger GPU) when the model doesn't fit; horizontal (more replicas) for throughput and resilience.

Data drift vs concept drift?

Data drift: the inputs change. Concept drift: the right answer for the same input changes, which needs labels or a judge to detect.

What does the KS statistic measure?

The largest gap between two samples' cumulative distributions of one numeric feature.

Is MLflow a production monitoring tool?

No, it is for experiment tracking and the model registry; use Prometheus/Grafana, Evidently or Langfuse for monitoring.

Interpretability vs explainability?

Interpretability: the model is understandable by design (linear models, small trees). Explainability: post-hoc explanations of black boxes (SHAP, LIME).

Agents & tool use
How many MCP clients does a host connected to three servers run?

Three: each client keeps a 1:1 connection with one server.

stdio vs Streamable HTTP?

stdio: the server runs locally as a subprocess of the host. Streamable HTTP: the server runs remotely over the network. Neither limits the number of servers.

Does the LLM call the MCP server directly?

No. It proposes a tool call; the host and client execute it via tools/call and return the result as context.

Tools, resources, prompts: who controls each?

Tools: the model. Resources: the application. Prompts: the user.

Why does MCP reduce integration work?

M apps and N systems need M + N MCP implementations instead of M × N custom connectors.

What is tool poisoning?

A malicious MCP server hiding instructions for the LLM inside its tool descriptions.

What is an agent's short-term memory?

The context window: system prompt, tools, retrieved context and the reasoning/action history for the current interaction.

Episodic, semantic, procedural: which stores “the user prefers short answers”?

Semantic (a fact about the user). Episodic stores what happened; procedural stores how to do things.

Hot-path vs background memory writing?

Hot path: the agent saves memories during the conversation (immediate, slower turns). Background: a job extracts them afterwards (fast chat, delayed memory).

What is memory consolidation?

Turning many episodes into a few durable semantic facts, often with an LLM reflection step.

Which three signals does Generative Agents use to retrieve memories?

Recency, importance and relevance, combined in a weighted sum.

What is memory poisoning?

A prompt injection that gets saved to long-term memory and keeps affecting future sessions.

License, citation and sources

© 2026 Dimitris Gkoumas. Text and figures are licensed under Creative Commons Attribution 4.0 (CC BY 4.0): you may share and adapt them for any purpose, as long as you give credit and link to this page. All figures are original illustrations drawn for these notes. Last updated: 1 November 2026.

How to cite

Gkoumas, D. (2026). AI Under the Hood: Study Notes from ML Foundations to Agents. https://gkoumasd.github.io/ai-under-the-hood.html

@misc{gkoumas2026aiunderthehood,
  author = {Gkoumas, Dimitris},
  title  = {AI Under the Hood: Study Notes from ML Foundations to Agents},
  year   = {2026},
  url    = {https://gkoumasd.github.io/ai-under-the-hood.html}
}

Sources and further reading

These notes summarise and build on the following work; specific credits also appear next to the relevant sections.

  • Papers: Hinton, Vinyals & Dean (2015), Distilling the Knowledge in a Neural Network; Romero et al. (2015), FitNets; Park et al. (2019), Relational Knowledge Distillation; Vaswani et al. (2017), Attention Is All You Need; Hu et al. (2021), LoRA; Loshchilov & Hutter (2019), Decoupled Weight Decay Regularization; Power et al. (2022), Grokking; Dai et al. (2024), DeepSeekMoE; Leviathan et al. (2023) and Chen et al. (2023) on speculative decoding; Madaan et al. (2023), Self-Refine; Huang et al. (2023), LLMs Cannot Self-Correct Reasoning Yet; Snell et al. (2024), Scaling LLM Test-Time Compute Optimally; Chuang et al. (2023), DoLa; Faysse et al. (2024), ColPali; Sumers et al. (2023), Cognitive Architectures for Language Agents; Park et al. (2023), Generative Agents; Gou et al. (2021), Knowledge Distillation: A Survey.
  • Guides and blogs: Hugging Face, How to Generate Text, Scaling Test-Time Compute with Open Models, The Ultra-Scale Playbook and the Transformers documentation on LLM inference optimisation; Pinecone, Faiss: The Missing Manual; Google Cloud, MLOps: Continuous Delivery and Automation Pipelines in Machine Learning; DataCamp, CI/CD for Machine Learning; the Model Context Protocol specification (modelcontextprotocol.io).